use clap::{Parser};
use cpp_out::{Configuration, Error, FileType};
use std::path::PathBuf;
use tool_helper::exit_with_error;

#[derive(Parser)]
#[clap(about = "Output a file content or stdin to a c++ header/source file", long_about = None)]
struct CommandLine {
    #[clap(value_parser)]
    input_file: Option<PathBuf>,

    #[clap(short='n', long="name")]
    data_name: String,

    #[clap(short='o')]
    output_file: PathBuf,
}

fn configurate(cmd: &mut CommandLine) -> Result<Configuration, Error> {
    let file_name = tool_helper::get_file_name_from_path_buf(&cmd.output_file, "output")?;
    let extension = tool_helper::os_str_to_string(Error::ok_or_new(cmd.output_file.extension(), ||"File extension required for output".to_owned())?, "extension")?.to_ascii_lowercase();
    let file_type = Error::ok_or_new({
        match extension.as_ref() {
            "h"   => Some(FileType::CHeader),
            "hpp" => Some(FileType::CPPHeader),
            "c"   => Some(FileType::CSource),
            "cpp" => Some(FileType::CPPSource),
            _     => None
        }
    }, ||format!("{} unkown file extension", extension))?;

    Ok(Configuration{file_name, data_name: std::mem::take(&mut cmd.data_name), line_feed: cpp_out::LineFeed::Windows, file_type})
}

fn run_main(mut cmd: CommandLine) -> Result<(), Error> {
    let cfg    = configurate(&mut cmd)?;
    let input  = tool_helper::open_input(&cmd.input_file)?;
    let output = tool_helper::open_output(&Some(cmd.output_file))?;

    return cpp_out::convert(cfg, input, output);
}

fn main() {
    match CommandLine::try_parse() {
        Ok(cmd)    => {
            if let Err(error) = run_main(cmd) {
                exit_with_error(error)
            }
        }, 
        Err(error) => println!("{}", error)
    }
}