use std::ops::ControlFlow;

use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use tracing::instrument;

use crate::vfs::{self, Dir, VPathBuf};

#[derive(Debug, Clone, Serialize)]
pub struct ImportMap {
    pub imports: IndexMap<String, String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ImportRoot {
    pub name: String,
    pub path: VPathBuf,
}

impl ImportMap {
    #[instrument(name = "ImportMap::generate", skip(import_roots))]
    pub fn generate(site: &str, root: &dyn Dir, import_roots: &[ImportRoot]) -> Self {
        let mut import_map = ImportMap {
            imports: IndexMap::new(),
        };

        for import_root in import_roots {
            vfs::walk_dir_rec(root, &import_root.path, &mut |path| {
                if path.extension() == Some("js") {
                    import_map.imports.insert(
                        format!(
                            "{}/{}",
                            import_root.name,
                            path.strip_prefix(&import_root.path).unwrap_or(path)
                        ),
                        vfs::url(site, root, path)
                            .expect("import directory is not anchored anywhere"),
                    );
                }
                ControlFlow::Continue(())
            });
        }

        import_map.imports.sort_unstable_keys();

        import_map
    }
}
