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;

    /// Sets up any state required for the renderer. When this is called the cache has already been
    /// populated.
    fn init(
        krate: clean::Crate,
        options: RenderOptions,
        cache: Cache,
        tcx: TyCtxt<'tcx>,
    ) -> Result<(Self, clean::Crate), Error>;

    /// 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>>(
    krate: clean::Crate,
    options: RenderOptions,
    cache: Cache,
    tcx: TyCtxt<'tcx>,
) -> 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(|| T::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())
}
