use std::cell::RefCell;
use std::collections::BTreeMap;
use std::fmt::{self, Write as _};
use std::io;
use std::path::{Path, PathBuf};
use std::sync::mpsc::{Receiver, channel};

use askama::Template;
use rustc_ast::join_path_syms;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::edition::Edition;
use rustc_span::{BytePos, FileName, Symbol, sym};
use tracing::info;

use super::print_item::{full_path, print_item, print_item_path};
use super::sidebar::{ModuleLike, Sidebar, print_sidebar, sidebar_module_like};
use super::{AllTypes, LinkFromSrc, StylePath, collect_spans_and_sources, scrape_examples_help};
use crate::clean::types::ExternalLocation;
use crate::clean::utils::has_doc_flag;
use crate::clean::{self, ExternalCrate};
use crate::config::{ModuleSorting, RenderOptions, ShouldMerge};
use crate::docfs::{DocFS, PathError};
use crate::error::Error;
use crate::formats::FormatRenderer;
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
use crate::html::escape::Escape;
use crate::html::macro_expansion::ExpandedCode;
use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary};
use crate::html::render::span_map::Span;
use crate::html::render::write_shared::write_shared;
use crate::html::url_parts_builder::UrlPartsBuilder;
use crate::html::{layout, sources, static_files};
use crate::scrape_examples::AllCallLocations;
use crate::{DOC_RUST_LANG_ORG_VERSION, try_err};

/// Major driving force in all rustdoc rendering. This contains information
/// about where in the tree-like hierarchy rendering is occurring and controls
/// how the current page is being rendered.
///
/// It is intended that this context is a lightweight object which can be fairly
/// easily cloned because it is cloned per work-job (about once per item in the
/// rustdoc tree).
pub(crate) struct Context<'tcx> {
    /// Current hierarchy of components leading down to what's currently being
    /// rendered
    pub(crate) current: Vec<Symbol>,
    /// The current destination folder of where HTML artifacts should be placed.
    /// This changes as the context descends into the module hierarchy.
    pub(crate) dst: PathBuf,
    /// Tracks section IDs for `Deref` targets so they match in both the main
    /// body and the sidebar.
    pub(super) deref_id_map: RefCell<DefIdMap<String>>,
    /// The map used to ensure all generated 'id=' attributes are unique.
    pub(super) id_map: RefCell<IdMap>,
    /// Shared mutable state.
    ///
    /// Issue for improving the situation: [#82381][]
    ///
    /// [#82381]: https://github.com/rust-lang/rust/issues/82381
    pub(crate) shared: SharedContext<'tcx>,
    /// Collection of all types with notable traits referenced in the current module.
    pub(crate) types_with_notable_traits: RefCell<FxIndexSet<clean::Type>>,
    /// Contains information that needs to be saved and reset after rendering an item which is
    /// not a module.
    pub(crate) info: ContextInfo,
}

/// This struct contains the information that needs to be reset between each
/// [`FormatRenderer::item`] call.
///
/// When we enter a new module, we set these values for the whole module but they might be updated
/// in each child item (especially if it's a module). So to prevent these changes to impact other
/// items rendering in the same module, we need to reset them to the module's set values.
#[derive(Clone, Copy)]
pub(crate) struct ContextInfo {
    /// A flag, which when `true`, will render pages which redirect to the
    /// real location of an item. This is used to allow external links to
    /// publicly reused items to redirect to the right location.
    pub(super) render_redirect_pages: bool,
    /// This flag indicates whether source links should be generated or not. If
    /// the source files are present in the html rendering, then this will be
    /// `true`.
    pub(crate) include_sources: bool,
    /// Field used during rendering, to know if we're inside an inlined item.
    pub(crate) is_inside_inlined_module: bool,
}

impl ContextInfo {
    fn new(include_sources: bool) -> Self {
        Self { render_redirect_pages: false, include_sources, is_inside_inlined_module: false }
    }
}

