// This file is part of AllMyToes.
//
// AllMyToes is free software: you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// AllMyToes is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with AllMyToes.
// If not, see <https://www.gnu.org/licenses/>.
//
//mod allmytoes;

use allmytoes::{AMTConfiguration, Thumb, ThumbSize, AMT};
use clap::Parser;
use std::path::Path;
#[macro_use]
extern crate log;

#[derive(Parser)]
#[clap(author, version)]
#[clap(about = "Provides paths to image thumbnails and creates them if necessary, using the thumbnail database standardized by freedesktop.org", long_about = None)]
struct Cli {
    #[clap(short, long, value_parser = parse_toe_size, help="Thumbnail size (one of {n,l,x,xx}). Default: l (large)")]
    size: Option<ThumbSize>,

    #[clap(
        long,
        short,
        help = "Show extensive information, including meta data from the thumbnail"
    )]
    extensive: bool,

    #[clap(short, long, help = "Provider configuration file")]
    provider_config_file: Option<String>,

    #[clap(
        short = 'P',
        long,
        help = "Force use of in-built provider configuration"
    )]
    inbuilt_provider_config: bool,

    #[clap(
        short = 'F',
        long,
        help = "Force to return exactly the requested thumb size"
    )]
    force_size: bool,

    #[clap(long, help = "Keep temp dir when using provider")]
    leak: bool,

    #[clap(value_parser, help = "File for which a thumbnail shall be returned")]
    file: String,

    #[clap(long, help = "Force creation of thumbs no matter if they exist")]
    force_creation: bool,
}

fn parse_toe_size(s: &str) -> Result<ThumbSize, String> {
    match s {
        "n" => Ok(ThumbSize::Normal),
        "l" => Ok(ThumbSize::Large),
        "x" => Ok(ThumbSize::XLarge),
        "xx" => Ok(ThumbSize::XXLarge),
        _ => Err(String::from("Invalid size specification.")),
    }
}

fn build_extensive_information_list(thumb: &Thumb) -> Vec<(String, String)> {
    let static_values = vec![
        (String::from("Thumb path"), String::from(&thumb.path)),
        (String::from("Thumb hash"), String::from(&thumb.hash)),
        //(String::from("Canonical source path"), String::from(thumb.foo)),
    ];
    let mut meta_values = thumb
        .meta
        .iter()
        .map(|t| (format!(":{}", t.0), String::from(t.1)))
        .collect::<Vec<(String, String)>>();
    meta_values.sort_by(|t1, t2| t1.0.cmp(&t2.0));
    [static_values, meta_values].concat()
}

fn main() {
    let cli = Cli::parse();
    flexi_logger::Logger::try_with_env_or_str("warn")
        .unwrap()
        .start()
        .unwrap();

    let size = match cli.size {
        Some(v) => v,
        None => ThumbSize::Large,
    };

    //AMT is mutable to allow “lazy loading” of the configuration later on
    let amt = AMT::new(&AMTConfiguration {
        force_creation: cli.force_creation,
        return_smallest_feasible: !cli.force_size,
        leak: cli.leak,
        custom_provider_spec_file: cli.provider_config_file,
        force_inbuilt_provider_spec: cli.inbuilt_provider_config,
    });

    match amt.get(Path::new(&cli.file), size) {
        Ok(thumb) => {
            if cli.extensive {
                for (k, v) in build_extensive_information_list(&thumb) {
                    println!("{k}: {v}")
                }
            } else {
                println!("{}", thumb.path)
            }
        }
        Err(e) => {
            error!("{}", e.msg());
            std::process::exit(e.error_code());
        }
    }
}
