const gulp = require('gulp');
// gulp core function
const { src, dest, series, parallel, watch } = require('gulp');
// gulp compress js
const uglify = require('gulp-uglify');
// gulp judgment
const gulpif = require('gulp-if');
// gulp compress css
const cleanCSS = require('gulp-clean-css');
// Delete Files
const del = require('delete');
// Refresh the browser in real time
const browserSync = require('browser-sync').create();
const reload = browserSync.reload;
// proxy
const { createProxyMiddleware } = require('http-proxy-middleware');
// According to html reference, files are merged
// const useref = require('gulp-useref');
// File merge
const concat = require('gulp-concat');
// rollup packaging, processing es6 modules
const { rollup } = require('rollup');
// rollup looks for node_modules module
const { nodeResolve } = require('@rollup/plugin-node-resolve');
// rollup converts commonjs module to es6 module
const commonjs = require('@rollup/plugin-commonjs');
// rollup code compression
const terser = require('rollup-plugin-terser').terser;
// rollup babel plugin, support the latest ES grammar
const babel = require('@rollup/plugin-babel').default;
// const gulpBabel = require('gulp-babel');
// Distinguish development and production environments
const production = process.env.NODE_ENV === 'production' ? true : false;

// uglify js Compression configuration https://github.com/mishoo/UglifyJS#minify-options
const uglifyOptions = {
    compress: {
        drop_console: true
    }
}

// babel config
const babelConfig = {
    compact:false,
    babelHelpers: 'bundled',
    exclude: 'node_modules/**', // Only compile our source code
    plugins: [
    ],
    presets: [
        ['@babel/preset-env', {
            useBuiltIns: 'usage',
            corejs: 3,
            targets: {
                chrome: 58,
                ie: 11
            }
        }]
    ]
};

// file handler paths
const paths = {
    // static resources,contains index.html, fonts and images,and extension plugins dependency
    staticHtml: ['src/*.html'],
    staticFonts: ['src/fonts/**'],
    staticAssets: ['src/assets/**'],
    staticImages: ['src/plugins/images/*.png'],
    staticExpendPlugins: ['src/expendPlugins/**', '!src/expendPlugins/**/plugin.js'],
    staticDemoData: ['src/demoData/*.js'],
    staticCssImages: ['src/css/**','!src/css/*.css'],

    // static resources dest
    destStaticHtml: ['dist'],
    destStaticFonts: ['dist/fonts'],
    destStaticAssets: ['dist/assets'],
    destStaticImages: ['dist/plugins/images'],
    destStaticExpendPlugins: ['dist/expendPlugins'],
    destStaticDemoData: ['dist/demoData'],
    destStaticCssImages: ['dist/css'],

    //core es module
    core: ['src/**/*.js','!src/demoData/*.js','src/expendPlugins/**/plugin.js','!src/plugins/js/*.js'],

     //plugins src
    pluginsCss: ['src/plugins/css/*.css'],
    plugins: ['src/plugins/*.css'],
    css:['src/css/*.css','node_modules/flatpickr/dist/themes/light.css'],
    pluginsJs:[
        'node_modules/jquery/dist/jquery.min.js',
        'src/plugins/js/clipboard.min.js',
        'src/plugins/js/spectrum.min.js',
        'src/plugins/js/jquery-ui.min.js',
        'src/plugins/js/jquery.mousewheel.min.js',
        // 'src/plugins/js/numeral.min.js',
        'src/plugins/js/html2canvas.min.js',
        'src/plugins/js/localforage.min.js',
        'src/plugins/js/lodash.min.js',
        'src/plugins/js/jstat.min.js',
        'src/plugins/js/crypto-api.min.js'
    ],

    //plugins concat
    concatPluginsCss: 'pluginsCss.css',
    concatPlugins: 'plugins.css',
    concatCss: 'luckysheet.css',
    concatPluginsJs: 'plugin.js',

    //plugins dest
    destPluginsCss: ['dist/plugins/css'],
    destPlugins: ['dist/plugins'],
    destCss: ['dist/css'],
    destPluginsJs: ['dist/plugins/js'],

    // Package directory
    dist: 'dist',
};

// Clear the dist directory
function clean() {
    return del([paths.dist]);
}

// proxy middleware
const apiProxy = createProxyMiddleware('/luckysheet/', {
    target: 'http://luckysheet.lashuju.com/', // set your server address
    changeOrigin: true, // for vhosted sites
    ws: true, // proxy websockets
});

// Static server
function serve(done) {
    browserSync.init({
        server: {
            baseDir: paths.dist,
            middleware: [apiProxy],//proxy
        },
        ghostMode: false, //默认true，滚动和表单在任何设备上输入将被镜像到所有设备里，会影响本地的协同编辑消息，故关闭
    }, done)
}

