use std::collections::BTreeMap;
use std::fmt;
use std::path::PathBuf;

use errors;
use getopts;
use rustc::lint::Level;
use rustc::session;
use rustc::session::config::{CrateType, parse_crate_types_from_list};
use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options,
                             get_cmd_lint_options, ExternEntry};
use rustc::session::search_paths::SearchPath;
use rustc_driver;
use rustc_target::spec::TargetTriple;
use syntax::edition::{Edition, DEFAULT_EDITION};

use crate::core::new_handler;
use crate::externalfiles::ExternalHtml;
use crate::html;
use crate::html::{static_files};
use crate::html::markdown::{IdMap};
use crate::opts;
use crate::passes::{self, DefaultPassOption};
use crate::theme;

/// Configuration options for rustdoc.
#[derive(Clone)]
pub struct Options {
    // Basic options / Options passed directly to rustc

    /// The crate root or Markdown file to load.
    pub input: PathBuf,
    /// The name of the crate being documented.
    pub crate_name: Option<String>,
    /// Whether or not this is a proc-macro crate
    pub proc_macro_crate: bool,
    /// How to format errors and warnings.
    pub error_format: ErrorOutputType,
    /// Library search paths to hand to the compiler.
    pub libs: Vec<SearchPath>,
    /// Library search paths strings to hand to the compiler.
    pub lib_strs: Vec<String>,
    /// The list of external crates to link against.
    pub externs: Externs,
    /// The list of external crates strings to link against.
    pub extern_strs: Vec<String>,
    /// List of `cfg` flags to hand to the compiler. Always includes `rustdoc`.
    pub cfgs: Vec<String>,
    /// Codegen options to hand to the compiler.
    pub codegen_options: CodegenOptions,
    /// Codegen options strings to hand to the compiler.
    pub codegen_options_strs: Vec<String>,
    /// Debugging (`-Z`) options to pass to the compiler.
    pub debugging_options: DebuggingOptions,
    /// The target used to compile the crate against.
    pub target: Option<TargetTriple>,
    /// Edition used when reading the crate. Defaults to "2015". Also used by default when
    /// compiling doctests from the crate.
    pub edition: Edition,
    /// The path to the sysroot. Used during the compilation process.
    pub maybe_sysroot: Option<PathBuf>,
    /// Lint information passed over the command-line.
    pub lint_opts: Vec<(String, Level)>,
    /// Whether to ask rustc to describe the lints it knows. Practically speaking, this will not be
    /// used, since we abort if we have no input file, but it's included for completeness.
    pub describe_lints: bool,
    /// What level to cap lints at.
    pub lint_cap: Option<Level>,

    // Options specific to running doctests

    /// Whether we should run doctests instead of generating docs.
    pub should_test: bool,
    /// List of arguments to pass to the test harness, if running tests.
    pub test_args: Vec<String>,
    /// Optional path to persist the doctest executables to, defaults to a
    /// temporary directory if not set.
    pub persist_doctests: Option<PathBuf>,

    // Options that affect the documentation process

    /// The selected default set of passes to use.
    ///
    /// Be aware: This option can come both from the CLI and from crate attributes!
    pub default_passes: DefaultPassOption,
    /// Any passes manually selected by the user.
    ///
    /// Be aware: This option can come both from the CLI and from crate attributes!
    pub manual_passes: Vec<String>,
    /// Whether to display warnings during doc generation or while gathering doctests. By default,
    /// all non-rustdoc-specific lints are allowed when generating docs.
    pub display_warnings: bool,
    /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items
    /// with and without documentation.
    pub show_coverage: bool,

    // Options that alter generated documentation pages

    /// Crate version to note on the sidebar of generated docs.
    pub crate_version: Option<String>,
    /// Collected options specific to outputting final pages.
    pub render_options: RenderOptions,
}

