/*
* 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.
*/

/**
 * [Create CommonJS files]:
 * Compatible with prevoius folder structure: `echarts/lib` exists in `node_modules`
 * (1) Build all files to CommonJS to `echarts/lib`.
 * (2) Remove __DEV__.
 * (3) Mount `echarts/src/export.js` to `echarts/lib/echarts.js`.
 *
 * [Create ESModule files]:
 * Build all files to CommonJS to `echarts/esm`.
 */

const nodePath = require('path');
const assert = require('assert');
const fs = require('fs');
const fsExtra = require('fs-extra');
const chalk = require('chalk');
const ts = require('typescript');
const globby = require('globby');
const transformDEVUtil = require('./transform-dev');
const preamble = require('./preamble');
const dts = require('@lang/rollup-plugin-dts').default;
const rollup = require('rollup');

const ecDir = nodePath.resolve(__dirname, '..');
const tmpDir = nodePath.resolve(ecDir, 'pre-publish-tmp');

const tsConfig = readTSConfig();

const autoGeneratedFileAlert = `
/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

`;

const mainSrcGlobby = {
    patterns: [
        'src/**/*.ts'
    ],
    cwd: ecDir
};
const extensionSrcGlobby = {
    patterns: [
        'extension-src/**/*.ts'
    ],
    cwd: ecDir
};
const extensionSrcDir = nodePath.resolve(ecDir, 'extension-src');
const extensionESMDir = nodePath.resolve(ecDir, 'extension');

const typesDir = nodePath.resolve(ecDir, 'types');
const esmDir = 'lib';


const compileWorkList = [
    {
        logLabel: 'main ts -> js-esm',
        compilerOptionsOverride: {
            module: 'ES2015',
            rootDir: ecDir,
            outDir: tmpDir,
            // Generate types when buidling esm
            declaration: true,
            declarationDir: typesDir
        },
        srcGlobby: mainSrcGlobby,
        transformOptions: {
            filesGlobby: {patterns: ['**/*.js'], cwd: tmpDir},
            preamble: preamble.js,
            transformDEV: true
        },
        before: async function () {
            fsExtra.removeSync(tmpDir);
            fsExtra.removeSync(nodePath.resolve(ecDir, 'types'));
            fsExtra.removeSync(nodePath.resolve(ecDir, esmDir));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.js'));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.blank.js'));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.common.js'));
            fsExtra.removeSync(nodePath.resolve(ecDir, 'index.simple.js'));
        },
        after: async function () {
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.all.js'), nodePath.resolve(ecDir, 'index.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.blank.js'), nodePath.resolve(ecDir, 'index.blank.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.common.js'), nodePath.resolve(ecDir, 'index.common.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src/echarts.simple.js'), nodePath.resolve(ecDir, 'index.simple.js'));
            fs.renameSync(nodePath.resolve(tmpDir, 'src'), nodePath.resolve(ecDir, esmDir));

            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.js'), esmDir);
            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.blank.js'), esmDir);
            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.common.js'), esmDir);
            transformRootFolderInEntry(nodePath.resolve(ecDir, 'index.simple.js'), esmDir);

            await transformDistributionFiles(nodePath.resolve(ecDir, esmDir), esmDir);
            await transformDistributionFiles(nodePath.resolve(ecDir, 'types'), esmDir);
            fsExtra.removeSync(tmpDir);
        }
    },
    {
        logLabel: 'extension ts -> js-esm',
        compilerOptionsOverride: {
            module: 'ES2015',
            rootDir: extensionSrcDir,
            outDir: extensionESMDir
        },
        srcGlobby: extensionSrcGlobby,
        transformOptions: {
            filesGlobby: {patterns: ['**/*.js'], cwd: extensionESMDir},
            preamble: preamble.js,
            transformDEV: true
        },
        before: async function () {
            fsExtra.removeSync(extensionESMDir);
        },
        after: async function () {
            await transformDistributionFiles(extensionESMDir, 'lib');
        }
    }
];



/**
 * @public
 */
