'use client'

import type { ContentModule, ScriptModule, WasmModuleParam, ResourceFileParam, StringParam } from "./types"
import { useEffect, useRef } from "react"
import { themeSignal } from "../Appearance"

interface ScriptLoaderClientParams {
  src: ScriptModule,
  wasm: WasmModuleParam | undefined,
  rest: {
    [name: string]: ResourceFileParam | StringParam
  }
}

export default function ScriptLoaderClient({ src, wasm, rest }: ScriptLoaderClientParams) {
  const moduleRef = useRef<ContentModule | null>(null)

  useEffect(() => {
    (async () => {
      if (!src) return undefined

      const scriptModule : ContentModule = await import(/*webpackIgnore: true */ src.path)

      let wasmModule: WebAssembly.Instance | undefined = undefined

      if (wasm) {
        const instantiatedWasm = await WebAssembly.instantiateStreaming(fetch(wasm.binaryPath))
        wasmModule = instantiatedWasm.instance
      }

      moduleRef.current = scriptModule

      const restProps = Object.keys(rest).reduce((acc: {[name: string]: string}, propName: string) => {
        const prop = rest[propName]
        return {
          ...acc,
          [propName]: prop.type === 'string' ? prop.value : prop
        }
      }, {})

      if (scriptModule.setup && typeof scriptModule.setup === 'function')
        scriptModule.setup(restProps, wasmModule)
    })()

    return () => {
      const mod = moduleRef.current

      if (mod?.cleanup && typeof mod.cleanup === 'function') {
        mod.cleanup()
      }
    }
  }, [])

  useEffect(() => {
    function onThemeChange() {
      const mod = moduleRef.current

      if (mod?.onThemeChange && typeof mod?.onThemeChange === 'function') {
        mod.onThemeChange()
      }
    }

    themeSignal.addListener('change', onThemeChange)
    return () => { themeSignal.removeListener('change', onThemeChange) }
  }, [])

  return null
}