impl fmt::Debug for Options {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        struct FmtExterns<'a>(&'a Externs);

        impl<'a> fmt::Debug for FmtExterns<'a> {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.debug_map()
                    .entries(self.0.iter())
                    .finish()
            }
        }

        f.debug_struct("Options")
            .field("input", &self.input)
            .field("crate_name", &self.crate_name)
            .field("proc_macro_crate", &self.proc_macro_crate)
            .field("error_format", &self.error_format)
            .field("libs", &self.libs)
            .field("externs", &FmtExterns(&self.externs))
            .field("cfgs", &self.cfgs)
            .field("codegen_options", &"...")
            .field("debugging_options", &"...")
            .field("target", &self.target)
            .field("edition", &self.edition)
            .field("maybe_sysroot", &self.maybe_sysroot)
            .field("lint_opts", &self.lint_opts)
            .field("describe_lints", &self.describe_lints)
            .field("lint_cap", &self.lint_cap)
            .field("should_test", &self.should_test)
            .field("test_args", &self.test_args)
            .field("persist_doctests", &self.persist_doctests)
            .field("default_passes", &self.default_passes)
            .field("manual_passes", &self.manual_passes)
            .field("display_warnings", &self.display_warnings)
            .field("show_coverage", &self.show_coverage)
            .field("crate_version", &self.crate_version)
            .field("render_options", &self.render_options)
            .finish()
    }
}

/// Configuration options for the HTML page-creation process.
#[derive(Clone, Debug)]
pub struct RenderOptions {
    /// Output directory to generate docs into. Defaults to `doc`.
    pub output: PathBuf,
    /// External files to insert into generated pages.
    pub external_html: ExternalHtml,
    /// A pre-populated `IdMap` with the default headings and any headings added by Markdown files
    /// processed by `external_html`.
    pub id_map: IdMap,
    /// If present, playground URL to use in the "Run" button added to code samples.
    ///
    /// Be aware: This option can come both from the CLI and from crate attributes!
    pub playground_url: Option<String>,
    /// Whether to sort modules alphabetically on a module page instead of using declaration order.
    /// `true` by default.
    //
    // FIXME(misdreavus): the flag name is `--sort-modules-by-appearance` but the meaning is
    // inverted once read.
    pub sort_modules_alphabetically: bool,
    /// List of themes to extend the docs with. Original argument name is included to assist in
    /// displaying errors if it fails a theme check.
    pub themes: Vec<PathBuf>,
    /// If present, CSS file that contains rules to add to the default CSS.
    pub extension_css: Option<PathBuf>,
    /// A map of crate names to the URL to use instead of querying the crate's `html_root_url`.
    pub extern_html_root_urls: BTreeMap<String, String>,
    /// If present, suffix added to CSS/JavaScript files when referencing them in generated pages.
    pub resource_suffix: String,
    /// Whether to run the static CSS/JavaScript through a minifier when outputting them. `true` by
    /// default.
    //
    // FIXME(misdreavus): the flag name is `--disable-minification` but the meaning is inverted
    // once read.
    pub enable_minification: bool,
    /// Whether to create an index page in the root of the output directory. If this is true but
    /// `enable_index_page` is None, generate a static listing of crates instead.
    pub enable_index_page: bool,
    /// A file to use as the index page at the root of the output directory. Overrides
    /// `enable_index_page` to be true if set.
    pub index_page: Option<PathBuf>,
    /// An optional path to use as the location of static files. If not set, uses combinations of
    /// `../` to reach the documentation root.
    pub static_root_path: Option<String>,

    // Options specific to reading standalone Markdown files

    /// Whether to generate a table of contents on the output file when reading a standalone
    /// Markdown file.
    pub markdown_no_toc: bool,
    /// Additional CSS files to link in pages generated from standalone Markdown files.
    pub markdown_css: Vec<String>,
    /// If present, playground URL to use in the "Run" button added to code samples generated from
    /// standalone Markdown files. If not present, `playground_url` is used.
    pub markdown_playground_url: Option<String>,
    /// If false, the `select` element to have search filtering by crates on rendered docs
    /// won't be generated.
    pub generate_search_filter: bool,
    /// Option (disabled by default) to generate files used by RLS and some other tools.
    pub generate_redirect_pages: bool,
}

