import { join } from "jsr:@std/path";
import { createMiddleware } from "jsr:@hono/hono/factory";
import mustache from "npm:mustache";
import { HTTPException } from "jsr:@hono/hono/http-exception";

const data: { [key: string]: string } = {};

export async function mimerRender(path: string) {
  const dir_path = join(path);
  const promises: Promise<string>[] = [];

  promises.push(...readHeadAndFoot(dir_path));

  console.log(
    `\n %cReading template\n`,
    "color: red; text-decoration: underline;font-weight: bold;",
  );

  for await (const dirEntry of Deno.readDir(path)) {
    const template = dirEntry.name.split(".").slice(0, -1).join(".");
    const file_path = join(path, dirEntry.name);
    promises.push(
      Deno.readTextFile(file_path).then((txt) => data[template] = txt).then(
        () => {
          console.log(
            `%c${capitalizeFirstLetter(template)}`,
            "color: green;d;",
          );
          return template;
        },
      ).catch(
        () => {
          console.error("Error reading " + file_path);
          return "";
        },
      ),
    );
  }
  await Promise.all(promises);
  console.log("");
  const foot = mustache.render(data["foot"]);

  return createMiddleware(async (c, next) => {
    await next();
    const template_name = c.get("template");
    if (template_name !== undefined) {
      const json = await c.res.json();
      json.theme = c.get("theme");
      const template = data[template_name];
      if (template === undefined) {
        console.error("Template is missing:" + template_name);
        throw new HTTPException(500, { message: "Template is missing." });
      }
      const head = mustache.render(data["head"], json);
      const page = mustache.render(template, json);
      c.res = new Response(head + page + foot, c.res);
      c.header("Content-Type", "text/html");
    }
  });
}

function readHeadAndFoot(dirPath: string) {
  const promises: Promise<string>[] = [];
  try {
    promises.push(
      Deno.readTextFile(join(dirPath, "head.txt")).then((txt) =>
        data["head"] = txt
      ),
    );
  } catch {
    console.log("No head file");
  }
  try {
    promises.push(
      Deno.readTextFile(join(dirPath, "foot.txt")).then((txt) =>
        data["foot"] = txt
      ),
    );
  } catch {
    console.log("No foot file");
  }
  return promises;
}

// From https://stackoverflow.com/questions/1026069/how-do-i-make-the-first-letter-of-a-string-uppercase-in-javascript
function capitalizeFirstLetter(val: string) {
  return String(val).charAt(0).toUpperCase() + String(val).slice(1);
}
