import fs from "node:fs/promises";
import path from "node:path";
import process from "node:process";
import { build } from "esbuild";

const [root, output] = process.argv.slice(2);
if (!root || !output) throw new Error("usage: node build.mjs <repository> <output>");

const browser = {
  bundle: true,
  format: "esm",
  legalComments: "none",
  minify: true,
  platform: "browser",
  target: "es2022",
};

const workerFiles = new Map([
  [path.join(root, "core", "index.js"), "./worker.js"],
  [path.join(root, "addons", "handles", "src", "importers", "gltf.ts"), "./importer-worker.js"],
  [path.join(root, "addons", "handles", "src", "bvh", "picking.ts"), "./bvh-worker.js"],
]);

const workerURLs = {
  name: "yawn-worker-urls",
  setup(builder) {
    builder.onLoad({ filter: /\.(js|ts)$/ }, async ({ path: source }) => {
      const worker = workerFiles.get(path.normalize(source));
      if (!worker) return;
      let contents = await fs.readFile(source, "utf8");
      const transformed = contents.replace(
        /new Worker\(new URL\("\.\/worker\.(?:js|ts)", import\.meta\.url\),/,
        `createYawnWorker(new URL(${JSON.stringify(worker)}, import.meta.url),`,
      );
      if (transformed === contents) throw new Error(`worker constructor not found in ${source}`);
      contents = `
function createYawnWorker(url, options) {
  if (url.origin === globalThis.location.origin) return new Worker(url, options);
  const source = "import " + JSON.stringify(url.href) + ";";
  const bootstrap = URL.createObjectURL(new Blob([source], { type: "text/javascript" }));
  const worker = new Worker(bootstrap, options);
  URL.revokeObjectURL(bootstrap);
  return worker;
}
${transformed}`;
      return { contents, loader: path.extname(source) === ".ts" ? "ts" : "js" };
    });
  },
};

await Promise.all([
  build({
    ...browser,
    entryPoints: [path.join(root, "core", "index.js")],
    outfile: path.join(output, "core.js"),
    plugins: [workerURLs],
  }),
  build({
    ...browser,
    alias: { "@yawn/core": path.join(root, "core", "index.js") },
    entryPoints: [path.join(root, "addons", "handles", "src", "index.ts")],
    outfile: path.join(output, "handles.js"),
    plugins: [workerURLs],
  }),
  build({
    bundle: false,
    entryPoints: [path.join(root, "core", "worker.js")],
    format: "esm",
    legalComments: "none",
    minify: true,
    outfile: path.join(output, "worker.js"),
    target: "es2022",
  }),
  build({
    ...browser,
    entryPoints: [path.join(root, "addons", "handles", "src", "importers", "worker.ts")],
    outfile: path.join(output, "importer-worker.js"),
  }),
  build({
    ...browser,
    entryPoints: [path.join(root, "addons", "handles", "src", "bvh", "worker.ts")],
    outfile: path.join(output, "bvh-worker.js"),
  }),
]);