/// Shared mutable state used in [`Context`] and elsewhere.
pub(crate) struct SharedContext<'tcx> {
    pub(crate) tcx: TyCtxt<'tcx>,
    /// The path to the crate root source minus the file name.
    /// Used for simplifying paths to the highlighted source code files.
    pub(crate) src_root: PathBuf,
    /// This describes the layout of each page, and is not modified after
    /// creation of the context (contains info like the favicon and added html).
    pub(crate) layout: layout::Layout,
    /// The local file sources we've emitted and their respective url-paths.
    pub(crate) local_sources: FxIndexMap<PathBuf, String>,
    /// Show the memory layout of types in the docs.
    pub(super) show_type_layout: bool,
    /// The base-URL of the issue tracker for when an item has been tagged with
    /// an issue number.
    pub(super) issue_tracker_base_url: Option<String>,
    /// The directories that have already been created in this doc run. Used to reduce the number
    /// of spurious `create_dir_all` calls.
    created_dirs: RefCell<FxHashSet<PathBuf>>,
    /// This flag indicates whether listings of modules (in the side bar and documentation itself)
    /// should be ordered alphabetically or in order of appearance (in the source code).
    pub(super) module_sorting: ModuleSorting,
    /// Additional CSS files to be added to the generated docs.
    pub(crate) style_files: Vec<StylePath>,
    /// Suffix to add on resource files (if suffix is "-v2" then "search-index.js" becomes
    /// "search-index-v2.js").
    pub(crate) resource_suffix: String,
    /// Optional path string to be used to load static files on output pages. If not set, uses
    /// combinations of `../` to reach the documentation root.
    pub(crate) static_root_path: Option<String>,
    /// The fs handle we are working with.
    pub(crate) fs: DocFS,
    pub(super) codes: ErrorCodes,
    pub(super) playground: Option<markdown::Playground>,
    all: RefCell<AllTypes>,
    /// Storage for the errors produced while generating documentation so they
    /// can be printed together at the end.
    errors: Receiver<String>,
    /// `None` by default, depends on the `generate-redirect-map` option flag. If this field is set
    /// to `Some(...)`, it'll store redirections and then generate a JSON file at the top level of
    /// the crate.
    redirections: Option<RefCell<FxHashMap<String, String>>>,

    /// Correspondence map used to link types used in the source code pages to allow to click on
    /// links to jump to the type's definition.
    pub(crate) span_correspondence_map: FxHashMap<Span, LinkFromSrc>,
    pub(crate) expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
    /// The [`Cache`] used during rendering.
    pub(crate) cache: Cache,
    pub(crate) call_locations: AllCallLocations,
    /// Controls whether we read / write to cci files in the doc root. Defaults read=true,
    /// write=true
    should_merge: ShouldMerge,
}

impl SharedContext<'_> {
    pub(crate) fn ensure_dir(&self, dst: &Path) -> Result<(), Error> {
        let mut dirs = self.created_dirs.borrow_mut();
        if !dirs.contains(dst) {
            try_err!(self.fs.create_dir_all(dst), dst);
            dirs.insert(dst.to_path_buf());
        }

        Ok(())
    }

    pub(crate) fn edition(&self) -> Edition {
        self.tcx.sess.edition()
    }
}

