use anyhow::{format_err, Result};

use io::Error as IoError;
use thiserror::Error;

use rustfmt_nightly as rustfmt;

use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::{self, stdout, Read, Write};
use std::path::{Path, PathBuf};
use std::str::FromStr;

use getopts::{Matches, Options};

use crate::rustfmt::{
    load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName,
    FormatReportFormatterBuilder, Input, Session, Verbosity,
};

fn main() {
    env_logger::Builder::from_env("RUSTFMT_LOG").init();
    let opts = make_opts();

    let exit_code = match execute(&opts) {
        Ok(code) => code,
        Err(e) => {
            eprintln!("{:#}", e);
            1
        }
    };
    // Make sure standard output is flushed before we exit.
    std::io::stdout().flush().unwrap();

    // Exit with given exit code.
    //
    // NOTE: this immediately terminates the process without doing any cleanup,
    // so make sure to finish all necessary cleanup before this is called.
    std::process::exit(exit_code);
}

/// Rustfmt operations.
enum Operation {
    /// Format files and their child modules.
    Format {
        files: Vec<PathBuf>,
        minimal_config_path: Option<String>,
    },
    /// Print the help message.
    Help(HelpOp),
    /// Print version information
    Version,
    /// Output default config to a file, or stdout if None
    ConfigOutputDefault { path: Option<String> },
    /// Output current config (as if formatting to a file) to stdout
    ConfigOutputCurrent { path: Option<String> },
    /// No file specified, read from stdin
    Stdin { input: String },
}

/// Rustfmt operations errors.
#[derive(Error, Debug)]
pub enum OperationError {
    /// An unknown help topic was requested.
    #[error("Unknown help topic: `{0}`.")]
    UnknownHelpTopic(String),
    /// An unknown print-config option was requested.
    #[error("Unknown print-config option: `{0}`.")]
    UnknownPrintConfigTopic(String),
    /// Attempt to generate a minimal config from standard input.
    #[error("The `--print-config=minimal` option doesn't work with standard input.")]
    MinimalPathWithStdin,
    /// An io error during reading or writing.
    #[error("{0}")]
    IoError(IoError),
    /// Attempt to use --emit with a mode which is not currently
    /// supported with standard input.
    #[error("Emit mode {0} not supported with standard output.")]
    StdinBadEmit(EmitMode),
}

impl From<IoError> for OperationError {
    fn from(e: IoError) -> OperationError {
        OperationError::IoError(e)
    }
}

/// Arguments to `--help`
enum HelpOp {
    None,
    Config,
    FileLines,
}

fn make_opts() -> Options {
    let mut opts = Options::new();

    opts.optflag(
        "",
        "check",
        "Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits \
         with 1 and prints a diff if formatting is required.",
    );
    let is_nightly = is_nightly();
    let emit_opts = if is_nightly {
        "[files|stdout|coverage|checkstyle|json]"
    } else {
        "[files|stdout]"
    };
    opts.optopt("", "emit", "What data to emit and how", emit_opts);
    opts.optflag("", "backup", "Backup any modified files.");
    opts.optopt(
        "",
        "config-path",
        "Recursively searches the given path for the rustfmt.toml config file. If not \
         found reverts to the input file path",
        "[Path for the configuration file]",
    );
    opts.optopt("", "edition", "Rust edition to use", "[2015|2018|2021]");
    opts.optopt(
        "",
        "color",
        "Use colored output (if supported)",
        "[always|never|auto]",
    );
    opts.optopt(
        "",
        "print-config",
        "Dumps a default or minimal config to PATH. A minimal config is the \
         subset of the current config file used for formatting the current program. \
         `current` writes to stdout current config as if formatting the file at PATH.",
        "[default|minimal|current] PATH",
    );
    opts.optflag(
        "l",
        "files-with-diff",
        "Prints the names of mismatched files that were formatted. Prints the names of \
         files that would be formatted when used with `--check` mode. ",
    );
    opts.optmulti(
        "",
        "config",
        "Set options from command line. These settings take priority over .rustfmt.toml",
        "[key1=val1,key2=val2...]",
    );

    if is_nightly {
        opts.optflag(
            "",
            "unstable-features",
            "Enables unstable features. Only available on nightly channel.",
        );
        opts.optopt(
            "",
            "file-lines",
            "Format specified line ranges. Run with `--help=file-lines` for \
             more detail (unstable).",
            "JSON",
        );
        opts.optflag(
            "",
            "error-on-unformatted",
            "Error if unable to get comments or string literals within max_width, \
             or they are left with trailing whitespaces (unstable).",
        );
        opts.optflag(
            "",
            "skip-children",
            "Don't reformat child modules (unstable).",
        );
    }

    opts.optflag("v", "verbose", "Print verbose output");
    opts.optflag("q", "quiet", "Print less output");
    opts.optflag("V", "version", "Show version information");
    let help_topics = if is_nightly {
        "`config` or `file-lines`"
    } else {
        "`config`"
    };
    let mut help_topic_msg = "Show this message or help about a specific topic: ".to_owned();
    help_topic_msg.push_str(help_topics);

    opts.optflagopt("h", "help", &help_topic_msg, "=TOPIC");

    opts
}

