// @ts-ignore
import { ModuleFilenameHelpers } from 'next/dist/compiled/webpack/webpack';
import { webpack } from 'next/dist/compiled/webpack/webpack';
// @ts-ignore
import { RawSource, SourceMapSource } from 'next/dist/compiled/webpack-sources3';
import { ECacheKey } from './interface';
import { getTargets } from './utils';
import { Buffer } from 'buffer';
const PLUGIN_NAME = 'lightning-css-minify';
const CSS_FILE_REG = /\.css(?:\?.*)?$/i;
export class LightningCssMinifyPlugin {
    constructor(opts = {}){
        const { implementation, ...otherOpts } = opts;
        if (implementation && typeof implementation.transformCss !== 'function') {
            throw Object.defineProperty(new TypeError(`[LightningCssMinifyPlugin]: implementation.transformCss must be an 'lightningcss' transform function. Received ${typeof implementation.transformCss}`), "__NEXT_ERROR_CODE", {
                value: "E561",
                enumerable: false
            });
        }
        this.transform = implementation == null ? void 0 : implementation.transformCss;
        this.options = otherOpts;
    }
    apply(compiler) {
        const meta = JSON.stringify({
            name: '@next/lightningcss-loader',
            version: '0.0.0',
            options: this.options
        });
        compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation)=>{
            compilation.hooks.chunkHash.tap(PLUGIN_NAME, (_, hash)=>hash.update(meta));
            compilation.hooks.processAssets.tapPromise({
                name: PLUGIN_NAME,
                stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE,
                additionalAssets: true
            }, async ()=>await this.transformAssets(compilation));
            compilation.hooks.statsPrinter.tap(PLUGIN_NAME, (statsPrinter)=>{
                statsPrinter.hooks.print.for('asset.info.minimized')// @ts-ignore
                .tap(PLUGIN_NAME, (minimized, { green, formatFlag })=>{
                    // @ts-ignore
                    return minimized ? green(formatFlag('minimized')) : undefined;
                });
            });
        });
    }
    async transformAssets(compilation) {
        const { options: { devtool } } = compilation.compiler;
        if (!this.transform) {
            const { loadBindings } = require('next/dist/build/swc');
            this.transform = (await loadBindings()).css.lightning.transform;
        }
        const sourcemap = this.options.sourceMap === undefined ? devtool && devtool.includes('source-map') : this.options.sourceMap;
        const { include, exclude, test: testRegExp, targets: userTargets, ...transformOptions } = this.options;
        const assets = compilation.getAssets().filter((asset)=>// Filter out already minimized
            !asset.info.minimized && // Filter out by file type
            (testRegExp || CSS_FILE_REG).test(asset.name) && ModuleFilenameHelpers.matchObject({
                include,
                exclude
            }, asset.name));
        await Promise.all(assets.map(async (asset)=>{
            const { source, map } = asset.source.sourceAndMap();
            const sourceAsString = source.toString();
            const code = typeof source === 'string' ? Buffer.from(source) : source;
            const targets = getTargets({
                targets: userTargets,
                key: ECacheKey.minify
            });
            const result = await this.transform({
                filename: asset.name,
                code,
                minify: true,
                sourceMap: sourcemap,
                targets,
                ...transformOptions
            });
            const codeString = result.code.toString();
            compilation.updateAsset(asset.name, // @ts-ignore
            sourcemap ? new SourceMapSource(codeString, asset.name, JSON.parse(result.map.toString()), sourceAsString, map, true) : new RawSource(codeString), {
                ...asset.info,
                minimized: true
            });
        }));
    }
}

//# sourceMappingURL=minify.js.map