use crate::util;
pub use crate::passes::BoxedResolver;

use rustc::lint;
use rustc::session::early_error;
use rustc::session::config::{self, Input, ErrorOutputType};
use rustc::session::{DiagnosticOutput, Session};
use rustc::util::common::ErrorReported;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_data_structures::OnDrop;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
use rustc_errors::registry::Registry;
use rustc_parse::new_parser_from_source_str;
use rustc::ty;
use std::path::PathBuf;
use std::result;
use std::sync::{Arc, Mutex};
use syntax::ast::{self, MetaItemKind};
use syntax::token;
use syntax::source_map::{FileName, FileLoader, SourceMap};
use syntax::sess::ParseSess;
use syntax_pos::edition;

pub type Result<T> = result::Result<T, ErrorReported>;

/// Represents a compiler session.
/// Can be used run `rustc_interface` queries.
/// Created by passing `Config` to `run_compiler`.
pub struct Compiler {
    pub(crate) sess: Lrc<Session>,
    codegen_backend: Lrc<Box<dyn CodegenBackend>>,
    source_map: Lrc<SourceMap>,
    pub(crate) input: Input,
    pub(crate) input_path: Option<PathBuf>,
    pub(crate) output_dir: Option<PathBuf>,
    pub(crate) output_file: Option<PathBuf>,
    pub(crate) crate_name: Option<String>,
    pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
    pub(crate) override_queries:
        Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)>,
}

impl Compiler {
    pub fn session(&self) -> &Lrc<Session> {
        &self.sess
    }
    pub fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
        &self.codegen_backend
    }
    pub fn source_map(&self) -> &Lrc<SourceMap> {
        &self.source_map
    }
    pub fn input(&self) -> &Input {
        &self.input
    }
    pub fn output_dir(&self) -> &Option<PathBuf> {
        &self.output_dir
    }
    pub fn output_file(&self) -> &Option<PathBuf> {
        &self.output_file
    }
}

/// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
    syntax::with_default_globals(move || {
        let cfg = cfgspecs.into_iter().map(|s| {
            let sess = ParseSess::with_silent_emitter();
            let filename = FileName::cfg_spec_source_code(&s);
            let mut parser = new_parser_from_source_str(&sess, filename, s.to_string());

            macro_rules! error {($reason: expr) => {
                early_error(ErrorOutputType::default(),
                            &format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s));
            }}

            match &mut parser.parse_meta_item() {
                Ok(meta_item) if parser.token == token::Eof => {
                    if meta_item.path.segments.len() != 1 {
                        error!("argument key must be an identifier");
                    }
                    match &meta_item.kind {
                        MetaItemKind::List(..) => {
                            error!(r#"expected `key` or `key="value"`"#);
                        }
                        MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
                            error!("argument value must be a string");
                        }
                        MetaItemKind::NameValue(..) | MetaItemKind::Word => {
                            let ident = meta_item.ident().expect("multi-segment cfg key");
                            return (ident.name, meta_item.value_str());
                        }
                    }
                }
                Ok(..) => {}
                Err(err) => err.cancel(),
            }

            error!(r#"expected `key` or `key="value"`"#);
        }).collect::<ast::CrateConfig>();
        cfg.into_iter().map(|(a, b)| {
            (a.to_string(), b.map(|b| b.to_string()))
        }).collect()
    })
}

/// The compiler configuration
pub struct Config {
    /// Command line options
    pub opts: config::Options,

    /// cfg! configuration in addition to the default ones
    pub crate_cfg: FxHashSet<(String, Option<String>)>,

    pub input: Input,
    pub input_path: Option<PathBuf>,
    pub output_dir: Option<PathBuf>,
    pub output_file: Option<PathBuf>,
    pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
    pub diagnostic_output: DiagnosticOutput,

    /// Set to capture stderr output during compiler execution
    pub stderr: Option<Arc<Mutex<Vec<u8>>>>,

    pub crate_name: Option<String>,
    pub lint_caps: FxHashMap<lint::LintId, lint::Level>,

    /// This is a callback from the driver that is called when we're registering lints;
    /// it is called during plugin registration when we have the LintStore in a non-shared state.
    ///
    /// Note that if you find a Some here you probably want to call that function in the new
    /// function being registered.
    pub register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,

    /// This is a callback from the driver that is called just after we have populated
    /// the list of queries.
    ///
    /// The second parameter is local providers and the third parameter is external providers.
    pub override_queries:
        Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)>,

    /// Registry of diagnostics codes.
    pub registry: Registry,
}

pub fn run_compiler_in_existing_thread_pool<R>(
    config: Config,
    f: impl FnOnce(&Compiler) -> R,
) -> R {
    let registry = &config.registry;
    let (sess, codegen_backend, source_map) = util::create_session(
        config.opts,
        config.crate_cfg,
        config.diagnostic_output,
        config.file_loader,
        config.input_path.clone(),
        config.lint_caps,
        registry.clone(),
    );

    let compiler = Compiler {
        sess,
        codegen_backend,
        source_map,
        input: config.input,
        input_path: config.input_path,
        output_dir: config.output_dir,
        output_file: config.output_file,
        crate_name: config.crate_name,
        register_lints: config.register_lints,
        override_queries: config.override_queries,
    };

    let _sess_abort_error = OnDrop(|| {
        compiler.sess.diagnostic().print_error_count(registry);
    });

    f(&compiler)
}

pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
    let stderr = config.stderr.take();
    util::spawn_thread_pool(
        config.opts.edition,
        config.opts.debugging_opts.threads,
        &stderr,
        || run_compiler_in_existing_thread_pool(config, f),
    )
}

pub fn default_thread_pool<R: Send>(edition: edition::Edition, f: impl FnOnce() -> R + Send) -> R {
    // the 1 here is duplicating code in config.opts.debugging_opts.threads
    // which also defaults to 1; it ultimately doesn't matter as the default
    // isn't threaded, and just ignores this parameter
    util::spawn_thread_pool(edition, 1, &None, f)
}
