use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_middle::ty::TyCtxt;

use crate::clean;
use crate::config::RenderOptions;
use crate::error::Error;
use crate::formats::cache::Cache;

/// Allows for different backends to rustdoc to be used with the `run_format()` function. Each
/// backend renderer has hooks for initialization, documenting an item, entering and exiting a
/// module, and cleanup/finalizing output.
pub(crate) trait FormatRenderer<'tcx>: Sized {
    /// Gives a description of the renderer. Used for performance profiling.
    fn descr() -> &'static str;

    /// Whether to call `item` recursively for modules
    ///
    /// This is true for html, and false for json. See #80664
    const RUN_ON_MODULE: bool;

    /// This associated type is the type where the current module information is stored.
    ///
    /// For each module, we go through their items by calling for each item:
    ///
    /// 1. `save_module_data`
    /// 2. `item`
    /// 3. `restore_module_data`
    ///
    /// This is because the `item` method might update information in `self` (for example if the child
    /// is a module). To prevent it from impacting the other children of the current module, we need to
    /// reset the information between each call to `item` by using `restore_module_data`.
    type ModuleData;

    /// This method is called right before call [`Self::item`]. This method returns a type
    /// containing information that needs to be reset after the [`Self::item`] method has been
    /// called with the [`Self::restore_module_data`] method.
    ///
    /// In short it goes like this:
    ///
    /// ```ignore (not valid code)
    /// let reset_data = renderer.save_module_data();
    /// renderer.item(item)?;
    /// renderer.restore_module_data(reset_data);
    /// ```
    fn save_module_data(&mut self) -> Self::ModuleData;
    /// Used to reset current module's information.
    fn restore_module_data(&mut self, info: Self::ModuleData);

    /// Renders a single non-module item. This means no recursive sub-item rendering is required.
    fn item(&mut self, item: &clean::Item) -> Result<(), Error>;

    /// Renders a module (should not handle recursing into children).
    fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error>;

    /// Runs after recursively rendering all sub-items of a module.
    fn mod_item_out(&mut self) -> Result<(), Error> {
        Ok(())
    }

    /// Post processing hook for cleanup and dumping output to files.
    fn after_krate(self) -> Result<(), Error>;
}

fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
    cx: &mut T,
    item: &clean::Item,
    prof: &SelfProfilerRef,
) -> Result<(), Error> {
    if item.is_mod() && T::RUN_ON_MODULE {
        // modules are special because they add a namespace. We also need to
        // recurse into the items of the module as well.
        let _timer =
            prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());

        cx.mod_item_in(item)?;
        let (clean::StrippedItem(box clean::ModuleItem(ref module))
        | clean::ModuleItem(ref module)) = item.inner.kind
        else {
            unreachable!()
        };
        for it in module.items.iter() {
            let info = cx.save_module_data();
            run_format_inner(cx, it, prof)?;
            cx.restore_module_data(info);
        }

        cx.mod_item_out()?;
    // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
    // cases. Use an explicit match instead.
    } else if let Some(item_name) = item.name
        && !item.is_extern_crate()
    {
        prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
    }
    Ok(())
}

/// Main method for rendering a crate.
pub(crate) fn run_format<
    'tcx,
    T: FormatRenderer<'tcx>,
    F: FnOnce(clean::Crate, RenderOptions, Cache, TyCtxt<'tcx>) -> Result<(T, clean::Crate), Error>,
>(
    krate: clean::Crate,
    options: RenderOptions,
    cache: Cache,
    tcx: TyCtxt<'tcx>,
    init: F,
) -> Result<(), Error> {
    let prof = &tcx.sess.prof;

    let emit_crate = options.should_emit_crate();
    let (mut format_renderer, krate) = prof
        .verbose_generic_activity_with_arg("create_renderer", T::descr())
        .run(|| init(krate, options, cache, tcx))?;

    if !emit_crate {
        return Ok(());
    }

    // Render the crate documentation
    run_format_inner(&mut format_renderer, &krate.module, prof)?;

    prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
        .run(|| format_renderer.after_krate())
}