impl<'tcx> Context<'tcx> {
    pub(crate) fn tcx(&self) -> TyCtxt<'tcx> {
        self.shared.tcx
    }

    pub(crate) fn cache(&self) -> &Cache {
        &self.shared.cache
    }

    pub(super) fn sess(&self) -> &'tcx Session {
        self.shared.tcx.sess
    }

    pub(super) fn derive_id<S: AsRef<str> + ToString>(&self, id: S) -> String {
        self.id_map.borrow_mut().derive(id)
    }

    /// String representation of how to get back to the root path of the 'doc/'
    /// folder in terms of a relative URL.
    pub(super) fn root_path(&self) -> String {
        "../".repeat(self.current.len())
    }

    fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
        let mut render_redirect_pages = self.info.render_redirect_pages;
        // If the item is stripped but inlined, links won't point to the item so no need to generate
        // a file for it.
        if it.is_stripped()
            && let Some(def_id) = it.def_id()
            && def_id.is_local()
            && (self.info.is_inside_inlined_module
                || self.shared.cache.inlined_items.contains(&def_id))
        {
            // For now we're forced to generate a redirect page for stripped items until
            // `record_extern_fqn` correctly points to external items.
            render_redirect_pages = true;
        }
        let mut title = String::new();
        if !is_module {
            title.push_str(it.name.unwrap().as_str());
        }
        let short_title;
        let short_title = if is_module {
            let module_name = self.current.last().unwrap();
            short_title = if it.is_crate() {
                format!("Crate {module_name}")
            } else {
                format!("Module {module_name}")
            };
            &short_title[..]
        } else {
            it.name.as_ref().unwrap().as_str()
        };
        if !it.is_fake_item() {
            if !is_module {
                title.push_str(" in ");
            }
            // No need to include the namespace for primitive types and keywords
            title.push_str(&join_path_syms(&self.current));
        };
        title.push_str(" - Rust");
        let tyname = it.type_();
        let desc = plain_text_summary(&it.doc_value(), &it.link_names(self.cache()));
        let desc = if !desc.is_empty() {
            desc
        } else if it.is_crate() {
            format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate)
        } else {
            format!(
                "API documentation for the Rust `{name}` {tyname} in crate `{krate}`.",
                name = it.name.as_ref().unwrap(),
                krate = self.shared.layout.krate,
            )
        };
        let name;
        let tyname_s = if it.is_crate() {
            name = format!("{tyname} crate");
            name.as_str()
        } else {
            tyname.as_str()
        };

        if !render_redirect_pages {
            let content = print_item(self, it);
            let page = layout::Page {
                css_class: tyname_s,
                root_path: &self.root_path(),
                static_root_path: self.shared.static_root_path.as_deref(),
                title: &title,
                short_title,
                description: &desc,
                resource_suffix: &self.shared.resource_suffix,
                rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo),
            };
            layout::render(
                &self.shared.layout,
                &page,
                fmt::from_fn(|f| print_sidebar(self, it, f)),
                content,
                &self.shared.style_files,
            )
        } else {
            if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id())
                && (self.current.len() + 1 != names.len()
                    || self.current.iter().zip(names.iter()).any(|(a, b)| a != b))
            {
                // We checked that the redirection isn't pointing to the current file,
                // preventing an infinite redirection loop in the generated
                // documentation.

                let path = fmt::from_fn(|f| {
                    for name in &names[..names.len() - 1] {
                        write!(f, "{name}/")?;
                    }
                    write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
                });
                match self.shared.redirections {
                    Some(ref redirections) => {
                        let mut current_path = String::new();
                        for name in &self.current {
                            current_path.push_str(name.as_str());
                            current_path.push('/');
                        }
                        let _ = write!(
                            current_path,
                            "{}",
                            print_item_path(ty, names.last().unwrap().as_str())
                        );
                        redirections.borrow_mut().insert(current_path, path.to_string());
                    }
                    None => {
                        return layout::redirect(&format!("{root}{path}", root = self.root_path()));
                    }
                }
            }
            String::new()
        }
    }

    /// Construct a map of items shown in the sidebar to a plain-text summary of their docs.
    fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<String>> {
        // BTreeMap instead of HashMap to get a sorted output
        let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new();
        let mut inserted: FxHashMap<ItemType, FxHashSet<Symbol>> = FxHashMap::default();

        for item in &m.items {
            if item.is_stripped() {
                continue;
            }

            let short = item.type_();
            let myname = match item.name {
                None => continue,
                Some(s) => s,
            };
            if inserted.entry(short).or_default().insert(myname) {
                let short = short.to_string();
                let myname = myname.to_string();
                map.entry(short).or_default().push(myname);
            }
        }

        match self.shared.module_sorting {
            ModuleSorting::Alphabetical => {
                for items in map.values_mut() {
                    items.sort();
                }
            }
            ModuleSorting::DeclarationOrder => {}
        }
        map
    }

    /// Generates a url appropriate for an `href` attribute back to the source of
    /// this item.
    ///
    /// The url generated, when clicked, will redirect the browser back to the
    /// original source code.
    ///
    /// If `None` is returned, then a source link couldn't be generated. This
    /// may happen, for example, with externally inlined items where the source
    /// of their crate documentation isn't known.
    pub(super) fn src_href(&self, item: &clean::Item) -> Option<String> {
        self.href_from_span(item.span(self.tcx())?, true)
    }

    pub(crate) fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option<String> {
        let mut root = self.root_path();
        let mut path: String;
        let cnum = span.cnum(self.sess());

        // We can safely ignore synthetic `SourceFile`s.
        let file = match span.filename(self.sess()) {
            FileName::Real(ref path) => path.local_path_if_available().to_path_buf(),
            _ => return None,
        };
        let file = &file;

        let krate_sym;
        let (krate, path) = if cnum == LOCAL_CRATE {
            if let Some(path) = self.shared.local_sources.get(file) {
                (self.shared.layout.krate.as_str(), path)
            } else {
                return None;
            }
        } else {
            let (krate, src_root) = match *self.cache().extern_locations.get(&cnum)? {
                ExternalLocation::Local => {
                    let e = ExternalCrate { crate_num: cnum };
                    (e.name(self.tcx()), e.src_root(self.tcx()))
                }
                ExternalLocation::Remote(ref s) => {
                    root = s.to_string();
                    let e = ExternalCrate { crate_num: cnum };
                    (e.name(self.tcx()), e.src_root(self.tcx()))
                }
                ExternalLocation::Unknown => return None,
            };

            let href = RefCell::new(PathBuf::new());
            sources::clean_path(
                &src_root,
                file,
                |component| {
                    href.borrow_mut().push(component);
                },
                || {
                    href.borrow_mut().pop();
                },
            );

            path = href.into_inner().to_string_lossy().into_owned();

            if let Some(c) = path.as_bytes().last()
                && *c != b'/'
            {
                path.push('/');
            }

            let mut fname = file.file_name().expect("source has no filename").to_os_string();
            fname.push(".html");
            path.push_str(&fname.to_string_lossy());
            krate_sym = krate;
            (krate_sym.as_str(), &path)
        };

        let anchor = if with_lines {
            let loline = span.lo(self.sess()).line;
            let hiline = span.hi(self.sess()).line;
            format!(
                "#{}",
                if loline == hiline { loline.to_string() } else { format!("{loline}-{hiline}") }
            )
        } else {
            "".to_string()
        };
        Some(format!(
            "{root}src/{krate}/{path}{anchor}",
            root = Escape(&root),
            krate = krate,
            path = path,
            anchor = anchor
        ))
    }

    pub(crate) fn href_from_span_relative(
        &self,
        span: clean::Span,
        relative_to: &str,
    ) -> Option<String> {
        self.href_from_span(span, false).map(|s| {
            let mut url = UrlPartsBuilder::new();
            let mut dest_href_parts = s.split('/');
            let mut cur_href_parts = relative_to.split('/');
            for (cur_href_part, dest_href_part) in (&mut cur_href_parts).zip(&mut dest_href_parts) {
                if cur_href_part != dest_href_part {
                    url.push(dest_href_part);
                    break;
                }
            }
            for dest_href_part in dest_href_parts {
                url.push(dest_href_part);
            }
            let loline = span.lo(self.sess()).line;
            let hiline = span.hi(self.sess()).line;
            format!(
                "{}{}#{}",
                "../".repeat(cur_href_parts.count()),
                url.finish(),
                if loline == hiline { loline.to_string() } else { format!("{loline}-{hiline}") }
            )
        })
    }
}

