#![feature(rustc_private)]

extern crate rustc_driver;
extern crate rustc_log;
extern crate rustc_session;

extern crate rustc_errors;
use std::env;
use std::error::Error;
use std::fs::{self, File};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::str::FromStr;

use mdbook_driver::MDBook;
use mdbook_driver::book::{BookItem, Chapter};
use mdbook_driver::config::Config;
use mdbook_summary::parse_summary;
use rustc_errors::codes::DIAGNOSTICS;

enum OutputFormat {
    HTML,
    Markdown,
    Unknown(String),
}

impl OutputFormat {
    fn from(format: &str) -> OutputFormat {
        match &*format.to_lowercase() {
            "html" => OutputFormat::HTML,
            "markdown" => OutputFormat::Markdown,
            s => OutputFormat::Unknown(s.to_owned()),
        }
    }
}

/// Output an HTML page for the errors in `err_map` to `output_path`.
fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
    let mut output_file = File::create(output_path)?;

    write!(output_file, "# Rust Compiler Error Index\n")?;

    for (err_code, description) in DIAGNOSTICS.iter() {
        write!(output_file, "## {}\n{}\n", err_code, description)?
    }

    Ok(())
}

// By default, mdbook doesn't consider code blocks as Rust ones contrary to rustdoc so we have
// to manually add `rust` attribute whenever needed.
fn add_rust_attribute_on_codeblock(explanation: &str) -> String {
    // Very hacky way to add the rust attribute on all code blocks.
    let mut skip = true;
    explanation.split("\n```").fold(String::new(), |mut acc, part| {
        if !acc.is_empty() {
            acc.push_str("\n```");
        }
        if !skip {
            if let Some(attrs) = part.split('\n').next() {
                if !attrs.contains("rust")
                    && (attrs.is_empty()
                        || attrs.contains("compile_fail")
                        || attrs.contains("ignore")
                        || attrs.contains("edition"))
                {
                    if !attrs.is_empty() {
                        acc.push_str("rust,");
                    } else {
                        acc.push_str("rust");
                    }
                }
            }
        }
        skip = !skip;
        acc.push_str(part);
        acc
    })
}

fn render_html(output_path: &Path) -> Result<(), Box<dyn Error>> {
    let mut introduction = format!(
        "# Rust error codes index

This page lists all the error codes emitted by the Rust compiler.

"
    );

    let err_codes = DIAGNOSTICS;
    let mut chapters = Vec::with_capacity(err_codes.len());

    for (err_code, explanation) in err_codes.iter() {
        introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));

        let content = add_rust_attribute_on_codeblock(explanation);
        chapters.push(BookItem::Chapter(Chapter {
            name: err_code.to_string(),
            content: format!("# Error code {}\n\n{}\n", err_code, content),
            number: None,
            sub_items: Vec::new(),
            // We generate it into the `error_codes` folder.
            path: Some(PathBuf::from(&format!("{}.html", err_code))),
            source_path: None,
            parent_names: Vec::new(),
        }));
    }

    let mut config = Config::from_str(include_str!("book_config.toml"))?;
    config.build.build_dir = output_path.join("error_codes").to_path_buf();
    let mut book = MDBook::load_with_config_and_summary(
        env!("CARGO_MANIFEST_DIR"),
        config,
        parse_summary("")?,
    )?;
    let chapter = Chapter {
        name: "Rust error codes index".to_owned(),
        content: introduction,
        number: None,
        sub_items: chapters,
        // Very important: this file is named as `error-index.html` and not `index.html`!
        path: Some(PathBuf::from("error-index.html")),
        source_path: None,
        parent_names: Vec::new(),
    };
    book.book.items.push(BookItem::Chapter(chapter));
    book.build()?;

    // The error-index used to be generated manually (without mdbook), and the
    // index was located at the top level. Now that it is generated with
    // mdbook, error-index.html has moved to error_codes/error-index.html.
    // This adds a redirect so that old links go to the new location.
    //
    // We can't put this content into another file, otherwise `mdbook` will also put it into the
    // output directory, making a duplicate.
    fs::write(
        output_path.join("error-index.html"),
        r#"<!DOCTYPE html>
<html>
    <head>
        <title>Rust error codes index - Error codes index</title>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="Book listing all Rust error codes">
        <script src="error_codes/redirect.js"></script>
    </head>
    <body>
        <div>If you are not automatically redirected to the error code index, please <a id="index-link" href="./error_codes/error-index.html">here</a>.
    </body>
</html>"#,
    )?;

    Ok(())
}

fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box<dyn Error>> {
    match format {
        OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
        OutputFormat::HTML => render_html(dst),
        OutputFormat::Markdown => render_markdown(dst),
    }
}

fn parse_args() -> (OutputFormat, PathBuf) {
    let mut args = env::args().skip(1);
    let format = args.next();
    let dst = args.next();
    let format = format.map(|a| OutputFormat::from(&a)).unwrap_or(OutputFormat::from("html"));
    let dst = dst.map(PathBuf::from).unwrap_or_else(|| match format {
        OutputFormat::HTML => PathBuf::from("doc"),
        OutputFormat::Markdown => PathBuf::from("doc/error-index.md"),
        OutputFormat::Unknown(..) => PathBuf::from("<nul>"),
    });
    (format, dst)
}

fn main() {
    let handler =
        rustc_session::EarlyDiagCtxt::new(rustc_session::config::ErrorOutputType::default());
    rustc_driver::init_logger(&handler, rustc_log::LoggerConfig::from_env("RUST_LOG"));
    let (format, dst) = parse_args();
    let result = main_with_result(format, &dst);
    if let Err(e) = result {
        panic!("{:?}", e);
    }
}
