"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sync = sync;
exports.rawSync = rawSync;
const fs_1 = require("fs");
const fs_extra_1 = require("fs-extra");
const glob = require("glob");
const path = require("path");
const keyCode_1 = require("../client/event/keyboard/keyCode");
const removeLastSegment_1 = require("../util/removeLastSegment");
/* eslint-disable no-console */
async function sync(systemDir, outputDir, specIdWhitelist) {
    const { specs, ids, classes, components } = rawSync(systemDir, specIdWhitelist);
    await (0, fs_extra_1.ensureDir)(outputDir);
    await Promise.all([
        (0, fs_extra_1.writeFile)(path.join(outputDir, '_ids.ts'), ids),
        (0, fs_extra_1.writeFile)(path.join(outputDir, '_classes.ts'), classes),
        (0, fs_extra_1.writeFile)(path.join(outputDir, '_components.ts'), components),
        (0, fs_extra_1.writeFile)(path.join(outputDir, '_specs.ts'), specs),
    ]);
}
function rawSync(dir, idSet) {
    let specs = '';
    const _specs = {};
    let ids = '';
    let ids_name_set = new Set();
    let classes = '';
    let classes_import = '';
    let classes_export = 'export default {\n';
    const class_name_set = new Set();
    let components = '';
    let components_import = '';
    let components_export = 'export default {\n';
    const component_name_set = new Set();
    glob
        .sync(`**/**/spec.json`, {
        cwd: dir,
    })
        .map((path) => (0, removeLastSegment_1.removeLastSegment)(path))
        .forEach((_) => {
        const spec_file_path = `${dir}/${_}/spec.json`;
        const spec = (0, fs_extra_1.readJSONSync)(spec_file_path);
        const segments = _.split('/');
        const l = segments.length;
        const tags = segments.slice(0, l - 1);
        const id = spec.id;
        if (!id) {
            console.log(`id not specified at ${spec_file_path}`);
        }
        spec.system = true;
        spec.metadata = spec.metadata || {};
        spec.metadata.tags = tags;
        const { base, name } = spec;
        let _name = name;
        let i = 0;
        while (ids_name_set.has(_name)) {
            _name = name + ' ' + i;
            i++;
        }
        ids_name_set.add(_name);
        if (idSet && !idSet.has(id)) {
            return;
        }
        const NAME = _name
            .split('')
            .filter(keyCode_1.isNotSymbol)
            .join('')
            .toUpperCase()
            .split(' ')
            .join('_');
        ids += `export const ID_${NAME} = '${id}'\n`;
        _specs[id] = spec;
        let name_init = segments[l - 1];
        const class_file_path = `${dir}/${_}/index.ts`;
        if ((0, fs_1.existsSync)(class_file_path)) {
            let name = name_init;
            let i = 0;
            while (class_name_set.has(name)) {
                name = name_init + i;
                i++;
            }
            class_name_set.add(name);
            classes_import += `import ${name} from './${_}'\n`;
            classes_export += `\t'${id}': ${name},\n`;
        }
        const component_file_path = `${dir}/${_}/Component.ts`;
        if ((0, fs_1.existsSync)(component_file_path)) {
            let name = name_init;
            let i = 0;
            while (component_name_set.has(name)) {
                name = name_init + i;
                i++;
            }
            component_name_set.add(name);
            components_import += `import ${name} from './${_}/Component'\n`;
            components_export += `\t'${id}': ${name},\n`;
        }
    });
    classes_export += '}';
    components_export += '}';
    components = components_import + '\n' + components_export;
    classes = classes_import + '\n' + classes_export;
    specs = `export default JSON.parse(\`${JSON.stringify(_specs)
        .replace(/\\/g, '\\\\')
        .replace(/`/g, '\\`')
        .replace(/\$/g, '\\$')}\`)\n`;
    return { specs, classes, components, ids };
}
//# sourceMappingURL=sync.js.map