const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const config = require('./server/config');

const staticPath = config.app.assets;
const freezePath = config.app.freezePath;

const DEFAULT_ENV = 'development';

const VALID_ENVS = [
    'development',
    'production',
    'qa',
    'integration-qa',
    'prestable',
    'testing',
    'corp',
    'corp-qa',
    'corp-prestable',
    'corp-testing',
];

const hmrEnabled = process.env.HOT_RELOAD;
const configEnv = VALID_ENVS.indexOf(config.app.env) === -1 ? DEFAULT_ENV : config.app.env;

const vendor = {
    basic: [
        // function/name fixes Immutable.fromJS() in IE (DIR-9378)
        // https://github.com/immutable-js/immutable-js/issues/1648#issuecomment-448363393
        'core-js/features/function/name',
        'core-js/features/object/assign',
        'core-js/features/object/entries',
        'core-js/features/object/values',
        'core-js/features/promise',
        'core-js/features/symbol',
        'core-js/features/set',
        'core-js/features/map',
        'core-js/features/array/from',
        'core-js/features/array/find',
        'core-js/features/array/includes',
        'core-js/features/string/includes',
        'core-js/features/string/starts-with',
        'core-js/features/number/is-nan',
        'core-js/features/number/max-safe-integer',
        'core-js/web/url',
        'core-js/web/url-search-params',
        'whatwg-fetch',
    ],
    legacy: [
        'lodash',
        'react-addons-pure-render-mixin',
        'rsvp',
    ],
};

function getClientPath() {
    return path.join.apply(path, [__dirname, 'client'].concat([].slice.call(arguments)));
}

function getLayoutEntries(layouts) {
    return layouts.reduce((result, layout) => {
        const files = [`./client/layouts/${layout}.js`];

        if (hmrEnabled) {
            files.push('webpack-hot-middleware/client');
        }

        return {
            ...result,
            [layout]: files,
        };
    }, {});
}

const rules = [
    {
        test: /\.jsx?$/,
        use: [
            'babel-loader',
            `preprocess-loader?NODE_ENV=${configEnv}`,
        ],
        exclude: /node_modules(?!\/(ui-components|lego-on-react|@yandex-int|@connect))/,
    },
];

if (hmrEnabled) {
    const styleLoaderOpts = {
        loader: 'style-loader',
        options: {
            attributes: {
                nonce: config.app.devNonce,
            },
        },
    };

    rules.push(
        {
            test: /\.css$/,
            use: [styleLoaderOpts, 'css-loader', 'postcss-loader'],
        },
        {
            test: /\.styl$/,
            use: [
                styleLoaderOpts,
                'css-loader',
                'postcss-loader',
                'stylus-loader',
            ],
        },
        {
            test: /\.(png|svg|csv|eot|gif)(?:\?[\s\S]*)?/,
            use: [
                'file-loader',
            ],
        }
    );
} else {
    rules.push(
        {
            test: /\.css$/,
            use: [
                MiniCssExtractPlugin.loader,
                'css-loader',
                'postcss-loader',
            ],
        },
        {
            test: /\.styl$/,
            use: [
                MiniCssExtractPlugin.loader,
                'css-loader',
                'postcss-loader',
                'stylus-loader',
            ],
        },
        {
            test: /\.(png|svg|csv|eot|gif)(?:\?[\s\S]*)?/,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        outputPath: '../_/',
                        publicPath: `${freezePath}/`,
                        name: '[sha1:hash:base58:8].[ext]',
                    },
                },
            ],
        },
        {
            test: /\.svg$/,
            use: [
                'svgo-loader',
            ],
        }
    );
}

rules.push(
    {
        test: /\.(woff2?|ttf)$/,
        use: {
            loader: 'file-loader',
            options: {
                name: '[name].[ext]',
                outputPath: 'fonts/',
            },
        },
    },
    {
        test: /\.dot$/,
        loader: 'dot-loader',
    }
);

module.exports = {
    mode: configEnv === 'development' ? 'development' : 'production',
    entry: {
        // https://github.yandex-team.ru/RUM/rum-counter#Внешний-код
        rum: [
            '@yandex-int/rum-counter/dist/bundle/send',
            '@yandex-int/rum-counter/dist/bundle/implementation',
            '@yandex-int/rum-counter/dist/bundle/onload',
        ],
        'rum.debug': [
            '@yandex-int/rum-counter/debug/blockstat',
        ],
        vendor: [
            ...vendor.legacy,
            ...vendor.basic,
        ],
        'vendor.basic': vendor.basic,
        ...getLayoutEntries([
            'index',
            'home',
            'profile',
            'context',
            'services',
            'forbidden',
            'registration',
            'invites',
            'bindWidgetFakePage',
            'bindWidget',
            'bindPromo',
            'onboarding',
        ]),
    },
    output: {
        path: path.join(__dirname, 'build', 'static'),
        filename: '[name].js',
        publicPath: `${staticPath}/`,
    },
    devtool: config.app.isProd ? 'hidden-source-map' : 'eval-source-map',
    module: {
        rules,
    },
    externals: {
        jquery: 'jQuery',
        react: 'React',
        'react-dom': 'ReactDOM',
        moment: 'moment',
    },
    resolve: {
        alias: {
            client: getClientPath(),
            actions: getClientPath('actions'),
            components: getClientPath('components'),
            components2: getClientPath('components2'),
            constants: getClientPath('constants'),
            records: getClientPath('records'),
            services: getClientPath('services'),
            dispatcher: getClientPath('services', 'dispatcher.js'),
            stores: getClientPath('stores'),
            api: getClientPath('api'),
            api2: getClientPath('api2'),
            ui: getClientPath('ui'),
            'ui-externals': getClientPath('ui-externals'),
            'flat-ui': getClientPath('flat-ui'),
            'lego-ui': getClientPath('lego-ui'),
            'lego-on-react': getClientPath('lego-on-react'),
            lib: getClientPath('lib'),
            lib2: getClientPath('lib2'),
            const2: getClientPath('const2'),
            i18n2: getClientPath('i18n2'),
            validation: getClientPath('validation'),
        },
        // чтобы читались file:*-либы из package.json
        symlinks: false,
    },
    optimization: {
        minimize: configEnv !== 'development',
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify(configEnv),
            'process.env.BEM_LANG': '"en"',
            'process.env.REACT_APP_BEM_LANG': '"en"',
        }),
        new MiniCssExtractPlugin({
            filename: '[name].css',
            allChunks: true,
            publicPath: `${staticPath}/`,
        }),
        new CopyWebpackPlugin([
            { from: 'static/error.*', to: '[name].[ext]' },
            { from: 'static/museum.*', to: '[name].[ext]' },
            { from: 'static/i/yandex-connect.png', to: './i/[name].[ext]' },
            { from: 'static/i/error_5xx.svg', to: './i/[name].[ext]' },
        ]),
        hmrEnabled ? new webpack.HotModuleReplacementPlugin() : null,
        hmrEnabled ? new webpack.NoEmitOnErrorsPlugin() : null,
    ].filter(Boolean),
};