fn is_nightly() -> bool {
    option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev")
}

// Returned i32 is an exit code
fn execute(opts: &Options) -> Result<i32> {
    let matches = opts.parse(env::args().skip(1))?;
    let options = GetOptsOptions::from_matches(&matches)?;

    match determine_operation(&matches)? {
        Operation::Help(HelpOp::None) => {
            print_usage_to_stdout(opts, "");
            Ok(0)
        }
        Operation::Help(HelpOp::Config) => {
            Config::print_docs(&mut stdout(), options.unstable_features);
            Ok(0)
        }
        Operation::Help(HelpOp::FileLines) => {
            print_help_file_lines();
            Ok(0)
        }
        Operation::Version => {
            print_version();
            Ok(0)
        }
        Operation::ConfigOutputDefault { path } => {
            let toml = Config::default().all_options().to_toml()?;
            if let Some(path) = path {
                let mut file = File::create(path)?;
                file.write_all(toml.as_bytes())?;
            } else {
                io::stdout().write_all(toml.as_bytes())?;
            }
            Ok(0)
        }
        Operation::ConfigOutputCurrent { path } => {
            let path = match path {
                Some(path) => path,
                None => return Err(format_err!("PATH required for `--print-config current`")),
            };

            let file = PathBuf::from(path);
            let file = file.canonicalize().unwrap_or(file);

            let (config, _) = load_config(Some(file.parent().unwrap()), Some(options))?;
            let toml = config.all_options().to_toml()?;
            io::stdout().write_all(toml.as_bytes())?;

            Ok(0)
        }
        Operation::Stdin { input } => format_string(input, options),
        Operation::Format {
            files,
            minimal_config_path,
        } => format(files, minimal_config_path, &options),
    }
}

fn format_string(input: String, options: GetOptsOptions) -> Result<i32> {
    // try to read config from local directory
    let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?;

    if options.check {
        config.set().emit_mode(EmitMode::Diff);
    } else {
        match options.emit_mode {
            // Emit modes which work with standard input
            // None means default, which is Stdout.
            None | Some(EmitMode::Stdout) | Some(EmitMode::Checkstyle) | Some(EmitMode::Json) => {}
            Some(emit_mode) => {
                return Err(OperationError::StdinBadEmit(emit_mode).into());
            }
        }
        config
            .set()
            .emit_mode(options.emit_mode.unwrap_or(EmitMode::Stdout));
    }
    config.set().verbose(Verbosity::Quiet);

    // parse file_lines
    config.set().file_lines(options.file_lines);
    for f in config.file_lines().files() {
        match *f {
            FileName::Stdin => {}
            _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f),
        }
    }

    let out = &mut stdout();
    let mut session = Session::new(config, Some(out));
    format_and_emit_report(&mut session, Input::Text(input));

    let exit_code = if session.has_operational_errors() || session.has_parsing_errors() {
        1
    } else {
        0
    };
    Ok(exit_code)
}

