/*
* 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 { transformImport } = require('zrender/build/transformImport');

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 transformLibFiles(nodePath.resolve(ecDir, esmDir), esmDir);
            await transformLibFiles(nodePath.resolve(ecDir, 'types'), esmDir);
            fsExtra.removeSync(tmpDir);
        }
    },
    {
        logLabel: 'extension ts -> js-esm',
        compilerOptionsOverride: {
            module: 'ES2015',
            declaration: false,
            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 transformLibFiles(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 ...\n`));
    generateEntries();
    process.stdout.write(chalk.green.dim(`Bundling DTS ...\n`));
    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')));
        }
    });
    if (allDiagnostics.length > 0) {
        throw new Error('TypeScript 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: false
    };

    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.
        singleTransformImport(code, replacement),
        'utf-8'
    );
}

/**
 * Transform `zrender/src` to `zrender/lib` in all files
 */
async function transformLibFiles(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 = singleTransformImport(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');
    }
}

/**
 * 1. Transform zrender/src to zrender/lib
 * 2. Add .js extensions
 */
function singleTransformImport(code, replacement) {
    return transformImport(
        code.replace(/([\"\'])zrender\/src\//g, `$1zrender/${replacement}/`),
        (moduleName) => {
            // Ignore 'tslib' and 'echarts' in the extensions.
            if (moduleName === 'tslib' || moduleName === 'echarts') {
                return moduleName;
            }
            else if (moduleName === 'zrender/lib/export') {
                throw new Error('Should not import the whole zrender library.');
            }
            else if (moduleName.endsWith('.ts')) {
                // Replace ts with js
                return moduleName.replace(/\.ts$/, '.js');
            }
            else if (moduleName.endsWith('.js')) {
                return moduleName;
            }
            else {
                return moduleName + '.js'
            }
        }
    );
}

// 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', 'features', 'extensionHelper'
    ];
    const inputs = {};
    parts.forEach(partName => {
        inputs[partName] = nodePath.resolve(__dirname, `../types/src/export/${partName}.d.ts`)
    });

    const bundle = await rollup.rollup({
        input: inputs,
        ...commonConfig
    });

    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', 'features', 'extensionHelper'].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;