// Monitoring file changes
function watcher(done) {
    watch(paths.core,{ delay: 500 }, series(core, reloadBrowser));

    // watch plugins and css
    watch(paths.pluginsCss,{ delay: 500 }, series(pluginsCss, reloadBrowser));
    watch(paths.plugins,{ delay: 500 }, series(plugins, reloadBrowser));
    watch(paths.css,{ delay: 500 }, series(css, reloadBrowser));
    watch(paths.pluginsJs,{ delay: 500 }, series(pluginsJs, reloadBrowser));

    // watch static
    watch(paths.staticHtml,{ delay: 500 }, series(copyStaticHtml, reloadBrowser));
    watch(paths.staticFonts,{ delay: 500 }, series(copyStaticFonts, reloadBrowser));
    watch(paths.staticAssets,{ delay: 500 }, series(copyStaticAssets, reloadBrowser));
    watch(paths.staticImages,{ delay: 500 }, series(copyStaticImages, reloadBrowser));
    watch(paths.staticExpendPlugins,{ delay: 500 }, series(copyStaticExpendPlugins, reloadBrowser));
    watch(paths.staticDemoData,{ delay: 500 }, series(copyStaticDemoData, reloadBrowser));
    watch(paths.staticCssImages,{ delay: 500 }, series(copyStaticCssImages, reloadBrowser));

    done();
}

// Refresh browser
function reloadBrowser(done) {
    reload();

    done();
}

//Package the core code
async function core() {
    const bundle = await rollup({
        input: 'src/index.js',
        plugins: [
            nodeResolve(), // tells Rollup how to find date-fns in node_modules
            commonjs(), // converts date-fns to ES modules
            // postcss({
            // 	plugins: [],
            // 	extract: true,
            // 	// minimize: isProductionEnv,
            // }),
            production && terser(), // minify, but only in production
            babel(babelConfig)
        ],
    });

    bundle.write({
        file: 'dist/luckysheet.umd.js',
        format: 'umd',
        name: 'luckysheet',
        sourcemap: true,
        inlineDynamicImports:true,

    });

    if(production){
        bundle.write({
            file: 'dist/luckysheet.esm.js',
            format: 'esm',
            name: 'luckysheet',
            sourcemap: true,
            inlineDynamicImports:true,
        });
    }

}

// According to the build tag in html, package js and css
function pluginsCss() {
    return src(paths.pluginsCss)
        .pipe(concat(paths.concatPluginsCss))
        .pipe(gulpif(production, cleanCSS()))
        .pipe(dest(paths.destPluginsCss))

}

function plugins() {
    return src(paths.plugins)
        .pipe(concat(paths.concatPlugins))
        .pipe(gulpif(production, cleanCSS()))
        .pipe(dest(paths.destPlugins));
}

function css() {
    return  src(paths.css)
        .pipe(concat(paths.concatCss))
        .pipe(gulpif(production, cleanCSS()))
        .pipe(dest(paths.destCss));
}

function pluginsJs() {
    return  src(paths.pluginsJs)
        .pipe(concat(paths.concatPluginsJs))
        .pipe(gulpif(production, uglify(uglifyOptions)))
        .pipe(dest(paths.destPluginsJs));
}

// Copy static resources
function copyStaticHtml(){
    return src(paths.staticHtml)
        .pipe(dest(paths.destStaticHtml));
}
function copyStaticFonts(){
    return src(paths.staticFonts)
        .pipe(dest(paths.destStaticFonts));
}
function copyStaticAssets(){
    return src(paths.staticAssets)
        .pipe(dest(paths.destStaticAssets));
}
function copyStaticImages(){
    return src(paths.staticImages)
        .pipe(dest(paths.destStaticImages));
}
function copyStaticExpendPlugins(){
    return src(paths.staticExpendPlugins)
        .pipe(dest(paths.destStaticExpendPlugins));
}
function copyStaticDemoData(){
    return src(paths.staticDemoData)
        .pipe(dest(paths.destStaticDemoData));
        // .pipe(gulpBabel({
        //     presets: ['@babel/env']
        // }))
        // .pipe(gulp.dest('dist'));
}
function copyStaticCssImages(){
    return src(paths.staticCssImages)
        .pipe(dest(paths.destStaticCssImages));
}

const dev = series(clean, parallel(pluginsCss, plugins, css, pluginsJs, copyStaticHtml, copyStaticFonts, copyStaticAssets, copyStaticImages, copyStaticExpendPlugins, copyStaticDemoData, copyStaticCssImages, core), watcher, serve);
const build = series(clean, parallel(pluginsCss, plugins, css, pluginsJs, copyStaticHtml, copyStaticFonts, copyStaticAssets, copyStaticImages, copyStaticExpendPlugins, copyStaticDemoData, copyStaticCssImages, core));

exports.dev = dev;
exports.build = build;
exports.default = dev;
