import * as path from "jsr:@std/path";
import { Parser } from "./parser/parser.ts";
import * as ast from "./ast/mod.ts";
import { Ctx } from "./ctx.ts";
import { File } from "./ctx.ts";

export type Pack = {
    rootMod: Mod;
};

export type Mod = null;

export interface PackEmitter {
    emit(pack: Pack): void;
}

export class PackCompiler {
    public constructor(
        private entryFilePath: string,
        private emitter: PackEmitter,
    ) {}

    public compile() {
    }
}

type _P = { file: File };
export class FileTreeCollector implements ast.Visitor<[_P]> {
    private subFilePromise = Promise.resolve();

    public constructor(
        private ctx: Ctx,
        private superFile: File | undefined,
        private ident: string,
        private absPath: string,
        private relPath: string,
    ) {}

    public async collect(): Promise<void> {
        const text = await Deno.readTextFile(this.absPath);
        const file = this.ctx.addFile(
            this.ident,
            this.absPath,
            this.relPath,
            this.superFile,
            text,
        );
        const fileAst = new Parser(file, text).parse();
        this.ctx.addFileAst(file, fileAst);
        ast.visitFile(this, fileAst, { file });
        await this.subFilePromise;
    }

    visitModFileStmt(
        _stmt: ast.Stmt,
        kind: ast.ModFileStmt,
        { file }: _P,
    ): ast.VisitRes {
        const { ident, filePath: relPath } = kind;
        const absPath = path.join(path.dirname(this.absPath), relPath);
        this.subFilePromise = this.subFilePromise
            .then(() => {
                if (this.ctx.fileHasChildWithIdent(file, ident)) {
                }
                return new FileTreeCollector(
                    this.ctx,
                    file,
                    ident,
                    absPath,
                    relPath,
                )
                    .collect();
            });
        return "stop";
    }
}