"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.dev = exports.preview = exports.build = void 0;
const fs_1 = require("fs");
const assets_1 = require("./assets");
const path_1 = __importDefault(require("path"));
const vite_1 = require("vite");
const plugin_vue_1 = __importDefault(require("@vitejs/plugin-vue"));
const adm_zip_1 = __importDefault(require("adm-zip"));
const roadroller_1 = require("roadroller");
const config_1 = require("../helpers/config");
const colors_1 = require("../helpers/colors");
const { execFile } = require("child_process");
const advzip = require("advzip-bin");
const plugins = [(0, plugin_vue_1.default)(), (0, assets_1.assetTransform)()];
function getBuildOptions(config) {
    if (config.build.mode === "zip") {
        return {
            polyfillModulePreload: false,
            minify: "terser",
            outDir: path_1.default.resolve("build/web"),
            emptyOutDir: true,
            terserOptions: {
                ecma: 2020,
                module: true,
                sourceMap: false,
                toplevel: true,
            },
        };
    }
    return {
        outDir: path_1.default.resolve("build/web"),
        emptyOutDir: true,
        minify: false,
    };
}
const optimize = async (buildFolder, compressedFolder, files) => {
    const css = files.filter((x) => path_1.default.extname(x) === ".css");
    const html = files.filter((x) => path_1.default.extname(x) === ".html");
    const js = files.filter((x) => path_1.default.extname(x) === ".js");
    const jsInput = js.map((x) => ({
        data: (0, fs_1.readFileSync)(path_1.default.join(buildFolder, x), "utf-8"),
        type: "js" /* InputType.JS */,
        action: "eval" /* InputAction.Eval */,
    }));
    // minify JS
    const packer = new roadroller_1.Packer(jsInput, {});
    await packer.optimize(1);
    const { firstLine, secondLine } = packer.makeDecoder();
    let htmlContent = (0, fs_1.readFileSync)(path_1.default.join(buildFolder, html[0]), "utf-8");
    const searchJS = `<script type="module" crossorigin src="/${js[0]}"></script>`;
    const matchScript = htmlContent.match(searchJS);
    if (matchScript) {
        const index = matchScript.index;
        htmlContent = `${htmlContent.slice(0, index)}<script type="module">
${firstLine}
${secondLine}
  </script>${htmlContent.slice(index + searchJS.length)}`;
    }
    const searchCSS = `<link rel="stylesheet" href="/${css[0]}">`;
    const matchStyle = htmlContent.match(searchCSS);
    if (matchStyle) {
        const index = matchStyle.index;
        htmlContent = `${htmlContent.slice(0, index)}<style>${(0, fs_1.readFileSync)(path_1.default.join(buildFolder, css[0]), "utf-8")}</style>${htmlContent.slice(index + searchCSS.length)}`;
    }
    (0, fs_1.writeFileSync)(path_1.default.join(compressedFolder, "_index.html"), htmlContent);
    // add file to zip
    const zip = new adm_zip_1.default();
    zip.addFile("index.html", (0, fs_1.readFileSync)(path_1.default.join(compressedFolder, "_index.html")));
    await zip.writeZipPromise(path_1.default.join(compressedFolder, "build.zip"));
    // use ADVZip (https://linux.die.net/man/1/advzip)
    await new Promise((resolve) => {
        execFile(advzip, ["--recompress", "--shrink-extra", path_1.default.join(compressedFolder, "build.zip")], (err) => {
            if (err)
                console.warn(err);
            resolve(true);
        });
    });
    // measure size and log
    const res = (0, fs_1.statSync)(path_1.default.join(compressedFolder, "build.zip"));
    console.log("------");
    console.log(`Exported: ${path_1.default.join(compressedFolder, "build.zip")}`);
    console.log(`Size: ${Math.round((res.size / 1024) * 100) / 100}KB`);
};
const build = async (options) => {
    console.log((0, colors_1.info)("[Pixel Builder] Build Command"));
    const config = (0, config_1.getPixelConfig)();
    const def = config.define["production"] ?? {};
    if (!(0, fs_1.existsSync)(".pixel"))
        (0, fs_1.mkdirSync)(".pixel");
    if (!(0, fs_1.existsSync)("build"))
        (0, fs_1.mkdirSync)("build");
    if (!(0, fs_1.existsSync)("build/web"))
        (0, fs_1.mkdirSync)("build/web");
    const buildOptions = {
        root: path_1.default.resolve("src"),
        plugins,
        define: def,
        publicDir: "../public",
        mode: "production",
        base: options.base ?? "",
        build: getBuildOptions(config),
        resolve: {
            alias: {
                "@assets": path_1.default.resolve(process.cwd(), "./src/assets/"),
                "@src": path_1.default.resolve(process.cwd(), "./src/"),
            },
        },
    };
    // console.log('Build', buildOptions)
    const output = (await (0, vite_1.build)(buildOptions));
    if (config.build.mode === "zip") {
        if (!(0, fs_1.existsSync)("build/compressed"))
            (0, fs_1.mkdirSync)("build/compressed");
        const buildFolder = path_1.default.join("build", "web");
        const compressedFolder = path_1.default.join("build", "compressed");
        const files = output.output.map((x) => x.fileName).filter((x) => !!x);
        await optimize(buildFolder, compressedFolder, files);
    }
};
exports.build = build;
const preview = async () => {
    console.log((0, colors_1.info)("[Pixel Builder] Preview Command"));
    const config = (0, config_1.getPixelConfig)();
    if (!(0, fs_1.existsSync)(".pixel"))
        (0, fs_1.mkdirSync)(".pixel");
    if (!(0, fs_1.existsSync)("build"))
        (0, fs_1.mkdirSync)("build");
    const previewServer = await (0, vite_1.preview)({
        root: path_1.default.resolve("src"),
        plugins,
        publicDir: "../public",
        build: getBuildOptions(config),
        preview: {
            port: 8080,
            open: true,
        },
        resolve: {
            alias: {
                "@assets": path_1.default.resolve(process.cwd(), "./src/assets/"),
                "@src": path_1.default.resolve(process.cwd(), "./src/"),
            },
        },
    });
    previewServer.printUrls();
};
exports.preview = preview;
const dev = async () => {
    console.log((0, colors_1.info)("[Pixel Builder] Dev Command"));
    const config = (0, config_1.getPixelConfig)();
    const def = config.define["develop"] ?? {};
    const server = await (0, vite_1.createServer)({
        configFile: false,
        root: path_1.default.resolve("src"),
        plugins,
        define: def,
        publicDir: "../public",
        mode: "develop",
        build: getBuildOptions(config),
        server: {
            port: 1337,
        },
        resolve: {
            alias: {
                "@assets": path_1.default.resolve(process.cwd(), "./src/assets/"),
                "@src": path_1.default.resolve(process.cwd(), "./src/"),
            },
        },
    });
    await server.listen();
    server.printUrls();
};
exports.dev = dev;
