////
// Publishes webapps as subdomains on your local network

import { watch } from "fs"
import { apps } from "./webapp"
import { expectDir } from "./utils"
import { NOSE_DIR } from "./config"
import { expectShellCmd } from "./utils"

export const dnsEntries: Record<string, any> = {}

const { stdout: ipRaw } = await Bun.$`hostname -I | awk '{print $1}'`.quiet()
const { stdout: hostRaw } = await Bun.$`hostname`.quiet()

const ip = ipRaw.toString().trim()
const host = hostRaw.toString().trim()
let dnsInit = false

export async function initDNS() {
    if (process.env.NO_DNS) return
    if (process.env.NODE_ENV !== "production") return
    if (!await expectShellCmd("avahi-publish")) return

    dnsInit = true

    startWatcher()
    apps().forEach(publishAppDNS)

    const signals = ["SIGINT", "SIGTERM"]
    signals.forEach(sig =>
        process.on(sig, () => {
            for (const name in dnsEntries)
                dnsEntries[name].kill("SIGTERM")
            process.exit(0)
        })
    )
}

export function publishAppDNS(app: string) {
    if (process.env.NO_DNS) return
    if (process.env.NODE_ENV !== "production") return
    if (!dnsInit) throw "publishAppDNS() must be called after initDNS()"

    if (!dnsEntries[app])
        dnsEntries[app] = Bun.spawn(["avahi-publish", "-a", `${app}.${host}.local`, "-R", ip])

    return dnsEntries[app]
}

let dnsWatcher
function startWatcher() {
    if (!expectDir(NOSE_DIR)) return

    dnsWatcher = watch(NOSE_DIR, (event, filename) => {
        const www = apps()
        www.forEach(publishAppDNS)
        for (const name in dnsEntries)
            if (!www.includes(name)) {
                dnsEntries[name].kill("SIGTERM")
                delete dnsEntries[name]
            }
    })
}