#!/usr/bin/env node

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

const fs = require('fs');
const config = require('./config.js');
const commander = require('commander');
const chalk = require('chalk');
const rollup = require('rollup');
const prePublish = require('./pre-publish');
const transformDEV = require('./transform-dev');
const preamble = require('./preamble');

async function run() {

    /**
     * Tips for `commander`:
     * (1) If arg xxx not specified, `commander.xxx` is undefined.
     *     Otherwise:
     *      If '-x, --xxx', `commander.xxx` can only be true/false, even if '--xxx yyy' input.
     *      If '-x, --xxx <some>', the 'some' string is required, or otherwise error will be thrown.
     *      If '-x, --xxx [some]', the 'some' string is optional, that is, `commander.xxx` can be boolean or string.
     * (2) `node ./build/build.js --help` will print helper info and exit.
     */

    let descIndent = '                                 ';
    let egIndent = '    ';

    commander
        .usage('[options]')
        .description([
            'Build echarts and generate result files in directory `echarts/dist`.',
            '',
            '  For example:',
            '',
            egIndent + 'node build/build.js --prepublish'
                + '\n' + descIndent + '# Only prepublish.',
            egIndent + 'node build/build.js --type ""'
                + '\n' + descIndent + '# Only generate `dist/echarts.js`.',
            egIndent + 'node build/build.js --type common --min'
                + '\n' + descIndent + '# Only generate `dist/echarts.common.min.js`.',
            egIndent + 'node build/build.js --type simple --min'
                + '\n' + descIndent + '# Only generate `dist/echarts-en.simple.min.js`.',
        ].join('\n'))
        .option(
            '--prepublish',
            'Build all for release'
        )
        .option(
            '--min',
            'Whether to compress the output file, and remove error-log-print code.'
        )
        .option(
            '--type <type name>', [
            'Can be "simple" or "common" or "all" (default). Or can be simple,common,all to build multiple. For example,',
            descIndent + '`--type ""` or `--type "common"`.'
        ].join('\n'))
        .option(
            '--format <format>',
            'The format of output bundle. Can be "umd", "amd", "iife", "cjs", "esm".'
        )
        .parse(process.argv);

    let isPrePublish = !!commander.prepublish;
    let buildType = commander.type || 'all';

    let opt = {
        min: commander.min,
        format: commander.format || 'umd'
    };

    validateIO(opt.input, opt.output);

    if (isPrePublish) {
        await prePublish();
    }
    else if (buildType === 'extension') {
        const cfgs = [
            config.createBMap(opt),
            config.createDataTool(opt)
        ];
        await build(cfgs);
    }
    else if (buildType === 'myTransform') {
        const cfgs = [
            config.createMyTransform(opt)
        ];
        await build(cfgs);
    }
    else {
        const types = buildType.split(',').map(a => a.trim());
        const cfgs = types.map(type =>
            config.createECharts({
                ...opt,
                type
            })
        );
        await build(cfgs);
    }
}

function checkBundleCode(cfg) {
    // Make sure process.env.NODE_ENV is eliminated.
    for (let output of cfg.output) {
        let code = fs.readFileSync(output.file, {encoding: 'utf-8'});
        if (!code) {
            throw new Error(`${output.file} is empty`);
        }
        transformDEV.recheckDEV(code);
        console.log(chalk.green.dim('Check code: correct.'));
    }
}

function validateIO(input, output) {
    if ((input != null && output == null)
        || (input == null && output != null)
    ) {
        throw new Error('`input` and `output` must be both set.');
    }
}

/**
 * @param {Array.<Object>} configs A list of rollup configs:
 *  See: <https://rollupjs.org/#big-list-of-options>
 *  For example:
 *  [
 *      {
 *          ...inputOptions,
 *          output: [outputOptions],
 *      },
 *      ...
 *  ]
 */
async function build(configs) {
    console.log(chalk.yellow(`
    NOTICE: If you are using 'npm run build'. Run 'npm run prepublish' before build !!!
`));

    console.log(chalk.yellow(`
    NOTICE: If you are using syslink on zrender. Run 'npm run prepublish' in zrender first !!
`));

    for (let singleConfig of configs) {
        console.log(
            chalk.cyan.dim('\Bundling '),
            chalk.cyan(singleConfig.input)
        );

        console.time('rollup build');
        const bundle = await rollup.rollup(singleConfig);

        for (let output of singleConfig.output) {
            console.log(
                chalk.green.dim('Created '),
                chalk.green(output.file),
                chalk.green.dim(' successfully.')
            );

            await bundle.write(output);

        };
        console.timeEnd('rollup build');

        checkBundleCode(singleConfig);
    }
}

async function main() {
    try {
        await run();
    }
    catch (err) {
        console.log(chalk.red('BUILD ERROR!'));
        // rollup parse error.
        if (err) {
            if (err.loc) {
                console.warn(chalk.red(`${err.loc.file} (${err.loc.line}:${err.loc.column})`));
                console.warn(chalk.red(err.message));
            }
            if (err.frame) {
                console.warn(chalk.red(err.frame));
            }
            console.log(chalk.red(err ? err.stack : err));

            err.id != null && console.warn(chalk.red(`id: ${err.id}`));
            err.hook != null && console.warn(chalk.red(`hook: ${err.hook}`));
            err.code != null && console.warn(chalk.red(`code: ${err.code}`));
            err.plugin != null && console.warn(chalk.red(`plugin: ${err.plugin}`));
        }
        // console.log(err);
    }
}

main();
