use std::io::Error;
use std::io::ErrorKind;
use std::path::PathBuf;
use structopt::StructOpt;

use preserves_schema::compiler::{ExternalModule, CompilerConfig, compile, expand_inputs};

#[derive(Clone, StructOpt, Debug)]
struct CommandLine {
    #[structopt(short, long)]
    output_dir: PathBuf,

    #[structopt(short, long)]
    prefix: String,

    #[structopt(long)]
    support_crate: Option<String>,

    #[structopt(long)]
    module: Vec<String>,

    #[structopt(long)]
    xref: Vec<String>,

    input_glob: Vec<String>,
}

fn main() -> Result<(), Error> {
    let args = CommandLine::from_args();
    let mut config = CompilerConfig::new(args.output_dir, args.prefix);
    for alias in args.module {
        let (modulepath_str, target) = {
            let pieces: Vec<&str> = alias.split('=').collect();
            if pieces.len() != 2 {
                return Err(Error::new(ErrorKind::InvalidData,
                                      format!("Invalid module alias: {:?}", alias)));
            }
            (pieces[0], pieces[1])
        };
        let modulepath: Vec<String> = modulepath_str.split('.').map(str::to_owned).collect();
        config.add_external_module(ExternalModule::new(modulepath, target));
    }
    if let Some(c) = args.support_crate {
        config.support_crate = c;
    }
    config.load_schemas_and_bundles(
        &expand_inputs(&args.input_glob)?,
        &expand_inputs(&args.xref)?)?;
    compile(&config)
}
