import swc from '@swc/core';
import combine from '../combine.js';
import { join as pathJoin } from 'path';
import { strtr, shortHash, writeFile } from './utils.js';

export const function(env) {
    const PREFIX = '#';
    const DEFAULT_ENTRY = 'main.js';
    const DEFAULT_VARS_TARGET = 'window';

    const createJscOpts = () => {
        return {
            target: env.swc.es,
            loose: false,
            externalHelpers: false,
            keepClassNames: true,
            preserveAllComments: false,
            transform: {},
            parser: {
                syntax: 'ecmascript',
                jsx: env.swc.jsx !== false,
                dynamicImport: false,
                privateMethod: false,
                functionBind: false,
                exportDefaultFrom: false,
                exportNamespaceFrom: false,
                decorators: false,
                decoratorsBeforeExport: false,
                topLevelAwait: true,
                importMeta: false,
            },
            transform: {
                react: {
                    runtime: 'classic',
                    pragma: env.swc.jsx || '',
                },
            },
        };
    };

    return {
        process: async (task, vars) => {
            const jscOpts = createJscOpts();
            if('es' in task)
                jscOpts.target = task.es;

            const output = await swc.transform(
                await combine.folder(pathJoin(env.source, task.source), {
                    prefix: PREFIX,
                    entry: task.entry ?? DEFAULT_ENTRY,
                    vars: vars,
                    varsTarget: task.varsTarget ?? DEFAULT_VARS_TARGET,
                }), {
                    filename: task.source,
                    sourceMaps: false,
                    isModule: false,
                    minify: !env.debug,
                    jsc: jscOpts,
                }
            );

            const path = pathJoin(
                task.target ?? '',
                strtr(task.name, { hash: shortHash(output.code) })
            );

            writeFile(pathJoin(env.public, path), output.code);

            return path;
        },
    };
};