fn format(
    files: Vec<PathBuf>,
    minimal_config_path: Option<String>,
    options: &GetOptsOptions,
) -> Result<i32> {
    options.verify_file_lines(&files);
    let (config, config_path) = load_config(None, Some(options.clone()))?;

    if config.verbose() == Verbosity::Verbose {
        if let Some(path) = config_path.as_ref() {
            println!("Using rustfmt config file {}", path.display());
        }
    }

    let out = &mut stdout();
    let mut session = Session::new(config, Some(out));

    for file in files {
        if !file.exists() {
            eprintln!("Error: file `{}` does not exist", file.to_str().unwrap());
            session.add_operational_error();
        } else if file.is_dir() {
            eprintln!("Error: `{}` is a directory", file.to_str().unwrap());
            session.add_operational_error();
        } else {
            // Check the file directory if the config-path could not be read or not provided
            if config_path.is_none() {
                let (local_config, config_path) =
                    load_config(Some(file.parent().unwrap()), Some(options.clone()))?;
                if local_config.verbose() == Verbosity::Verbose {
                    if let Some(path) = config_path {
                        println!(
                            "Using rustfmt config file {} for {}",
                            path.display(),
                            file.display()
                        );
                    }
                }

                session.override_config(local_config, |sess| {
                    format_and_emit_report(sess, Input::File(file))
                });
            } else {
                format_and_emit_report(&mut session, Input::File(file));
            }
        }
    }

    // If we were given a path via dump-minimal-config, output any options
    // that were used during formatting as TOML.
    if let Some(path) = minimal_config_path {
        let mut file = File::create(path)?;
        let toml = session.config.used_options().to_toml()?;
        file.write_all(toml.as_bytes())?;
    }

    let exit_code = if session.has_operational_errors()
        || session.has_parsing_errors()
        || ((session.has_diff() || session.has_check_errors()) && options.check)
    {
        1
    } else {
        0
    };
    Ok(exit_code)
}

fn format_and_emit_report<T: Write>(session: &mut Session<'_, T>, input: Input) {
    match session.format(input) {
        Ok(report) => {
            if report.has_warnings() {
                eprintln!(
                    "{}",
                    FormatReportFormatterBuilder::new(&report)
                        .enable_colors(should_print_with_colors(session))
                        .build()
                );
            }
        }
        Err(msg) => {
            eprintln!("Error writing files: {}", msg);
            session.add_operational_error();
        }
    }
}

fn should_print_with_colors<T: Write>(session: &mut Session<'_, T>) -> bool {
    match term::stderr() {
        Some(ref t)
            if session.config.color().use_colored_tty()
                && t.supports_color()
                && t.supports_attr(term::Attr::Bold) =>
        {
            true
        }
        _ => false,
    }
}

fn print_usage_to_stdout(opts: &Options, reason: &str) {
    let sep = if reason.is_empty() {
        String::new()
    } else {
        format!("{}\n\n", reason)
    };
    let msg = format!(
        "{}Format Rust code\n\nusage: rustfmt [options] <file>...",
        sep
    );
    println!("{}", opts.usage(&msg));
}

fn print_help_file_lines() {
    println!(
        "If you want to restrict reformatting to specific sets of lines, you can
use the `--file-lines` option. Its argument is a JSON array of objects
with `file` and `range` properties, where `file` is a file name, and
`range` is an array representing a range of lines like `[7,13]`. Ranges
are 1-based and inclusive of both end points. Specifying an empty array
will result in no files being formatted. For example,

```
rustfmt --file-lines '[
    {{\"file\":\"src/lib.rs\",\"range\":[7,13]}},
    {{\"file\":\"src/lib.rs\",\"range\":[21,29]}},
    {{\"file\":\"src/foo.rs\",\"range\":[10,11]}},
    {{\"file\":\"src/foo.rs\",\"range\":[15,15]}}]'
```

would format lines `7-13` and `21-29` of `src/lib.rs`, and lines `10-11`,
and `15` of `src/foo.rs`. No other files would be formatted, even if they
are included as out of line modules from `src/lib.rs`."
    );
}

fn print_version() {
    let version_info = format!(
        "{}-{}",
        option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"),
        include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
    );

    println!("rustfmt {}", version_info);
}

