using NubLang.Ast;

namespace NubLang.Syntax;

public sealed class TypedModule
{
    public static TypedModule FromModule(string name, Module module, Dictionary<string, Module> modules)
    {
        var typeResolver = new TypeResolver(modules);

        var functionPrototypes = new List<FuncPrototypeNode>();

        foreach (var funcSyntax in module.Functions(true))
        {
            var parameters = new List<FuncParameterNode>();
            foreach (var parameter in funcSyntax.Prototype.Parameters)
            {
                parameters.Add(new FuncParameterNode(parameter.Tokens, parameter.NameToken, typeResolver.ResolveType(parameter.Type, name)));
            }

            var returnType = typeResolver.ResolveType(funcSyntax.Prototype.ReturnType, name);

            functionPrototypes.Add(new FuncPrototypeNode(funcSyntax.Tokens, funcSyntax.Prototype.NameToken, funcSyntax.Prototype.ExternSymbolToken, parameters, returnType));
        }

        var structTypes = new List<NubStructType>();

        foreach (var structSyntax in module.Structs(true))
        {
            var fields = new List<NubStructFieldType>();
            foreach (var field in structSyntax.Fields)
            {
                fields.Add(new NubStructFieldType(field.NameToken.Value, typeResolver.ResolveType(field.Type, name), field.Value != null));
            }

            structTypes.Add(new NubStructType(name, structSyntax.NameToken.Value, structSyntax.Packed, fields));
        }

        return new TypedModule(functionPrototypes, structTypes, module.Imports());
    }

    public TypedModule(List<FuncPrototypeNode> functionPrototypes, List<NubStructType> structTypes, List<string> imports)
    {
        FunctionPrototypes = functionPrototypes;
        StructTypes = structTypes;
        Imports = imports;
    }

    public List<FuncPrototypeNode> FunctionPrototypes { get; }
    public List<NubStructType> StructTypes { get; }
    public List<string> Imports { get; }
}