impl Options {
    /// Parses the given command-line for options. If an error message or other early-return has
    /// been printed, returns `Err` with the exit code.
    pub fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> {
        // Check for unstable options.
        nightly_options::check_nightly_options(&matches, &opts());

        if matches.opt_present("h") || matches.opt_present("help") {
            crate::usage("rustdoc");
            return Err(0);
        } else if matches.opt_present("version") {
            rustc_driver::version("rustdoc", &matches);
            return Err(0);
        }

        if matches.opt_strs("passes") == ["list"] {
            println!("Available passes for running rustdoc:");
            for pass in passes::PASSES {
                println!("{:>20} - {}", pass.name, pass.description);
            }
            println!("\nDefault passes for rustdoc:");
            for pass in passes::DEFAULT_PASSES {
                println!("{:>20}", pass.name);
            }
            println!("\nPasses run with `--document-private-items`:");
            for pass in passes::DEFAULT_PRIVATE_PASSES {
                println!("{:>20}", pass.name);
            }

            if nightly_options::is_nightly_build() {
                println!("\nPasses run with `--show-coverage`:");
                for pass in passes::DEFAULT_COVERAGE_PASSES {
                    println!("{:>20}", pass.name);
                }
                println!("\nPasses run with `--show-coverage --document-private-items`:");
                for pass in passes::PRIVATE_COVERAGE_PASSES {
                    println!("{:>20}", pass.name);
                }
            }

            return Err(0);
        }

        let color = session::config::parse_color(&matches);
        let (json_rendered, _artifacts) = session::config::parse_json(&matches);
        let error_format = session::config::parse_error_format(&matches, color, json_rendered);

        let codegen_options = build_codegen_options(matches, error_format);
        let debugging_options = build_debugging_options(matches, error_format);

        let diag = new_handler(error_format,
                               None,
                               debugging_options.treat_err_as_bug,
                               debugging_options.ui_testing);

        // check for deprecated options
        check_deprecated_options(&matches, &diag);

        let to_check = matches.opt_strs("theme-checker");
        if !to_check.is_empty() {
            let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes());
            let mut errors = 0;

            println!("rustdoc: [theme-checker] Starting tests!");
            for theme_file in to_check.iter() {
                print!(" - Checking \"{}\"...", theme_file);
                let (success, differences) = theme::test_theme_against(theme_file, &paths, &diag);
                if !differences.is_empty() || !success {
                    println!(" FAILED");
                    errors += 1;
                    if !differences.is_empty() {
                        println!("{}", differences.join("\n"));
                    }
                } else {
                    println!(" OK");
                }
            }
            if errors != 0 {
                return Err(1);
            }
            return Err(0);
        }

        if matches.free.is_empty() {
            diag.struct_err("missing file operand").emit();
            return Err(1);
        }
        if matches.free.len() > 1 {
            diag.struct_err("too many file operands").emit();
            return Err(1);
        }
        let input = PathBuf::from(&matches.free[0]);

        let libs = matches.opt_strs("L").iter()
            .map(|s| SearchPath::from_cli_opt(s, error_format))
            .collect();
        let externs = match parse_externs(&matches) {
            Ok(ex) => ex,
            Err(err) => {
                diag.struct_err(&err).emit();
                return Err(1);
            }
        };
        let extern_html_root_urls = match parse_extern_html_roots(&matches) {
            Ok(ex) => ex,
            Err(err) => {
                diag.struct_err(err).emit();
                return Err(1);
            }
        };

        let test_args = matches.opt_strs("test-args");
        let test_args: Vec<String> = test_args.iter()
                                              .flat_map(|s| s.split_whitespace())
                                              .map(|s| s.to_string())
                                              .collect();

        let should_test = matches.opt_present("test");

        let output = matches.opt_str("o")
                            .map(|s| PathBuf::from(&s))
                            .unwrap_or_else(|| PathBuf::from("doc"));
        let mut cfgs = matches.opt_strs("cfg");
        cfgs.push("rustdoc".to_string());
        if should_test {
            cfgs.push("doctest".to_string());
        }