fn determine_operation(matches: &Matches) -> Result<Operation, OperationError> {
    if matches.opt_present("h") {
        let topic = matches.opt_str("h");
        if topic == None {
            return Ok(Operation::Help(HelpOp::None));
        } else if topic == Some("config".to_owned()) {
            return Ok(Operation::Help(HelpOp::Config));
        } else if topic == Some("file-lines".to_owned()) && is_nightly() {
            return Ok(Operation::Help(HelpOp::FileLines));
        } else {
            return Err(OperationError::UnknownHelpTopic(topic.unwrap()));
        }
    }
    let mut free_matches = matches.free.iter();

    let mut minimal_config_path = None;
    if let Some(kind) = matches.opt_str("print-config") {
        let path = free_matches.next().cloned();
        match kind.as_str() {
            "default" => return Ok(Operation::ConfigOutputDefault { path }),
            "current" => return Ok(Operation::ConfigOutputCurrent { path }),
            "minimal" => {
                minimal_config_path = path;
                if minimal_config_path.is_none() {
                    eprintln!("WARNING: PATH required for `--print-config minimal`.");
                }
            }
            _ => {
                return Err(OperationError::UnknownPrintConfigTopic(kind));
            }
        }
    }

    if matches.opt_present("version") {
        return Ok(Operation::Version);
    }

    let files: Vec<_> = free_matches
        .map(|s| {
            let p = PathBuf::from(s);
            // we will do comparison later, so here tries to canonicalize first
            // to get the expected behavior.
            p.canonicalize().unwrap_or(p)
        })
        .collect();

    // if no file argument is supplied, read from stdin
    if files.is_empty() {
        if minimal_config_path.is_some() {
            return Err(OperationError::MinimalPathWithStdin);
        }
        let mut buffer = String::new();
        io::stdin().read_to_string(&mut buffer)?;

        return Ok(Operation::Stdin { input: buffer });
    }

    Ok(Operation::Format {
        files,
        minimal_config_path,
    })
}

const STABLE_EMIT_MODES: [EmitMode; 3] = [EmitMode::Files, EmitMode::Stdout, EmitMode::Diff];

/// Parsed command line options.
#[derive(Clone, Debug, Default)]
struct GetOptsOptions {
    skip_children: Option<bool>,
    quiet: bool,
    verbose: bool,
    config_path: Option<PathBuf>,
    inline_config: HashMap<String, String>,
    emit_mode: Option<EmitMode>,
    backup: bool,
    check: bool,
    edition: Option<Edition>,
    color: Option<Color>,
    file_lines: FileLines, // Default is all lines in all files.
    unstable_features: bool,
    error_on_unformatted: Option<bool>,
    print_misformatted_file_names: bool,
}

impl GetOptsOptions {
    pub fn from_matches(matches: &Matches) -> Result<GetOptsOptions> {
        let mut options = GetOptsOptions::default();
        options.verbose = matches.opt_present("verbose");
        options.quiet = matches.opt_present("quiet");
        if options.verbose && options.quiet {
            return Err(format_err!("Can't use both `--verbose` and `--quiet`"));
        }

        let rust_nightly = is_nightly();

        if rust_nightly {
            options.unstable_features = matches.opt_present("unstable-features");

            if options.unstable_features {
                if matches.opt_present("skip-children") {
                    options.skip_children = Some(true);
                }
                if matches.opt_present("error-on-unformatted") {
                    options.error_on_unformatted = Some(true);
                }
                if let Some(ref file_lines) = matches.opt_str("file-lines") {
                    options.file_lines = file_lines.parse()?;
                }
            } else {
                let mut unstable_options = vec![];
                if matches.opt_present("skip-children") {
                    unstable_options.push("`--skip-children`");
                }
                if matches.opt_present("error-on-unformatted") {
                    unstable_options.push("`--error-on-unformatted`");
                }
                if matches.opt_present("file-lines") {
                    unstable_options.push("`--file-lines`");
                }
                if !unstable_options.is_empty() {
                    let s = if unstable_options.len() == 1 { "" } else { "s" };
                    return Err(format_err!(
                        "Unstable option{} ({}) used without `--unstable-features`",
                        s,
                        unstable_options.join(", "),
                    ));
                }
            }
        }

        options.config_path = matches.opt_str("config-path").map(PathBuf::from);

        options.inline_config = matches
            .opt_strs("config")
            .iter()
            .flat_map(|config| config.split(','))
            .map(
                |key_val| match key_val.char_indices().find(|(_, ch)| *ch == '=') {
                    Some((middle, _)) => {
                        let (key, val) = (&key_val[..middle], &key_val[middle + 1..]);
                        if !Config::is_valid_key_val(key, val) {
                            Err(format_err!("invalid key=val pair: `{}`", key_val))
                        } else {
                            Ok((key.to_string(), val.to_string()))
                        }
                    }

                    None => Err(format_err!(
                        "--config expects comma-separated list of key=val pairs, found `{}`",
                        key_val
                    )),
                },
            )
            .collect::<Result<HashMap<_, _>, _>>()?;

        options.check = matches.opt_present("check");
        if let Some(ref emit_str) = matches.opt_str("emit") {
            if options.check {
                return Err(format_err!("Invalid to use `--emit` and `--check`"));
            }

            options.emit_mode = Some(emit_mode_from_emit_str(emit_str)?);
        }

        if let Some(ref edition_str) = matches.opt_str("edition") {
            options.edition = Some(edition_from_edition_str(edition_str)?);
        }

        if matches.opt_present("backup") {
            options.backup = true;
        }

        if matches.opt_present("files-with-diff") {
            options.print_misformatted_file_names = true;
        }

        if !rust_nightly {
            if let Some(ref emit_mode) = options.emit_mode {
                if !STABLE_EMIT_MODES.contains(emit_mode) {
                    return Err(format_err!(
                        "Invalid value for `--emit` - using an unstable \
                         value without `--unstable-features`",
                    ));
                }
            }
        }

        if let Some(ref color) = matches.opt_str("color") {
            match Color::from_str(color) {
                Ok(color) => options.color = Some(color),
                _ => return Err(format_err!("Invalid color: {}", color)),
            }
        }

        Ok(options)
    }