impl<'tcx> Context<'tcx> {
    pub(crate) fn init(
        krate: clean::Crate,
        options: RenderOptions,
        cache: Cache,
        tcx: TyCtxt<'tcx>,
        expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
    ) -> Result<(Self, clean::Crate), Error> {
        // need to save a copy of the options for rendering the index page
        let md_opts = options.clone();
        let emit_crate = options.should_emit_crate();
        let RenderOptions {
            output,
            external_html,
            id_map,
            playground_url,
            module_sorting,
            themes: style_files,
            default_settings,
            extension_css,
            resource_suffix,
            static_root_path,
            generate_redirect_map,
            show_type_layout,
            generate_link_to_definition,
            call_locations,
            no_emit_shared,
            html_no_source,
            ..
        } = options;

        let src_root = match krate.src(tcx) {
            FileName::Real(ref p) => match p.local_path_if_available().parent() {
                Some(p) => p.to_path_buf(),
                None => PathBuf::new(),
            },
            _ => PathBuf::new(),
        };
        // If user passed in `--playground-url` arg, we fill in crate name here
        let mut playground = None;
        if let Some(url) = playground_url {
            playground = Some(markdown::Playground { crate_name: Some(krate.name(tcx)), url });
        }
        let krate_version = cache.crate_version.as_deref().unwrap_or_default();
        let mut layout = layout::Layout {
            logo: String::new(),
            favicon: String::new(),
            external_html,
            default_settings,
            krate: krate.name(tcx).to_string(),
            krate_version: krate_version.to_string(),
            css_file_extension: extension_css,
            scrape_examples_extension: !call_locations.is_empty(),
        };
        let mut issue_tracker_base_url = None;
        let mut include_sources = !html_no_source;

        // Crawl the crate attributes looking for attributes which control how we're
        // going to emit HTML
        for attr in krate.module.attrs.lists(sym::doc) {
            match (attr.name(), attr.value_str()) {
                (Some(sym::html_favicon_url), Some(s)) => {
                    layout.favicon = s.to_string();
                }
                (Some(sym::html_logo_url), Some(s)) => {
                    layout.logo = s.to_string();
                }
                (Some(sym::html_playground_url), Some(s)) => {
                    playground = Some(markdown::Playground {
                        crate_name: Some(krate.name(tcx)),
                        url: s.to_string(),
                    });
                }
                (Some(sym::issue_tracker_base_url), Some(s)) => {
                    issue_tracker_base_url = Some(s.to_string());
                }
                (Some(sym::html_no_source), None) if attr.is_word() => {
                    include_sources = false;
                }
                _ => {}
            }
        }

        let (local_sources, matches) = collect_spans_and_sources(
            tcx,
            &krate,
            &src_root,
            include_sources,
            generate_link_to_definition,
        );

        let (sender, receiver) = channel();
        let scx = SharedContext {
            tcx,
            src_root,
            local_sources,
            issue_tracker_base_url,
            layout,
            created_dirs: Default::default(),
            module_sorting,
            style_files,
            resource_suffix,
            static_root_path,
            fs: DocFS::new(sender),
            codes: ErrorCodes::from(options.unstable_features.is_nightly_build()),
            playground,
            all: RefCell::new(AllTypes::new()),
            errors: receiver,
            redirections: if generate_redirect_map { Some(Default::default()) } else { None },
            show_type_layout,
            span_correspondence_map: matches,
            cache,
            call_locations,
            should_merge: options.should_merge,
            expanded_codes,
        };

        let dst = output;
        scx.ensure_dir(&dst)?;

        let mut cx = Context {
            current: Vec::new(),
            dst,
            id_map: RefCell::new(id_map),
            deref_id_map: Default::default(),
            shared: scx,
            types_with_notable_traits: RefCell::new(FxIndexSet::default()),
            info: ContextInfo::new(include_sources),
        };

        if emit_crate {
            sources::render(&mut cx, &krate)?;
        }

        if !no_emit_shared {
            write_shared(&mut cx, &krate, &md_opts, tcx)?;
        }

        Ok((cx, krate))
    }
}