        let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));

        if let Some(ref p) = extension_css {
            if !p.is_file() {
                diag.struct_err("option --extend-css argument must be a file").emit();
                return Err(1);
            }
        }

        let mut themes = Vec::new();
        if matches.opt_present("themes") {
            let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes());

            for (theme_file, theme_s) in matches.opt_strs("themes")
                                                .iter()
                                                .map(|s| (PathBuf::from(&s), s.to_owned())) {
                if !theme_file.is_file() {
                    diag.struct_err("option --themes arguments must all be files").emit();
                    return Err(1);
                }
                let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag);
                if !success || !ret.is_empty() {
                    diag.struct_err(&format!("invalid theme: \"{}\"", theme_s))
                        .help("check what's wrong with the --theme-checker option")
                        .emit();
                    return Err(1);
                }
                themes.push(theme_file);
            }
        }

        let edition = if let Some(e) = matches.opt_str("edition") {
            match e.parse() {
                Ok(e) => e,
                Err(_) => {
                    diag.struct_err("could not parse edition").emit();
                    return Err(1);
                }
            }
        } else {
            DEFAULT_EDITION
        };

        let mut id_map = html::markdown::IdMap::new();
        id_map.populate(html::render::initial_ids());
        let external_html = match ExternalHtml::load(
                &matches.opt_strs("html-in-header"),
                &matches.opt_strs("html-before-content"),
                &matches.opt_strs("html-after-content"),
                &matches.opt_strs("markdown-before-content"),
                &matches.opt_strs("markdown-after-content"),
                &diag, &mut id_map, edition, &None) {
            Some(eh) => eh,
            None => return Err(3),
        };

        match matches.opt_str("r").as_ref().map(|s| &**s) {
            Some("rust") | None => {}
            Some(s) => {
                diag.struct_err(&format!("unknown input format: {}", s)).emit();
                return Err(1);
            }
        }

        match matches.opt_str("w").as_ref().map(|s| &**s) {
            Some("html") | None => {}
            Some(s) => {
                diag.struct_err(&format!("unknown output format: {}", s)).emit();
                return Err(1);
            }
        }

        let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s));
        if let Some(ref index_page) = index_page {
            if !index_page.is_file() {
                diag.struct_err("option `--index-page` argument must be a file").emit();
                return Err(1);
            }
        }

        let target = matches.opt_str("target").map(|target| {
            if target.ends_with(".json") {
                TargetTriple::TargetPath(PathBuf::from(target))
            } else {
                TargetTriple::TargetTriple(target)
            }
        });

        let show_coverage = matches.opt_present("show-coverage");
        let document_private = matches.opt_present("document-private-items");

        let default_passes = if matches.opt_present("no-defaults") {
            passes::DefaultPassOption::None
        } else if show_coverage && document_private {
            passes::DefaultPassOption::PrivateCoverage
        } else if show_coverage {
            passes::DefaultPassOption::Coverage
        } else if document_private {
            passes::DefaultPassOption::Private
        } else {
            passes::DefaultPassOption::Default
        };
        let manual_passes = matches.opt_strs("passes");

        let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) {
            Ok(types) => types,
            Err(e) =>{
                diag.struct_err(&format!("unknown crate type: {}", e)).emit();
                return Err(1);
            }
        };

        let crate_name = matches.opt_str("crate-name");
        let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
        let playground_url = matches.opt_str("playground-url");
        let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
        let display_warnings = matches.opt_present("display-warnings");
        let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
        let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
        let enable_minification = !matches.opt_present("disable-minification");
        let markdown_no_toc = matches.opt_present("markdown-no-toc");
        let markdown_css = matches.opt_strs("markdown-css");
        let markdown_playground_url = matches.opt_str("markdown-playground-url");
        let crate_version = matches.opt_str("crate-version");
        let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some();
        let static_root_path = matches.opt_str("static-root-path");
        let generate_search_filter = !matches.opt_present("disable-per-crate-search");
        let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from);
        let generate_redirect_pages = matches.opt_present("generate-redirect-pages");
        let codegen_options_strs = matches.opt_strs("C");
        let lib_strs = matches.opt_strs("L");
        let extern_strs = matches.opt_strs("extern");

        let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);

        Ok(Options {
            input,
            crate_name,
            proc_macro_crate,
            error_format,
            libs,
            lib_strs,
            externs,
            extern_strs,
            cfgs,
            codegen_options,
            codegen_options_strs,
            debugging_options,
            target,
            edition,
            maybe_sysroot,
            lint_opts,
            describe_lints,
            lint_cap,
            should_test,
            test_args,
            default_passes,
            manual_passes,
            display_warnings,
            show_coverage,
            crate_version,
            persist_doctests,
            render_options: RenderOptions {
                output,
                external_html,
                id_map,
                playground_url,
                sort_modules_alphabetically,
                themes,
                extension_css,
                extern_html_root_urls,
                resource_suffix,
                enable_minification,
                enable_index_page,
                index_page,
                static_root_path,
                markdown_no_toc,
                markdown_css,
                markdown_playground_url,
                generate_search_filter,
                generate_redirect_pages,
            }
        })
    }

    /// Returns `true` if the file given as `self.input` is a Markdown file.
    pub fn markdown_input(&self) -> bool {
        self.input.extension()
            .map_or(false, |e| e == "md" || e == "markdown")
    }
}

