const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const vueLoaderConfig = require('../vue-loader.conf');
const { _config } = require('../getBlConfig');
const jsonConditionalCompilation = require('../jsonConditionalCompilation');
const VirtualModulePlugin = require('virtual-module-webpack-plugin');

module.exports = (ROOT, SRC, mode = 'production') => {
    const DIST = path.join(ROOT, _config, 'dist');

    let blConfig = { isUni: true };

    if (fs.existsSync(path.join(ROOT, 'bl.config.js'))) {
        blConfig = require(path.join(ROOT, 'bl.config.js'));
        if (blConfig.isUni === undefined) {
            blConfig.isUni = true;
        }
    }

    let appJson = fs.readFileSync(path.join(SRC, 'app.json'), 'utf8');
    let _jsonData = JSON.parse(appJson)

    let entries = {};

    _jsonData.pages.forEach((conf) => {
        entries[conf.path + '/'] = `./src${conf.path}/index.js`; // ./src...
    });

    // 读取预处理文件
    let splitPage = fs.readFileSync(path.resolve(__dirname, './splitPage.js'), 'utf8');

    let virtualEntries = [];
    Object.keys(entries).forEach(name => {
        if (name !== '/') {
            let path = entries[name];
            virtualEntries.push({
                moduleName: path,
                contents: splitPage.replace(/BILIPAGE/g, name.slice(0, -1))
            });
        }
    });

    appJson = jsonConditionalCompilation({
        content: appJson,
        platform: 'bl'
    });

    let _minChunk = 2;
    if (_jsonData['_splitPackage'] && _jsonData['_splitPackage'].minChunks) {
        if (!isNaN(_jsonData['_splitPackage'].minChunks) && _jsonData['_splitPackage'].minChunks >= 2) {
            _minChunk = _jsonData['_splitPackage'].minChunks
        }
    }

    const configs = {
        node: {
            fs: 'empty'
        },
        mode: mode,
        entry: entries,
        output: {
            globalObject: 'this',
            filename: '[name]service.js',
            chunkFilename: '[name].service.js',
            path: DIST,
        },
        module: {
            rules: [
                {
                    test: /node_modules\/three/,
                    use: [
                        {
                            loader: path.resolve(
                                __dirname,
                                "../loaders/threejs-loader"
                            ),
                        },
                    ],
                },
                {
                test: /\.vue$/,
                use: [
                    { loader: path.resolve(__dirname, '../loaders/uni-vue-post-loader')},
                    { loader: path.resolve(__dirname, '../loaders/bl-sapp-service-post-loader') },
                    {
                        loader: 'vue-loader',
                        options: vueLoaderConfig,
                    },
                    { loader: path.resolve(__dirname, '../loaders/bl-sapp-service-pre-loader') },
                    // { loader: 'vue-blservice-loader' },
                    // {
                    //     loader: 'uni-vue-loader',
                    //     options: {
                    //         platform: 'bl',
                    //         isUni: blConfig.isUni
                    //     }
                    // }
                ],
            },
            {
                test: /\.js$/,
                use: [{
                    loader: 'babel-loader'
                },
                {
                    loader: 'uni-js-loader',
                    options: {
                        platform: 'bl'
                    }
                }
                ],
                include: [
                    SRC,
                    path.join(
                        ROOT,
                        'node_modules',
                        'bili-small-app',
                        'runtime'
                    ),
                    path.join(
                        ROOT,
                        'node_modules',
                        'bili-small-app',
                        'components'
                    ),
                ]
            },
            {
                test: /\.ts$/,
                use: [{
                    loader: 'babel-loader'
                },
                {
                    loader: 'uni-js-loader',
                    options: {
                        platform: 'bl'
                    }
                }, {
                    loader: 'ts-loader',
                    options: {
                        transpileOnly: true,
                        appendTsSuffixTo: [
                            '\\.vue$'
                        ]
                    }
                }]
            },
            {
                test: /\.(png|jpe?g|gif|svg)$/,
                loader: 'null-loader',
            },
            {
                test: /service\.js$/,
                use: [
                    { loader: 'babel-loader' },
                    { loader: path.resolve(__dirname, '../splitChunksConfig/service-loader')},
                ],
            },
            {
                test: /small-app[/\\]runtime[/\\]bl/,
                use: [
                    { loader: 'babel-loader' },
                    {
                        loader: 'string-replace-loader',
                        options: {
                            search: '__BLJS__',
                            replace: "import bl from './bl.app'",
                            flags: 'g',
                        },
                    },
                ],
            },
            {
                test: /\.pug$/,
                oneOf: [
                    // 这条规则应用到 Vue 组件内的 `<template lang="pug">`
                    {
                        resourceQuery: /^\?vue/,
                        use: [
                            { 
                                loader: path.resolve(__dirname, '../loaders/uni-vue-post-loader')
                            },
                            'pug-plain-loader'
                        ]
                    },
                    // 这条规则应用到 JavaScript 内的 pug 导入
                    {
                        use: ['raw-loader', 'pug-plain-loader']
                    }
                ]
            },
            {
                test: /\.json$/,
                use: [{
                    loader: 'uni-json-loader',
                    options: {
                        platform: 'bl'
                    }
                }],
            },
            {
                test: /\.css$/,
                use: [
                    'null-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'null-loader'
                ]
            },
            {
                test: /\.styl$/,
                use: [
                    'null-loader'
                ]
            },
            ],
        },
        resolve: {
            extensions: ['.js', '.vue', '.json', '.styl'],
            alias: {
                '@': ROOT,
                '%': SRC
            },
            mainFields: ['main']
        },
        plugins: [
            new VueLoaderPlugin(),
            new webpack.DefinePlugin({
                GLOBAL_OBJECT: 'Service',
                IS_SMALL_GAME: 'false',
                'process.env': require('../config').env,
                APPID: '"' + JSON.parse(fs.readFileSync(path.join(ROOT, _config, '.sapprc'), 'utf8')).appId + '"',
                APP_JSON: appJson
                // IS_DEV: String(mode === 'development'),
                // IP: '"' + getIpAddress() + '"'
            }),
            ...virtualEntries.map(options => new VirtualModulePlugin(options))
        ],
        externals: {
            vue: 'Vue',
            'bili-small-app': "bili-small-app"
        },
        optimization: {
            usedExports: true,
            splitChunks: {
                cacheGroups: {
                    commons: {
                        name: 'common',
                        chunks: 'initial',
                        minChunks: _minChunk
                    }
                }
            },
            // 生产模式下，也给模块有意义的名称代替id，因为webpack源码修改过，require里的moduleId都是路径，不是id(数字)
            namedModules: true,
            // 生产模式下，也给chunk有意义的名称代替id
            namedChunks: true
        }
    };
    if (process.env.BL_NOMIN) {
        configs.optimization = {
            minimize: false
        };
    }
    return configs;
};
