/**
 * ------------------------------------------------------------------------
 * Usage:
 *
 * ```shell
 * node build.js --env asf # build all for asf
 * node build.js --env echartsjs # build all for echartsjs.
 * node build.js --env localsite # build all for localsite.
 * node build.js --env dev # the same as "debug", dev the content of docs.
 * # Check `./config` to see the available env
 * ```
 * ------------------------------------------------------------------------
 */

const md2json = require('./tool/md2json');
const extractDesc = require('./tool/extractDesc');
const fs = require('fs');
const fse = require('fs-extra');
const marked = require('marked');
const copydir = require('copy-dir');
const chalk = require('chalk');
// const MarkDownTOCRenderer = require('./tool/MarkDownTOCRenderer');
const argv = require('yargs').argv;
const path = require('path');
const assert = require('assert');
const chokidar = require('chokidar');
const debounce = require('lodash.debounce');
const {getDocJSONPVarNname} = require('./src/shared');

const projectDir = __dirname;

function initEnv() {
    let envType = argv.env;
    let isDev = argv.dev != null || argv.debug != null || argv.env === 'dev';

    if (isDev) {
        console.warn('=============================');
        console.warn('!!! THIS IS IN DEV MODE !!!');
        console.warn('=============================');
        envType = 'dev';
    }

    if (!envType) {
        throw new Error('--env MUST be specified');
    }

    let config = require('./config/env.' + envType);

    assert(path.isAbsolute(config.releaseDestDir) && path.isAbsolute(config.ecWWWGeneratedDir));

    config.envType = envType;

    return config;
}

const config = initEnv();

const languages = ['zh', 'en'];

config.gl = config.gl || {};
for (let key in config) {
    if (key !== 'gl' && !config.gl.hasOwnProperty(key)) {
        config.gl[key] = config[key];
    }
}

async function md2jsonAsync(opt) {

    var newOpt = Object.assign({
        path: path.join(opt.language, opt.entry, '**/*.md'),
        tplEnv: Object.assign({}, config, {
            galleryViewPath: config.galleryViewPath.replace('${lang}', opt.language),
            galleryEditorPath: config.galleryEditorPath.replace('${lang}', opt.language)
        }),
        imageRoot: config.imagePath
    }, opt);

    function run(cb) {
        md2json(newOpt).then(schema => {
            writeSingleSchema(schema, opt.language, opt.entry, false);
            writeSingleSchemaPartioned(schema, opt.language, opt.entry, false);
            console.log(chalk.green('generated: ' + opt.language + '/' + opt.entry));
            cb && cb();
        }).catch(e => {
            console.log(e);
        });
    }

    var runDebounced = debounce(run, 500, {
        leading: false,
        trailing: true
    });
    return await new Promise((resolve, reject) => {
        run(resolve);

        if (argv.watch) {
            chokidar.watch(path.resolve(__dirname, opt.language, opt.entry), {
                ignoreInitial: true
            }).on('all', (event, path) => {
                console.log(path, event);
                runDebounced();
            });
        }
    });
}

function copyAsset() {

    const assetSrcDir = path.resolve(projectDir, 'asset');

    function doCopy() {
        for (let lang of languages) {
            const assetDestDir = path.resolve(config.releaseDestDir, `${lang}/documents/asset`);
            copydir.sync(assetSrcDir, assetDestDir);
        }
    }
    var doCopyDebounced = debounce(doCopy, 500, {
        leading: false,
        trailing: true
    });

    doCopy();

    if (argv.watch) {
        chokidar.watch(assetSrcDir, {
            ignoreInitial: true
        }).on('all', (event, path) => {
            console.log(path, event);
            doCopyDebounced();
        });
    }
    console.log('Copy asset done.');
}

async function run() {

    for (let language of languages) {
        await md2jsonAsync({
            sectionsAnyOf: ['visualMap', 'dataZoom', 'series', 'graphic.elements', 'dataset.transform'],
            entry: 'option',
            language
        });

        await md2jsonAsync({
            entry: 'tutorial',
            maxDepth: 1,
            language
        });

        await md2jsonAsync({
            entry: 'api',
            language
        });

        await md2jsonAsync({
            sectionsAnyOf: ['series'],
            entry: 'option-gl',
            // Overwrite
            tplEnv: config.gl,
            imageRoot: config.gl.imagePath,
            language
        });
    }

    console.log('Build doc done.');

    copyAsset();

    if (!argv.watch) {  // Not in watch dev mode
        try {
            // TODO Do we need to debug changelog in the doc folder?
            buildChangelog();
            buildCodeStandard();

            copySite();
        }
        catch (e) {
            console.log('Error happens when copying to dest folders.');
            console.log(e);
        }
    }

    console.log('All done.');
}

function buildChangelog() {
    for (let lang of languages) {
        const srcPath = path.resolve(projectDir, `${lang}/changelog.md`);
        const destPath = path.resolve(config.ecWWWGeneratedDir, `${lang}/documents/changelog-content.html`);
        fse.outputFileSync(
            destPath,
            marked(fs.readFileSync(srcPath, 'utf-8')),
            'utf-8'
        );
        console.log(chalk.green('generated: ' + destPath));
    }
    console.log('Build changelog done.');
}

