using NubLang.Syntax;

namespace NubLang.Generation;

public static class HeaderGenerator
{
    private static string FuncName(string module, string name, string? externSymbol)
    {
        return externSymbol ?? $"{module}_{name}";
    }

    public static string Generate(string name, TypedModule module)
    {
        var writer = new IndentedTextWriter();

        foreach (var import in module.Imports)
        {
            writer.WriteLine($"#include \"{import}.h\"");
        }

        writer.WriteLine();

        foreach (var structType in module.StructTypes)
        {
            writer.WriteLine("typedef struct");
            writer.WriteLine("{");
            using (writer.Indent())
            {
                foreach (var field in structType.Fields)
                {
                    writer.WriteLine($"{CType.Create(field.Type)} {field.Name};");
                }
            }

            writer.WriteLine($"}} {CType.Create(structType)};");
            writer.WriteLine($"void {CType.Create(structType)}_create({CType.Create(structType)} *self);");
            writer.WriteLine();
        }

        foreach (var prototype in module.FunctionPrototypes)
        {
            var parameters = prototype.Parameters.Count != 0
                ? string.Join(", ", prototype.Parameters.Select(x => CType.Create(x.Type, x.NameToken.Value)))
                : "void";

            var funcName = FuncName(name, prototype.NameToken.Value, prototype.ExternSymbolToken?.Value);
            writer.WriteLine($"{CType.Create(prototype.ReturnType, funcName)}({parameters});");
        }

        return writer.ToString();
    }
}