import {resolve, sep} from 'node:path';
import {env} from 'node:process';
import webpack from 'webpack';
import WebpackBar from 'webpackbar';

const {
    EnvironmentPlugin,
    NormalModuleReplacementPlugin,
} = webpack;

const modules = './modules';
const dirModules = './client/modules';
const dirCss = './css';
const dirThemes = `${dirCss}/themes`;
const dirColumns = `${dirCss}/columns`;
const dir = './client';
const {NODE_ENV} = env;
const isDev = NODE_ENV === 'development';

const rootDir = new URL('..', import.meta.url).pathname;
const dist = resolve(rootDir, 'dist');
const distDev = resolve(rootDir, 'dist-dev');
const devtool = isDev ? 'eval' : 'source-map';

const notEmpty = (a) => a;
const clean = (array) => array.filter(notEmpty);

const noParse = (a) => a.endsWith('.spec.js');
const options = {
    babelrc: true,
};

const rules = clean([
    !isDev && {
        test: /\.[mc]?js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
    },
    isDev && {
        test: /\.[mc]?js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options,
    },
]);

const plugins = [
    new NormalModuleReplacementPlugin(/^node:/, (resource) => {
        resource.request = resource.request.replace(/^node:/, '');
    }),
    new NormalModuleReplacementPlugin(/^putout$/, '@putout/bundle'),
    new EnvironmentPlugin({
        NODE_ENV,
    }),
    new WebpackBar(),
    new webpack.ProvidePlugin({
        process: 'process/browser',
    }),
];

const splitChunks = {
    chunks: 'all',
    cacheGroups: {
        abcCommon: {
            name: 'cloudcmd.common',
            chunks: (chunk) => {
                const lazyChunks = [
                    'sw',
                    'nojs',
                    'view',
                    'edit',
                    'terminal',
                    'config',
                    'user-menu',
                    'help',
                    'themes/dark',
                    'themes/light',
                    'columns/name-size',
                    'columns/name-size-date',
                    'columns/name-size-time',
                    'columns/name-size-date-time',
                ];
                
                return !lazyChunks.includes(chunk.name);
            },
            minChunks: 1,
            enforce: true,
            priority: -1,
            reuseExistingChunk: true,
        },
    },
};

export default {
    resolve: {
        symlinks: false,
        alias: {
            'node:process': 'process',
            'node:path': 'path',
        },
        fallback: {
            path: import.meta.resolve('path-browserify'),
            process: import.meta.resolve('process/browser'),
            util: import.meta.resolve('util'),
        },
    },
    devtool,
    optimization: {
        splitChunks,
    },
    entry: {
        'themes/dark': `${dirThemes}/dark.css`,
        'themes/light': `${dirThemes}/light.css`,
        'columns/name-size': `${dirColumns}/name-size.css`,
        'columns/name-size-date': `${dirColumns}/name-size-date.css`,
        'columns/name-size-date-time': `${dirColumns}/name-size-date-time.css`,
        'nojs': `${dirCss}/nojs.css`,
        'help': `${dirCss}/help.css`,
        'view': `${dirCss}/view.css`,
        'config': `${dirCss}/config.css`,
        'terminal': `${dirCss}/terminal.css`,
        'user-menu': `${dirCss}/user-menu.css`,
        'sw': `${dir}/sw/sw.js`,
        'cloudcmd': `${dir}/cloudcmd.js`,
        [`${modules}/edit`]: `${dirModules}/edit.js`,
        [`${modules}/edit-file`]: `${dirModules}/edit-file.js`,
        [`${modules}/edit-file-vim`]: `${dirModules}/edit-file-vim.js`,
        [`${modules}/edit-names`]: `${dirModules}/edit-names.js`,
        [`${modules}/edit-names-vim`]: `${dirModules}/edit-names-vim.js`,
        [`${modules}/menu`]: `${dirModules}/menu/index.js`,
        [`${modules}/view`]: `${dirModules}/view/index.js`,
        [`${modules}/help`]: `${dirModules}/help.js`,
        [`${modules}/markdown`]: `${dirModules}/markdown.js`,
        [`${modules}/config`]: `${dirModules}/config/index.js`,
        [`${modules}/contact`]: `${dirModules}/contact.js`,
        [`${modules}/upload`]: `${dirModules}/upload.js`,
        [`${modules}/operation`]: `${dirModules}/operation/index.js`,
        [`${modules}/konsole`]: `${dirModules}/konsole.js`,
        [`${modules}/terminal`]: `${dirModules}/terminal.js`,
        [`${modules}/terminal-run`]: `${dirModules}/terminal-run.js`,
        [`${modules}/cloud`]: `${dirModules}/cloud.js`,
        [`${modules}/user-menu`]: `${dirModules}/user-menu/index.js`,
        [`${modules}/polyfill`]: `${dirModules}/polyfill.js`,
        [`${modules}/command-line`]: `${dirModules}/command-line.js`,
    },
    output: {
        filename: '[name].js',
        path: isDev ? distDev : dist,
        pathinfo: isDev,
        devtoolModuleFilenameTemplate,
        publicPath: '/dist/',
    },
    module: {
        rules,
        noParse,
    },
    plugins,
    performance: {
        maxEntrypointSize: 600_000,
        maxAssetSize: 600_000,
    },
};

function devtoolModuleFilenameTemplate(info) {
    const resource = info.absoluteResourcePath.replace(rootDir + sep, '');
    return `file://cloudcmd/${resource}`;
}
