// The one shader-compile target matrix, shared by the backend's server-side compile
// (backend/src/utils/compileShader.ts) and the CLI's local compile (lecodes-cli
// src/compile/shaders.ts). Both must produce the SAME artifact family for a .mat source —
// the compiled bundle derives per-backend URLs by substituting `_creator.subBackend ??
// _creator.backend` into the opengl src (compileProject.ts), so the set of names is ABI.

export const externalSamplerReg = /type\s*:\s*samplerExternal/g

// matc invocation per target. `profile` is matc's -p (mobile = shader model MOBILE / ESSL3,
// desktop = shader model DESKTOP / GLSL 4.1); `api` is -a. WebGL and the Windows desktop host
// both run OpenGL without external (OES) sampler support, so they get samplerExternal rewritten
// to sampler2d. The desktop variant exists because the desktop Filament engine rejects the mobile
// _opengl shader ("not built for desktop"); _creator.backend returns "desktop" there.
//
// These names are opaque identities for a (profile, api, rewrite) triple, not API names — hence
// "opengl" (mobile profile) and "desktop" (desktop profile) both being OpenGL. Their only job is to
// be stable and unique: the runtime substitutes one into `<hash>_<name>.filamat`.
export const PLATFORM_BUILD = {
  opengl:  { profile: "mobile",  api: "opengl", replaceExternal: false },
  metal:   { profile: "mobile",  api: "metal",  replaceExternal: false },
  webgl:   { profile: "mobile",  api: "opengl", replaceExternal: true },
  desktop: { profile: "desktop", api: "opengl", replaceExternal: true },
} as const
export type MatcPlatform = keyof typeof PLATFORM_BUILD

// Targets the CLI compiles LOCALLY and the platform does not. Deliberately a separate table, not
// another PLATFORM_BUILD entry: `MatcPlatform` feeds the backend's `Platform` type, which is checked
// against the `shaderPlatform` pg enum — widening it would break the backend's inserts at compile
// time for a value the server never produces. Keep local-only targets here until the platform grows
// the matching enum value (docs/desktop-vulkan-release-plan.md §4 "Known limitation").
//
// 'desktop-vulkan' = the Windows Vulkan desktop host: same DESKTOP shader model as 'desktop' but
// SPIR-V, and the two are not interchangeable — Filament rejects a foreign one outright ("not built
// for any of the OpenGL backend's supported shader languages"). `_creator.backend` returns
// "desktop-vulkan" on that host.
export const LOCAL_PLATFORM_BUILD = {
  "desktop-vulkan": { profile: "desktop", api: "vulkan", replaceExternal: true },
} as const
export type LocalMatcPlatform = keyof typeof LOCAL_PLATFORM_BUILD

/** Every matc target, local-only ones included — the lookup table for matcArgs. */
export const ALL_PLATFORM_BUILD = { ...PLATFORM_BUILD, ...LOCAL_PLATFORM_BUILD }
export type AnyMatcPlatform = MatcPlatform | LocalMatcPlatform

/** The local-only targets, as a list (order matters where it feeds an artifact family). */
export const LOCAL_ONLY_PLATFORMS: LocalMatcPlatform[] = ["desktop-vulkan"]

// 'webgl-lite' is not a matc target: viewer-lite gets a JSON artifact (parsed .mat — see
// liteMaterial.ts) that it wraps in its own GLSL template at runtime.
export type ShaderPlatform = MatcPlatform | "webgl-lite"

/** Every platform the LOCAL compile can produce (matc targets + the lite JSON). */
export type AnyShaderPlatform = AnyMatcPlatform | "webgl-lite"

/** Bump when the matc invocation for an EXISTING target name changes (a different -p/-a/rewrite for
 *  a name that already exists). The CLI folds this into its artifact cache key, so such a change
 *  invalidates caches that would otherwise look complete — adding or removing a target name is
 *  already caught by the artifact-family check, but changing the argv behind a name is not.
 *  1 = 'desktop-vulkan' added (2026-08-24). */
export const TARGET_MATRIX_GENERATION = 1

/** The matc platforms a .mat source needs compiled. WebGL is matc-compiled only when the shader
 *  has an external sampler: its samplerExternal → sampler2d rewrite makes the output differ from
 *  the mobile opengl build. Without one the WebGL artifact is byte-identical to the mobile shader,
 *  so callers copy it from the opengl output instead of running matc again. Either way a _webgl
 *  artifact must always exist — the web runtime always requests one (via _creator.subBackend).
 *
 *  This is the SERVER's contract — it deliberately does not include LOCAL_ONLY_PLATFORMS. The CLI
 *  appends those itself (lecodes-cli src/compile/shaders.ts). */
export const matcPlatformsFor = (text: string): MatcPlatform[] => {
  externalSamplerReg.lastIndex = 0
  return externalSamplerReg.test(text)
    ? ["opengl", "metal", "webgl", "desktop"]
    : ["opengl", "metal", "desktop"]
}

/** The matc argv (without the executable) for one target. */
export const matcArgs = (platform: AnyMatcPlatform, outPath: string, inPath: string): string[] => {
  const build = ALL_PLATFORM_BUILD[platform]
  return ["-p", build.profile, "--no-essl1", "-a", build.api, "-o", outPath, inPath]
}
