const utils = light.util;
const { options, config } = light;
const path = require('path');
const fs = require('fs');
const shell = utils.require('shelljs');
const version = require('./package.json').version;

// 入口文件模板，这段代码在运行时必须最先执行
const vueTemplateFn = utils.template(`
/**AUTO-GEN-START*/
import __VUE__ from "vue"
import __LIGHT__ from "light"
__VUE__.use(__LIGHT__);
__LIGHT__.mainPage = '<%=mainPage%>'
__LIGHT__.onlyFor = '<%=onlyFor%>'
__LIGHT__
<%views.forEach(function(view){%>
.route({
    path: '/<%=view.id%>',
    <%if(view.async=="true"){%>component: ()=>{return import(/* webpackChunkName: "<%=view.chunkname||page+'-'+view.name%>" */"<%=srcDir%>/view/<%=view.id%>.vue")},<%}%>
    <%if(!view.async||view.async=="false"){%>component: require("<%=srcDir%>/view/<%=view.id%>.vue"),<%}%>
    <%if(view.parent){%>parent:"/<%=view.parent%>",<%}%>
    <%if(view.home){%>home:"/<%=view.home%>",<%}%>
    <%for(var key in view){%><%if(['id', 'async', 'parent', 'home', 'chunkname'].indexOf(key) == -1){%><%=key%>: "<%=view[key]%>",<%}%><%}%>
})
<%})%>
/**AUTO-GEN-END*/
`);
// ws模板，用于和http server通信
const htmlWsTemplate = `
<div class="light-loading-check" style="display:none;position: fixed;bottom: 0;top:0;left: 0;right: 0;background-color: rgba(0,0,0,0.5)"></div>
<div class="light-loading-check" style="display:none;position: fixed;top: 50%;left: 50%;transform: translate(-50%,-50%);font-size: 15px;color: #ccc;">加载中...</div>
<script>
var ws = new WebSocket('ws://'+location.host);
if(window.Light) window.Light.Logger.websocket = ws;
ws.onmessage = function(data, flags) {
    switch (data.data) {
        case "holdOn":
            document.querySelectorAll(".light-loading-check").forEach(function(o) {o.style.display = "block";})
            break;
        case "holdOff":
            document.querySelectorAll(".light-loading-check").forEach(function(o) {o.style.display = "none";})
            break;
        case "reload":
            ws.close();
            location.reload();
            break;
    }
};
ws.onopen = function(){
    ws.send(JSON.stringify({type:'currentShow',data:{hash:location.hash,path:location.pathname}}));
}
</script>`;

/**
 * 给project.json注入当前环境信息，包括node、light等
 */
function writeProjectInfo() {
    if (!config.plugins) config['plugins'] = ['type-vue'];
    const plugins = [];
    const basePlugins = [];

    config.plugins.forEach((plugin) => {
        const pluginName = plugin.split('@')[0];
        let pluginVersion = require(utils.join(config.pluginsDir, `node_modules/lighting-plugin-${plugin}/package.json`)).version;
        let basePluginVersion = require(utils.join(config.pluginsDir, `node_modules/lighting-plugin-${pluginName}/package.json`)).version;
        plugins.push(`${pluginName}@${pluginVersion}`);
        pluginVersion !== basePluginVersion && basePlugins.push(`${pluginName}@${basePluginVersion}`);
    });
    
    light.config.lightToolkits = {
        node: process.version,
        lighting: utils.getLightingVersion(),
        plugins,
        basePlugins
    };
    let projectConfigFile  = path.join(config.dist, 'project.json');
    if (utils.existsSync(projectConfigFile)) {
        let projectConfig = require(projectConfigFile);
        projectConfig.lightToolkits = light.config.lightToolkits;
        fs.writeFileSync(projectConfigFile, JSON.stringify(projectConfig, null, 2));
    }
}

/**
 * 准备编译入口文件
 * @param {String} htmlfilePathSrc 入口html文件路径
 * @param {String} htmlFilePathDist 输出html文件路径
 * @param {String} fileName js入口文件名，一般是app
 */