function buildCodeStandard() {
    // support for Chinese character
    const customRenderer = new marked.Renderer();
    customRenderer.heading = function(text, level, raw) {
        const id = raw.toLowerCase().replace(/[^\w\u4e00-\u9fa5]+/g, '-');
        return `<h${level} id="${id}">${text}</h${level}>\n`;
    };

    for (let lang of languages) {
        const codeStandardDestPath = path.resolve(config.ecWWWGeneratedDir, `${lang}/coding-standard-content.html`);
        fse.ensureDirSync(path.dirname(codeStandardDestPath));
        fse.outputFileSync(
            codeStandardDestPath,
            marked(fs.readFileSync(`${lang}/coding-standard.md`, 'utf-8'), { renderer: customRenderer }),
            'utf-8'
        );
        console.log(chalk.green('generated: ' + codeStandardDestPath));
    }

    console.log('Build code standard done.');
}

function copySite() {
    const jsSrcPath = path.resolve(projectDir, 'public/js/doc-bundle.js');
    const cssSrcDir = path.resolve(projectDir, 'public/css');

    // Copy js and css of doc site.
    for (let lang of languages) {
        const jsDestPath = path.resolve(config.releaseDestDir, `${lang}/js/doc-bundle.js`);
        fse.copySync(jsSrcPath, jsDestPath);
        console.log(chalk.green(`js copied to: ${jsDestPath}`));

        const cssDestDir = path.resolve(config.releaseDestDir, `${lang}/css`);
        fse.copySync(cssSrcDir, cssDestDir);
        console.log(chalk.green(`css copied to: ${cssDestDir}`));
    }

    console.log('Copy site done.');
}

function writeSingleSchema(schema, language, docName, format) {
    const destPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}.json`);
    fse.ensureDirSync(path.dirname(destPath));
    fse.outputFileSync(
        destPath,
        format ? JSON.stringify(schema, null, 2) : JSON.stringify(schema),
        'utf-8'
    );
    // console.log(chalk.green('generated: ' + destPath));
}

function writeSingleSchemaPartioned(schema, language, docName, format) {
    const {outline, descriptions} = extractDesc(schema, docName);

    function convertToJS(basename, filePath) {
        const content = fs.readFileSync(filePath, 'utf-8');
        const varName = getDocJSONPVarNname(basename);
        const code = `window.${varName} = ${content}`;
        fs.writeFileSync(filePath.replace(/\.json$/, '.js'), code, 'utf-8');
    }

    const outlineBasename = `${docName}-outline.json`;
    const outlineDestPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}-parts/${outlineBasename}`);
    fse.ensureDirSync(path.dirname(outlineDestPath));
    fse.outputFileSync(
        outlineDestPath,
        format ? JSON.stringify(outline, null, 2) : JSON.stringify(outline),
        'utf-8'
    );
    convertToJS(outlineBasename, outlineDestPath);

    function copyUIControlConfigs(source, target) {
        for (let key in source) {
            if (target[key]) {
                if (source[key].uiControl && !target[key].uiControl) {
                    target[key].uiControl = source[key].uiControl;
                }
                if (source[key].exampleBaseOptions && !target[key].exampleBaseOptions) {
                    target[key].exampleBaseOptions = source[key].exampleBaseOptions;
                }
            }
            else {
                // console.error(`Unmatched option path ${key}`);
            }
        }
    }

    function readOptionDesc(language, partKey) {
        const descDestPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}-parts/${partKey}.json`);
        try {
            const text = fs.readFileSync(descDestPath, 'utf-8');
            return JSON.parse(text);
        }
        catch(e) {
            return;
        }
    }

    function writeOptionDesc(language, partKey, json) {
        const descBasename = `${partKey}.json`;
        const descDestPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}-parts/${descBasename}`);
        fse.ensureDirSync(path.dirname(descDestPath));
        const content = JSON.stringify(json, null, 2);
        fse.outputFileSync(
            descDestPath,
            // format ? JSON.stringify(partDescriptions, null, 2) : JSON.stringify(partDescriptions),
            content,
            'utf-8'
        );
        // Convnert to JS
        convertToJS(descBasename, descDestPath);
    }

    for (let partKey in descriptions) {
        let partDescriptions = descriptions[partKey];

        // Copy ui control config from zh to english.
        if (language === 'zh') {
            languages.forEach(function (otherLang) {
                if (otherLang === 'zh') {
                    return;
                }
                const json = readOptionDesc(otherLang, partKey);
                if (json) {
                    copyUIControlConfigs(partDescriptions, json);
                    writeOptionDesc(otherLang, partKey, json);
                }
            });
        }
        else {
            const json = readOptionDesc('zh', partKey);
            if (json) {
                copyUIControlConfigs(json, partDescriptions);
            }
        }

        writeOptionDesc(language, partKey, partDescriptions);
        // console.log(chalk.green('generated: ' + descDestPath));
    }
};

run();
