////
// Manages the commands on disk, in NOSE_SYS_BIN and NOSE_BIN

import { Glob } from "bun"
import { watch } from "fs"
import { join } from "path"
import { isFile } from "./utils"
import { sendAll } from "./websocket"
import { expectDir } from "./utils"
import { NOSE_SYS_BIN, NOSE_BIN } from "./config"

export function initCommands() {
  startWatchers()
}

export async function commands(): Promise<string[]> {
  return (await findCommands(NOSE_SYS_BIN)).concat(await findCommands(NOSE_BIN))
}

export async function findCommands(path: string): Promise<string[]> {
  const glob = new Glob("**/*.{ts,tsx}")
  let list: string[] = []

  for await (const file of glob.scan(path)) {
    list.push(file.replace(".tsx", "").replace(".ts", ""))
  }

  return list
}

export function commandPath(cmd: string): string | undefined {
  return [
    join(NOSE_SYS_BIN, cmd + ".ts"),
    join(NOSE_SYS_BIN, cmd + ".tsx"),
    join(NOSE_BIN, cmd + ".ts"),
    join(NOSE_BIN, cmd + ".tsx")
  ].find((path: string) => isFile(path))
}

export function commandExists(cmd: string): boolean {
  return commandPath(cmd) !== undefined
}

export async function commandSource(name: string): Promise<string> {
  const path = commandPath(name)
  if (!path) return ""
  return Bun.file(path).text()
}

let sysCmdWatcher
let usrCmdWatcher
function startWatchers() {
  expectDir(NOSE_BIN)

  sysCmdWatcher = watch(NOSE_SYS_BIN, async (event, filename) =>
    sendAll({ type: "commands", data: await commands() })
  )

  usrCmdWatcher = watch(NOSE_BIN, async (event, filename) => {
    sendAll({ type: "commands", data: await commands() })
  })
}