function prepareGmuInstallEntry(htmlfilePathSrc, htmlFilePathDist, fileName) {
    // 处理html路由信息，注入ws
    const $ = utils.require("cheerio").load(utils.readFileSync(htmlfilePathSrc), {
        recognizeSelfClosing: true
    });
    let views = $("view");
    views.first().replaceWith("<router-view></router-view>");
    views.remove();
    // -wb的情况注入socket用于热更新，低版本light会注入ws，兼容高版本light，注入ws由type-vue完成
    options.watch && !options.isLowerLight && $('body').append(htmlWsTemplate);
    // 更新index.html
    utils.writeFileSync(htmlFilePathDist, $.html());
    const viewObj = {
        name: path.basename(htmlFilePathDist, '.html'),
        views: views
    };
    //1.2 根据视图内容生成视图注册的模板，注册路由
    //105231 确定主页名称为app或index并注入Light
    const v = [];
    viewObj.views.each(function (i, view) {
        view.attribs.name = view.attribs.id.replace(/\//g, '-');
        v.push(view.attribs);
    });
    //110579：将onlyFor注入Light，注入srcDir用于编译查找对应的源代码文件
    const vueViewString = vueTemplateFn({ views: v, page: viewObj.name, mainPage: fileName, onlyFor: options.onlyFor, srcDir: config.src.replace(/\\/g, '/') });
    utils.ensureDirSync(path.join(config.dist, 'view'));
    // 更新入口文件，webpack会自动编译刷新
    utils.writeFileSync(path.join(config.dist, 'view', viewObj.name + `.js`), vueViewString);
}

/**
 * 判断light是否低于1.32.0
 * @param {Object} light light编译对象
 * @returns 
 */
function isLowerLight(light) {
    if (!light.util.getLightingVersion) {
        return true;
    }
    const versionArr = light.util.getLightingVersion().split('.');
    const oldVersionArr = [1, 32, 0];
    for (let i = 0; i < versionArr.length; i++) {
        if (Number(versionArr[i]) > oldVersionArr[i]) {
            break;
        }
        if (Number(versionArr[i]) < oldVersionArr[i]) {
            return true;
        }
    }
    return false;
}


module.exports = {
    pluginName: `type-vue@${version}`,
    install: function (light) {
        utils.log('info', `type-vue@${version}插件加载成功`);
    },

    /**
     * 准备阶段
     */
    prepare: function (light, cb) {
        // 修复在lighting工程中执行light searver --debug 时无法正常执行的问题
        var Module = require('module');
        var originalRequire = Module.prototype.require;

        Module.prototype.require = function (m) {
            //do your thing here
            if (m === './JsonpMainTemplatePlugin') {
                return require('./plugins/JsonpMainTemplatePlugin.js')
            }
            return originalRequire.apply(this, arguments);
        };

        utils.ensureDirSync(light.config.dist);
        const htmlFilePathDist = path.resolve(config.dist, 'index.html');
        const htmlFilePathSrc = path.resolve(config.src, 'index.html');
        light.options.isLowerLight = isLowerLight(light);
        if (!options.isLowerLight) {
            // 兼容高版本light的reload监听
            if (options.watch) {
                let shouldReload = false; // 用于判断是否需要reload页面
                const reloadFn = function () {
                    this.plugin('done', function () {
                        if (shouldReload && light.devSockets && light.devSockets.length) {
                            // 如果修改的是index.html或app.js只会触发hot reload，但不会触发页面刷新，这里加个reload进行页面刷新
                            light.devSockets.forEach(function (socket) {
                                if (socket && socket.readyState === 1) socket.send('reload');
                            });
                        }
                        shouldReload = false;
                    });
                };
                if (require('./webpack.config').plugins.indexOf(reloadFn) < 0) {
                    require('./webpack.config').plugins.push(reloadFn);
                }
                // 兼容高版本light，监听src目录下的文件变化
                utils.require('chokidar').watch([htmlFilePathSrc, path.resolve(config.src, 'app.js')]).on('change', function (filePath) {
                    // 主要是监听index.html和app.js，再触发页面刷新
                    shouldReload = true;
                    if (path.extname(filePath) === '.html') {
                        prepareGmuInstallEntry(htmlFilePathSrc, htmlFilePathDist, 'app');
                    }
                });
            }
        }
        prepareGmuInstallEntry(htmlFilePathSrc, htmlFilePathDist, 'app');
        cb();
    },

    /**
     * 编译阶段
     */
    build(light, cb) {
        //2 编译，通过webpack把所有资源整合起来
        new Promise(function (resolve, reject) {
            process.mainModule.paths.push(`${__dirname}/node_modules`);
            return require('./build').build().then(resolve).catch(function(err) {
                console.log('\n' + err.message.red);
                // 生产环境编译失败直接退出，调试时则不处理，也不执行后续打开浏览器等操作
                !options.watch && setTimeout(() => {
                    console.log('\n' + ' ERROR '.white.bgRed + ` Build failed with errors`.red);
                    process.exit(1);
                }, 800);
            });
        }).then(cb);
    },

    /**
     * 打包阶段
     */
    packager(light, cb) {
        // 编译完删除入口文件
        shell.rm('-fr', path.join(config.dist, 'view'));
        shell.rm('-fr', path.join(config.dist, 'ui'));
        shell.rm('-fr', path.join(config.dist, 'html'));
        shell.rm('-fr', path.join(config.dist, 'js'));
        shell.rm('-fr', path.join(config.dist, 'lib'));
        shell.rm('-fr', path.join(config.dist, 'api'));
        shell.rm('-fr', path.join(config.dist, 'plugins'));
        shell.rm('-fr', path.join(config.dist, 'modules'));
        //145355 打包时移除根目录的app.less
        shell.rm("-fr", path.join(config.dist, 'app.less'));
        //114521 【工具】工程根目录中有node_modules目录时移除它
        shell.rm("-fr", path.join(config.dist, 'node_modules'));
        shell.rm("-fr", path.join(config.dist, 'native'));

        shell.cp(path.join(config.src, 'package.json'), path.join(config.dist, 'package.json'));
        shell.cp(path.join(config.src, 'project.json'), path.join(config.dist, 'project.json'));
        //116125【TS:201812210068-财富业委会-潘腾-【需求类型】需求【需求描述】1. light release -p或者-up时，能增加参数支持 不要将某些文件夹打入zip包
        if (options.except) {
            const exceptFolders = options.except.split(',');
            exceptFolders.forEach(function(folder) {
                shell.rm('-fr', path.join(config.dist, folder));
            });
        }
        try {
            writeProjectInfo();
        } catch (err) {
            utils.log('error', err.message.red);
        }
        cb();
    },

    /**
     * 运行阶段
     */
    runtime: function () {

    }
};