use crate::interpreter::{
    function::Function,
    library::{get_std_methods, get_std_types},
    namespace::{
        Namespace,
        NamespacedKind,
        Namespaces,
        Progress,
        ProgressKind,
        TypeAndGenerics,
        Typing,
    },
    scope::Scope,
    DependencyGraph,
    Interpreter,
    ParsedMacroStore,
};
use quote::format_ident;

impl<'ast> Interpreter<'ast> {
    pub fn with_standard_library(
        parsed_macros: ParsedMacroStore<'ast>,
        dependency_graph: DependencyGraph<'ast>,
    ) -> Self {
        let mut interpreter = Interpreter {
            parsed_macros,
            ..Default::default()
        };
        for (name, rust_type) in get_std_types() {
            let n = Typing::insert_inner(
                &mut interpreter,
                Progress::Output(TypeAndGenerics::new(rust_type, None)),
            );
            interpreter.namespaces.insert_with_scope(
                format_ident!("{name}"),
                Scope::TopLevel,
                Namespace::Type(n),
            );
        }
        for (name, ty, func) in get_std_methods() {
            let n = Typing::insert_inner(
                &mut interpreter,
                Progress::Output(TypeAndGenerics::new(ty, None)),
            );
            interpreter.insert_method(format_ident!("{name}"), n, Function::Static(func));
        }
        for (dep, v) in dependency_graph {
            for (name, parent) in v {
                let p_namespace = Namespace::Scope(match parent {
                    None => Scope::TopLevel,
                    Some(i) => i.0.into(),
                });
                let d_namespace = Namespace::Scope(dep.0.into());
                Namespaces::insert_with_namespace(
                    &mut interpreter,
                    format_ident!("{}", name),
                    p_namespace,
                    d_namespace,
                );
            }
        }
        interpreter
    }
}