module.exports = async function () {

    for (let {
        logLabel, compilerOptionsOverride, srcGlobby,
        transformOptions, before, after
    } of compileWorkList) {

        process.stdout.write(chalk.green.dim(`[${logLabel}]: compiling ...`));

        before && await before();

        let srcPathList = await readFilePaths(srcGlobby);

        await tsCompile(compilerOptionsOverride, srcPathList);

        process.stdout.write(chalk.green.dim(` done \n`));

        process.stdout.write(chalk.green.dim(`[${logLabel}]: transforming ...`));

        await transformCode(transformOptions);

        after && await after();

        process.stdout.write(chalk.green.dim(` done \n`));
    }

    process.stdout.write(chalk.green.dim(`Generating entries ...`));
    generateEntries();
    process.stdout.write(chalk.green.dim(`Bundling DTS ...`));
    await bundleDTS();

    console.log(chalk.green.dim('All done.'));
};

async function runTsCompile(localTs, compilerOptions, srcPathList) {
    // Must do it. becuase the value in tsconfig.json might be different from the inner representation.
    // For example: moduleResolution: "NODE" => moduleResolution: 2
    const {options, errors} = localTs.convertCompilerOptionsFromJson(compilerOptions, ecDir);

    if (errors.length) {
        let errMsg = 'tsconfig parse failed: '
            + errors.map(error => error.messageText).join('. ')
            + '\n compilerOptions: \n' + JSON.stringify(compilerOptions, null, 4);
        assert(false, errMsg);
    }

    // See: https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API

    let program = localTs.createProgram(srcPathList, options);
    let emitResult = program.emit();

    let allDiagnostics = localTs
        .getPreEmitDiagnostics(program)
        .concat(emitResult.diagnostics);

    allDiagnostics.forEach(diagnostic => {
        if (diagnostic.file) {
            let {line, character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
            let message = localTs.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
            console.log(chalk.red(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`));
        }
        else {
            console.log(chalk.red(localTs.flattenDiagnosticMessageText(diagnostic.messageText, '\n')));
        }
    });
    assert(!emitResult.emitSkipped, 'ts compile failed.');
}
module.exports.runTsCompile = runTsCompile;

async function tsCompile(compilerOptionsOverride, srcPathList) {
    assert(
        compilerOptionsOverride
        && compilerOptionsOverride.module
        && compilerOptionsOverride.rootDir
        && compilerOptionsOverride.outDir
    );

    let compilerOptions = {
        ...tsConfig.compilerOptions,
        ...compilerOptionsOverride
        // sourceMap: true
    };

    runTsCompile(ts, compilerOptions, srcPathList);
}

/**
 * Transform import/require path in the entry file to `esm` or `lib`.
 */
function transformRootFolderInEntry(entryFile, replacement) {
    let code = fs.readFileSync(entryFile, 'utf-8');
    // Simple regex replacement
    // TODO More robust way?
    assert(
        !/(import\s+|from\s+|require\(\s*)["']\.\/echarts\./.test(code)
        && !/(import\s+|from\s+|require\(\s*)["']echarts\./.test(code),
        'Import echarts.xxx.ts is not supported.'
    );
    code = code.replace(/((import\s+|from\s+|require\(\s*)["'])\.\//g, `$1./${replacement}/`);
    fs.writeFileSync(
        entryFile,
        // Also transform zrender.
        singleTransformZRRootFolder(code, replacement),
        'utf-8'
    );
}

/**
 * Transform `zrender/src` to `zrender/esm` in all files
 */
async function transformDistributionFiles(rooltFolder, replacement) {
    const files = await readFilePaths({
        patterns: ['**/*.js', '**/*.d.ts'],
        cwd: rooltFolder
    });
    // Simple regex replacement
    // TODO More robust way?
    for (let fileName of files) {
        let code = fs.readFileSync(fileName, 'utf-8');
        code = singleTransformZRRootFolder(code, replacement);
        // For lower ts version, not use import type
        // TODO Use https://github.com/sandersn/downlevel-dts ?
        // if (fileName.endsWith('.d.ts')) {
        //     code = singleTransformImportType(code);
        // }
        fs.writeFileSync(fileName, code, 'utf-8');
    }
}

/**
 * Remove __esModule mark.
 *
 * In the 4.x version. The exported CJS don't have __esModule mark.
 * Developers can use `import echarts from 'echarts/lib/echarts' instead of
 * `import * as echarts from 'echarts/lib/echarts'` to import all the exported methods.
 * It's not recommand but developers may still have the chance to do it.
 * But in the tsc export with __esModule mark. This will get an undefined export.
 * To avoid breaking this kind of code. We remove __esModule mark manually here.
 */
function removeESmoduleMark() {
    const filePath = nodePath.resolve(ecDir, 'lib/echarts.js');
    const code = fs.readFileSync(filePath, 'utf-8')
        .replace('\nexports.__esModule = true;\n', '');
    if (code.indexOf('__esModule') >= 0) {
        throw new Error('Seems still has __esModule mark');
    }
    fs.writeFileSync(filePath, code, 'utf-8');
}

function singleTransformZRRootFolder(code, replacement) {
    return code.replace(/([\"\'])zrender\/src\//g, `$1zrender/${replacement}/`);
}

// function singleTransformImportType(code) {
//     return code.replace(/import\s+type\s+/g, 'import ');
// }

/**
 * @param {Object} transformOptions
 * @param {Object} transformOptions.filesGlobby {patterns: string[], cwd: string}
 * @param {string} [transformOptions.preamble] See './preamble.js'
 * @param {boolean} [transformOptions.transformDEV]
 */
async function transformCode({filesGlobby, preamble, transformDEV}) {

    let filePaths = await readFilePaths(filesGlobby);

    filePaths.map(filePath => {
        let code = fs.readFileSync(filePath, 'utf8');

        if (transformDEV) {
            let result = transformDEVUtil.transform(code, false);
            code = result.code;
        }

        code = autoGeneratedFileAlert + code;

        if (preamble) {
            code = preamble + code;
        }

        fs.writeFileSync(filePath, code, 'utf8');
    });
}

async function readFilePaths({patterns, cwd}) {
    assert(patterns && cwd);
    return (
        await globby(patterns, {cwd})
    ).map(
        srcPath => nodePath.resolve(cwd, srcPath)
    );
}

async function bundleDTS() {

    const outDir = nodePath.resolve(__dirname, '../types/dist');
    const commonConfig = {
        onwarn(warning, rollupWarn) {
            // Not warn circular dependency
            if (warning.code !== 'CIRCULAR_DEPENDENCY') {
                rollupWarn(warning);
            }
        },
        plugins: [
            dts({
                respectExternal: true
            })
//             {
//                 generateBundle(options, bundle) {
//                     for (let chunk of Object.values(bundle)) {
//                         chunk.code = `
// type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
// ${chunk.code}`
//                     }
//                 }
//             }
        ]
    };

    // Bundle chunks.
    const parts = [
        'core', 'charts', 'components', 'renderers', 'option'
    ];
    const inputs = {};
    parts.forEach(partName => {
        inputs[partName] = nodePath.resolve(__dirname, `../types/src/export/${partName}.d.ts`)
    });

    const bundle = await rollup.rollup({
        input: inputs,
        ...commonConfig
    });
    let idx = 1;
    await bundle.write({
        dir: outDir,
        minifyInternalExports: false,
        manualChunks: (id) => {
            // Only create one chunk.
            return 'shared';
        },
        chunkFileNames: 'shared.d.ts'
    });

    // Bundle all in one
    const bundleAllInOne = await rollup.rollup({
        input: nodePath.resolve(__dirname, `../types/src/export/all.d.ts`),
        ...commonConfig
    });
    await bundleAllInOne.write({
        file: nodePath.resolve(outDir, 'echarts.d.ts')
    });
}

function readTSConfig() {
    // tsconfig.json may have comment string, which is invalid if
    // using `require('tsconfig.json'). So we use a loose parser.
    let filePath = nodePath.resolve(ecDir, 'tsconfig.json');
    const tsConfigText = fs.readFileSync(filePath, {encoding: 'utf8'});
    return (new Function(`return ( ${tsConfigText} )`))();
}


function generateEntries() {
    ['charts', 'components', 'renderers', 'core'].forEach(entryName => {
        if (entryName !== 'option') {
            const jsCode = fs.readFileSync(nodePath.join(__dirname, `template/${entryName}.js`), 'utf-8');
            fs.writeFileSync(nodePath.join(__dirname, `../${entryName}.js`), jsCode, 'utf-8');
        }

        const dtsCode = fs.readFileSync(nodePath.join(__dirname, `/template/${entryName}.d.ts`), 'utf-8');
        fs.writeFileSync(nodePath.join(__dirname, `../${entryName}.d.ts`), dtsCode, 'utf-8');
    });
}

module.exports.readTSConfig = readTSConfig;
