/// <reference no-default-lib="true" />
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
/// <reference lib="dom.asynciterable" />
/// <reference lib="deno.ns" />

import { PluginRenderResult, Plugin, ServerContext, Manifest, StartOptions } from "$fresh/server.ts";
import manifest from "./fresh.gen.ts";

import twindPlugin from "$fresh/plugins/twind.ts";
import twindConfig from "./twind.config.ts";
import "https://deno.land/std@0.170.0/dotenv/load.ts";


import { Command } from "https://deno.land/x/cliffy@v0.25.6/mod.ts";
import { fromFileUrl, join } from "path/mod.ts";
import { prepareSecretKey } from "./util/secret.ts";
import { serve } from "http/server.ts";

import { user_command } from "./user.ts";
import { key_out_cmd } from "./keyout.ts";

const github_markdown= await Deno.readTextFile(join(fromFileUrl(import.meta.url), "..", "static", "github-markdown.css"))

const CSSPlugin: Plugin = {
    name:"css plugin",
    // deno-lint-ignore require-await
    render(ctx): PluginRenderResult{
        ctx.render();
        return {
            styles: [{
                cssText: github_markdown,
            }] 
        }
    }
};
await prepareSecretKey();

async function startServer(manifest: Manifest, options: StartOptions = {}){
    const ctx = await ServerContext.fromManifest(manifest, options);
    
    options.port ??= 8000;
    if (options.experimentalDenoServe === true) {
      // @ts-ignore as `Deno.serve` is still unstable.
      await Deno.serve(ctx.handler() as Deno.ServeHandler, options);
    } else {
      await serve(ctx.handler(), options);
    }
}

async function start({port = 8000, hostname = "localhost"}: {port?: number, hostname?: string} = {}){
    await startServer(manifest, { plugins: [twindPlugin(twindConfig), CSSPlugin],
        port: port,
        hostname: hostname,
    });
}

if (import.meta.main){
    const cmd = new Command();
    cmd.name("fs-server")
    .description("A simple file server that supports search, upload, and download.")
    .version("0.0.1")
    .globalOption("-d, --debug", "Enable debug mode.")
    .command("start", "Start the server.")
    .option("-p, --port <port:number>", "The port to listen on.", 
        { default: 8000 })
    .option("--auth", "Enable authentication.")
    .arguments("[hostname:string]")
    .action(async ({debug, port, auth }, hostname) => {
        hostname ??= "localhost";
        if (auth){
            Deno.env.set("AUTH_REQUIRED", "true");
        }
        if (debug){
                console.log("Debug mode enabled.");
            }
            await start({ 
                port: port,
                hostname: hostname,
            });
        }
    )
    .command("user", user_command)
    .command("keyout", key_out_cmd)
    ;
    await cmd.parse(Deno.args);
}
else {
    await start();
}
