import { defineConfig } from "rollup";
import typescript from "@rollup/plugin-typescript";
import terser from "@rollup/plugin-terser";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import { basename, dirname, join } from "path";
import { opendirSync, rmSync, Dir } from "fs";
import { fileURLToPath } from "url";

// cleanup dist dir
const __dirname = fileURLToPath(new URL(".", import.meta.url));
cleanDir(join(__dirname, "./dist"));

export default defineConfig([
  {
    input: "./src/index.ts",
    output: [
      {
        format: "esm",
        dir: "./dist",
        preserveModules: true,
        preserveModulesRoot: "src",
        entryFileNames: (chunkInfo) => {
          if (chunkInfo.name.includes("node_modules")) {
            return externalLibPath(chunkInfo.name) + ".js";
          }

          return "[name].js";
        },
      },
      {
        format: "cjs",
        dir: "./dist",
        preserveModules: true,
        preserveModulesRoot: "src",
        entryFileNames: (chunkInfo) => {
          if (chunkInfo.name.includes("node_modules")) {
            return externalLibPath(chunkInfo.name) + ".cjs";
          }

          return "[name].cjs";
        },
      },
    ],
    plugins: [
      nodeResolve(),
      commonjs(),
      typescript({
        declaration: true,
        declarationDir: "./dist",
        rootDir: "src",
      }),
    ],
  },

  {
    input: "src/index.ts",
    output: {
      format: "iife",
      name: "__TAURI_IIFE__",
      footer: "window.__TAURI__ = __TAURI_IIFE__",
      file: "../../crates/tauri/scripts/bundle.global.js",
    },
    plugins: [nodeResolve(), commonjs(), typescript(), terser()],
  },
]);

function externalLibPath(path: string) {
  return `external/${basename(dirname(path))}/${basename(path)}`;
}

function cleanDir(path: string) {
  let dir: Dir;
  try {
    dir = opendirSync(path);
  } catch (err: any) {
    switch (err.code) {
      case "ENOENT":
        return; // Noop when directory don't exists.
      case "ENOTDIR":
        throw new Error(`'${path}' is not a directory.`);
      default:
        throw err;
    }
  }

  let file = dir.readSync();
  while (file) {
    const filePath = join(path, file.name);
    rmSync(filePath, { recursive: true });
    file = dir.readSync();
  }
  dir.closeSync();
}