/// Prints deprecation warnings for deprecated options
fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler) {
    let deprecated_flags = [
       "input-format",
       "output-format",
       "no-defaults",
       "passes",
    ];

    for flag in deprecated_flags.iter() {
        if matches.opt_present(flag) {
            let mut err = diag.struct_warn(&format!("the '{}' flag is considered deprecated",
                                                    flag));
            err.warn("please see https://github.com/rust-lang/rust/issues/44136");

            if *flag == "no-defaults" {
                err.help("you may want to use --document-private-items");
            }

            err.emit();
        }
    }

    let removed_flags = [
        "plugins",
        "plugin-path",
    ];

    for &flag in removed_flags.iter() {
        if matches.opt_present(flag) {
            diag.struct_warn(&format!("the '{}' flag no longer functions", flag))
                .warn("see CVE-2018-1000622")
                .emit();
        }
    }
}

/// Extracts `--extern-html-root-url` arguments from `matches` and returns a map of crate names to
/// the given URLs. If an `--extern-html-root-url` argument was ill-formed, returns an error
/// describing the issue.
fn parse_extern_html_roots(
    matches: &getopts::Matches,
) -> Result<BTreeMap<String, String>, &'static str> {
    let mut externs = BTreeMap::new();
    for arg in &matches.opt_strs("extern-html-root-url") {
        let mut parts = arg.splitn(2, '=');
        let name = parts.next().ok_or("--extern-html-root-url must not be empty")?;
        let url = parts.next().ok_or("--extern-html-root-url must be of the form name=url")?;
        externs.insert(name.to_string(), url.to_string());
    }

    Ok(externs)
}

/// Extracts `--extern CRATE=PATH` arguments from `matches` and
/// returns a map mapping crate names to their paths or else an
/// error message.
// FIXME(eddyb) This shouldn't be duplicated with `rustc::session`.
fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> {
    let mut externs: BTreeMap<_, ExternEntry> = BTreeMap::new();
    for arg in &matches.opt_strs("extern") {
        let mut parts = arg.splitn(2, '=');
        let name = parts.next().ok_or("--extern value must not be empty".to_string())?;
        let location = parts.next().map(|s| s.to_string());
        if location.is_none() && !nightly_options::is_unstable_enabled(matches) {
            return Err("the `-Z unstable-options` flag must also be passed to \
                        enable `--extern crate_name` without `=path`".to_string());
        }
        let name = name.to_string();
        // For Rustdoc purposes, we can treat all externs as public
        externs.entry(name)
            .or_default()
            .locations.insert(location.clone());
    }
    Ok(Externs::new(externs))
}
