import { ECSCompiler } from "../../common/ecs/compiler";
import { Dialect_CA65, ECSError, EntityManager } from "../../common/ecs/ecs";
import { CompileError } from "../../common/tokenizer";
import { CodeListingMap } from "../../common/workertypes";
import { BuildStep, BuildStepResult, getWorkFileAsString, gatherFiles, staleFiles, fixParamsWithDefines, putWorkFile } from "../builder";

export function assembleECS(step: BuildStep): BuildStepResult {
    let em = new EntityManager(new Dialect_CA65()); // TODO
    let compiler = new ECSCompiler(em, true);
    compiler.getImportFile = (path: string) => {
        return getWorkFileAsString(path);
    }
    gatherFiles(step, { mainFilePath: "main.ecs" });
    if (step.mainfile) em.mainPath = step.path;
    var destpath = step.prefix + '.ca65';
    if (staleFiles(step, [destpath])) {
        let code = getWorkFileAsString(step.path);
        // TODO
        step.params.cfgfile = 'atari2600-ecs.cfg';
        step.params.extra_link_files.push('atari2600-ecs.cfg');
        fixParamsWithDefines(step.path, step.params);
        // remove crt0.o from libargs
        step.params.libargs = step.params.libargs.filter((arg: string) => {
            return arg !== 'crt0.o';
        });
        try {
            compiler.includeDebugInfo = true;
            compiler.parseFile(code, step.path);
            let outtext = compiler.export().toString();
            putWorkFile(destpath, outtext);
            var listings: CodeListingMap = {};
            listings[destpath] = {lines:[], text:outtext} // TODO
            var debuginfo = compiler.em.getDebugTree();
        } catch (e) {
            if (e instanceof ECSError) {
                compiler.addError(e.message, e.$loc);
                for (let obj of e.$sources) {
                    let name = (obj as any).event;
                    if (name == 'start') break;
                    compiler.addError(`... ${name}`, obj.$loc); // TODO?
                }
                return { errors: compiler.errors, listings, debuginfo };
            } else if (e instanceof CompileError) {
                return { errors: compiler.errors, listings, debuginfo };
            } else {
                throw e;
            }
        }
        return {
            nexttool: "ca65",
            path: destpath,
            args: [destpath],
            files: [destpath].concat(step.files),
            listings,
            debuginfo
        };
    }
}
