import * as path from 'path';
import * as pipe from './buildpipe';
import { writeFileAsync } from 'fs-extra-promise';

export type BuildConfig = { projectRoot: string, debug: boolean, target: string }


export type AssetsDiagnosticMessage = {
    url: string,
    id: number,
    message: string
}

export type AssetsDiagnosticResult = {

    warn: AssetsDiagnosticMessage[],

    error: AssetsDiagnosticMessage[]
}


namespace i18n.diagnostic {

    export const DUPLICATE_RES_NAME = "资源名重复";
}

class Reporter {

    diagnostic: AssetsDiagnosticResult = { error: [], warn: [] }

    error(id: number, url: string, message1?: string, message2?: string) {
        const message = this.getMessage(id, message1, message2)
        const error: AssetsDiagnosticMessage = { id, message, url }
        this.diagnostic.error.push(error);
    }

    warn() {

    }

    private getMessage(id: number, message1?: string, message2?: string) {
        const str = i18n.diagnostic.DUPLICATE_RES_NAME;
        return str.replace('${0}', message1).replace('${1}', message2);
    }

}


export async function bake(buildConfig: BuildConfig) {

    const reporter = new Reporter();

    const userConfig: { outputDir: string, matcher: string, commands: any[] } = {
        outputDir: "xxxxx",
        matcher: "resource/**/*.*",
        commands: []
    }



    let projectRoot = path.resolve(process.cwd(), buildConfig.projectRoot).split("\\").join("/")

    const plugins: pipe.Plugin[] = [


    ]

    const files = await pipe.src(userConfig.matcher, { projectRoot });
    for (let p of plugins) {
        await Promise.all(files.map(p.onFile));
    }
    const config = emitResConfig(files, reporter);
    const resourceFilename = path.join(projectRoot, "resource/default.res.json");
    await writeFileAsync(resourceFilename, JSON.stringify(config, null, '\t'), "utf-8");
    return reporter.diagnostic;
}

export async function build(buildConfig: BuildConfig) {

    // pipe.compile(buildConfig.projectRoot);

}

type ResFileConfig = { name: string, type: string, url: string }

type ResConfig = {
    groups: string[],
    resources: ResFileConfig[]
}


function emitResConfig(files: pipe.ResFile[], reporter: Reporter) {
    const config: ResConfig = {
        groups: [],
        resources: []
    }
    for (let item of files) {
        const url = item.origin.replace("resource/", "");
        const name = nameSelector(url);
        const type = typeSelector(url);
        const r = { name, type, url };
        if (config.resources.find(item => item.name == name)) {
            reporter.error(1, url);
        }
        else {
            config.resources.push(r);
        }



    }
    return config;
}

export const nameSelector = (p: string) => {
    if (p.indexOf('2d/') >= 0) {
        return path.basename(p).split(".").join("_");
    }
    else {
        return p;
    }

}

const typeSelector = (p: string) => {
    if (p.indexOf("2d/") >= 0) {
        const ext = p.substr(p.lastIndexOf(".") + 1);
        const typeMap: { [index: string]: string } = {
            "jpg": "image",
            "png": "image",
            "webp": "image",
            "json": "json",
            "fnt": "font",
            "pvr": "pvr",
            "mp3": "sound",
            "zip": "zip",
            "mergeJson": "mergeJson",
            "sheet": "sheet"
        }
        let type = typeMap[ext];
        return type;
    } else {
        let filei = p.lastIndexOf("/");
        let file = p.substr(filei + 1);
        let i = file.indexOf(".", 0);
        let extname = "";
        while (i >= 0) {
            extname = file.substr(i);
            const typemap: { [index: string]: string } = {

                ".vs.glsl": 'GLVertexShader',
                ".fs.glsl": "GLFragmentShader",
                ".shader.json": "Shader",
                ".png": "Texture",
                ".jpg": "Texture",
                ".imgdesc.json": "TextureDesc",
                ".image.json": "TextureDesc",
                ".scene.json": "Scene",
                ".prefab.json": "Prefab",
                ".mat.json": "Material",
                ".gltf.bin": "Mesh",
                ".mesh.bin": "Mesh",
                ".bin": "bin",
                ".zipjson": "bin",
                ".ani.bin": "Animation"
            }
            const type = typemap[extname]
            if (type) {
                return type;
            }
            i = file.indexOf(".", i + 1);
        }
        return 'Unknown';

    }
}