/// Generates the documentation for `crate` into the directory `dst`
impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
    fn descr() -> &'static str {
        "html"
    }

    const RUN_ON_MODULE: bool = true;
    type ModuleData = ContextInfo;

    fn save_module_data(&mut self) -> Self::ModuleData {
        self.deref_id_map.borrow_mut().clear();
        self.id_map.borrow_mut().clear();
        self.types_with_notable_traits.borrow_mut().clear();
        self.info
    }

    fn restore_module_data(&mut self, info: Self::ModuleData) {
        self.info = info;
    }

    fn after_krate(mut self) -> Result<(), Error> {
        let crate_name = self.tcx().crate_name(LOCAL_CRATE);
        let final_file = self.dst.join(crate_name.as_str()).join("all.html");
        let settings_file = self.dst.join("settings.html");
        let help_file = self.dst.join("help.html");
        let scrape_examples_help_file = self.dst.join("scrape-examples-help.html");

        let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
        if !root_path.ends_with('/') {
            root_path.push('/');
        }
        let shared = &self.shared;
        let mut page = layout::Page {
            title: "List of all items in this crate",
            short_title: "All",
            css_class: "mod sys",
            root_path: "../",
            static_root_path: shared.static_root_path.as_deref(),
            description: "List of all items in this crate",
            resource_suffix: &shared.resource_suffix,
            rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo),
        };
        let all = shared.all.replace(AllTypes::new());
        let mut sidebar = String::new();

        // all.html is not customizable, so a blank id map is fine
        let blocks = sidebar_module_like(all.item_sections(), &mut IdMap::new(), ModuleLike::Crate);
        let bar = Sidebar {
            title_prefix: "",
            title: "",
            is_crate: false,
            is_mod: false,
            parent_is_crate: false,
            blocks: vec![blocks],
            path: String::new(),
        };

        bar.render_into(&mut sidebar).unwrap();

        let v = layout::render(&shared.layout, &page, sidebar, all.print(), &shared.style_files);
        shared.fs.write(final_file, v)?;

        // if to avoid writing help, settings files to doc root unless we're on the final invocation
        if shared.should_merge.write_rendered_cci {
            // Generating settings page.
            page.title = "Settings";
            page.description = "Settings of Rustdoc";
            page.root_path = "./";
            page.rust_logo = true;

            let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
            let v = layout::render(
                &shared.layout,
                &page,
                sidebar,
                fmt::from_fn(|buf| {
                    write!(
                        buf,
                        "<div class=\"main-heading\">\
                         <h1>Rustdoc settings</h1>\
                         <span class=\"out-of-band\">\
                             <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
                                Back\
                            </a>\
                         </span>\
                         </div>\
                         <noscript>\
                            <section>\
                                You need to enable JavaScript be able to update your settings.\
                            </section>\
                         </noscript>\
                         <script defer src=\"{static_root_path}{settings_js}\"></script>",
                        static_root_path = page.get_static_root_path(),
                        settings_js = static_files::STATIC_FILES.settings_js,
                    )?;
                    // Pre-load all theme CSS files, so that switching feels seamless.
                    //
                    // When loading settings.html as a popover, the equivalent HTML is
                    // generated in main.js.
                    for file in &shared.style_files {
                        if let Ok(theme) = file.basename() {
                            write!(
                                buf,
                                "<link rel=\"preload\" href=\"{root_path}{theme}{suffix}.css\" \
                                    as=\"style\">",
                                root_path = page.static_root_path.unwrap_or(""),
                                suffix = page.resource_suffix,
                            )?;
                        }
                    }
                    Ok(())
                }),
                &shared.style_files,
            );
            shared.fs.write(settings_file, v)?;

            // Generating help page.
            page.title = "Help";
            page.description = "Documentation for Rustdoc";
            page.root_path = "./";
            page.rust_logo = true;

            let sidebar = "<h2 class=\"location\">Help</h2><div class=\"sidebar-elems\"></div>";
            let v = layout::render(
                &shared.layout,
                &page,
                sidebar,
                format_args!(
                    "<div class=\"main-heading\">\
                        <h1>Rustdoc help</h1>\
                        <span class=\"out-of-band\">\
                            <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
                            Back\
                        </a>\
                        </span>\
                        </div>\
                        <noscript>\
                        <section>\
                            <p>You need to enable JavaScript to use keyboard commands or search.</p>\
                            <p>For more information, browse the <a href=\"{DOC_RUST_LANG_ORG_VERSION}/rustdoc/\">rustdoc handbook</a>.</p>\
                        </section>\
                        </noscript>",
                ),
                &shared.style_files,
            );
            shared.fs.write(help_file, v)?;
        }

        // if to avoid writing files to doc root unless we're on the final invocation
        if shared.layout.scrape_examples_extension && shared.should_merge.write_rendered_cci {
            page.title = "About scraped examples";
            page.description = "How the scraped examples feature works in Rustdoc";
            let v = layout::render(
                &shared.layout,
                &page,
                "",
                scrape_examples_help(shared),
                &shared.style_files,
            );
            shared.fs.write(scrape_examples_help_file, v)?;
        }

        if let Some(ref redirections) = shared.redirections
            && !redirections.borrow().is_empty()
        {
            let redirect_map_path = self.dst.join(crate_name.as_str()).join("redirect-map.json");
            let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
            shared.ensure_dir(&self.dst.join(crate_name.as_str()))?;
            shared.fs.write(redirect_map_path, paths)?;
        }

        // Flush pending errors.
        self.shared.fs.close();
        let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count();
        if nb_errors > 0 { Err(Error::new(io::Error::other("I/O error"), "")) } else { Ok(()) }
    }

    fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
        // Stripped modules survive the rustdoc passes (i.e., `strip-private`)
        // if they contain impls for public types. These modules can also
        // contain items such as publicly re-exported structures.
        //
        // External crates will provide links to these structures, so
        // these modules are recursed into, but not rendered normally
        // (a flag on the context).
        if !self.info.render_redirect_pages {
            self.info.render_redirect_pages = item.is_stripped();
        }
        let item_name = item.name.unwrap();
        self.dst.push(item_name.as_str());
        self.current.push(item_name);

        info!("Recursing into {}", self.dst.display());

        if !item.is_stripped() {
            let buf = self.render_item(item, true);
            // buf will be empty if the module is stripped and there is no redirect for it
            if !buf.is_empty() {
                self.shared.ensure_dir(&self.dst)?;
                let joint_dst = self.dst.join("index.html");
                self.shared.fs.write(joint_dst, buf)?;
            }
        }
        if !self.info.is_inside_inlined_module {
            if let Some(def_id) = item.def_id()
                && self.cache().inlined_items.contains(&def_id)
            {
                self.info.is_inside_inlined_module = true;
            }
        } else if !self.cache().document_hidden && item.is_doc_hidden() {
            // We're not inside an inlined module anymore since this one cannot be re-exported.
            self.info.is_inside_inlined_module = false;
        }

        // Render sidebar-items.js used throughout this module.
        if !self.info.render_redirect_pages {
            let (clean::StrippedItem(box clean::ModuleItem(ref module))
            | clean::ModuleItem(ref module)) = item.kind
            else {
                unreachable!()
            };
            let items = self.build_sidebar_items(module);
            let js_dst = self.dst.join(format!("sidebar-items{}.js", self.shared.resource_suffix));
            let v = format!("window.SIDEBAR_ITEMS = {};", serde_json::to_string(&items).unwrap());
            self.shared.fs.write(js_dst, v)?;
        }
        Ok(())
    }

    fn mod_item_out(&mut self) -> Result<(), Error> {
        info!("Recursed; leaving {}", self.dst.display());

        // Go back to where we were at
        self.dst.pop();
        self.current.pop();
        Ok(())
    }

    fn item(&mut self, item: &clean::Item) -> Result<(), Error> {
        // Stripped modules survive the rustdoc passes (i.e., `strip-private`)
        // if they contain impls for public types. These modules can also
        // contain items such as publicly re-exported structures.
        //
        // External crates will provide links to these structures, so
        // these modules are recursed into, but not rendered normally
        // (a flag on the context).
        if !self.info.render_redirect_pages {
            self.info.render_redirect_pages = item.is_stripped();
        }

        let buf = self.render_item(item, false);
        // buf will be empty if the item is stripped and there is no redirect for it
        if !buf.is_empty() {
            let name = item.name.as_ref().unwrap();
            let item_type = item.type_();
            let file_name = print_item_path(item_type, name.as_str()).to_string();
            self.shared.ensure_dir(&self.dst)?;
            let joint_dst = self.dst.join(&file_name);
            self.shared.fs.write(joint_dst, buf)?;

            if !self.info.render_redirect_pages {
                self.shared.all.borrow_mut().append(full_path(self, item), &item_type);
            }
            // If the item is a macro, redirect from the old macro URL (with !)
            // to the new one (without).
            if item_type == ItemType::Macro {
                let redir_name = format!("{item_type}.{name}!.html");
                if let Some(ref redirections) = self.shared.redirections {
                    let crate_name = &self.shared.layout.krate;
                    redirections.borrow_mut().insert(
                        format!("{crate_name}/{redir_name}"),
                        format!("{crate_name}/{file_name}"),
                    );
                } else {
                    let v = layout::redirect(&file_name);
                    let redir_dst = self.dst.join(redir_name);
                    self.shared.fs.write(redir_dst, v)?;
                }
            }
        }

        Ok(())
    }
}