    fn verify_file_lines(&self, files: &[PathBuf]) {
        for f in self.file_lines.files() {
            match *f {
                FileName::Real(ref f) if files.contains(f) => {}
                FileName::Real(_) => {
                    eprintln!("Warning: Extra file listed in file_lines option '{}'", f)
                }
                FileName::Stdin => eprintln!("Warning: Not a file '{}'", f),
            }
        }
    }
}

impl CliOptions for GetOptsOptions {
    fn apply_to(self, config: &mut Config) {
        if self.verbose {
            config.set().verbose(Verbosity::Verbose);
        } else if self.quiet {
            config.set().verbose(Verbosity::Quiet);
        } else {
            config.set().verbose(Verbosity::Normal);
        }
        config.set().file_lines(self.file_lines);
        config.set().unstable_features(self.unstable_features);
        if let Some(skip_children) = self.skip_children {
            config.set().skip_children(skip_children);
        }
        if let Some(error_on_unformatted) = self.error_on_unformatted {
            config.set().error_on_unformatted(error_on_unformatted);
        }
        if let Some(edition) = self.edition {
            config.set().edition(edition);
        }
        if self.check {
            config.set().emit_mode(EmitMode::Diff);
        } else if let Some(emit_mode) = self.emit_mode {
            config.set().emit_mode(emit_mode);
        }
        if self.backup {
            config.set().make_backup(true);
        }
        if let Some(color) = self.color {
            config.set().color(color);
        }
        if self.print_misformatted_file_names {
            config.set().print_misformatted_file_names(true);
        }

        for (key, val) in self.inline_config {
            config.override_value(&key, &val);
        }
    }

    fn config_path(&self) -> Option<&Path> {
        self.config_path.as_deref()
    }
}

fn edition_from_edition_str(edition_str: &str) -> Result<Edition> {
    match edition_str {
        "2015" => Ok(Edition::Edition2015),
        "2018" => Ok(Edition::Edition2018),
        "2021" => Ok(Edition::Edition2021),
        "2024" => Ok(Edition::Edition2024),
        _ => Err(format_err!("Invalid value for `--edition`")),
    }
}

fn emit_mode_from_emit_str(emit_str: &str) -> Result<EmitMode> {
    match emit_str {
        "files" => Ok(EmitMode::Files),
        "stdout" => Ok(EmitMode::Stdout),
        "coverage" => Ok(EmitMode::Coverage),
        "checkstyle" => Ok(EmitMode::Checkstyle),
        "json" => Ok(EmitMode::Json),
        _ => Err(format_err!("Invalid value for `--emit`")),
    }
}
