import { HandlerContext, Handlers, PageProps } from "$fresh/server.ts";
import { asset, Head } from "$fresh/runtime.ts";
import { removePrefixFromPathname } from "../../util/util.ts";
import { join } from "path/posix.ts";
import DirList, { EntryInfo } from "../../islands/DirList.tsx";
import FileViewer from "../../islands/FileViewer.tsx";

type DirProps = {
  type: "dir";
  path: string;
  stat: Deno.FileInfo;
  files: EntryInfo[];
};
type FileProps = {
  type: "file";
  path: string;
  stat: Deno.FileInfo;
};

type DirOrFileProps = DirProps | FileProps;

async function GET(req: Request, ctx: HandlerContext): Promise<Response> {
  const authRequired = Deno.env.get("AUTH_REQUIRED") === "true";
  if (authRequired) {
    const login = ctx.state["login"];
    if (!login) {
      return new Response(null, {
        status: 302,
        headers: {
          "Location": "/login",
          "content-type": "text/plain",
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Allow-Methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
          "Access-Control-Allow-Headers":
            "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With",
        },
      });
    }
  }
  const url = new URL(req.url);
  const path = removePrefixFromPathname(decodeURI(url.pathname), "/dir");
  const stat = await Deno.stat(path);
  if (stat.isDirectory) {
    const filesIter = await Deno.readDir(path);
    const files: EntryInfo[] = [];
    for await (const file of filesIter) {
      const fileStat = await Deno.stat(join(path, file.name));
      files.push({
        ...file,
        lastModified: fileStat.mtime ? new Date(fileStat.mtime) : undefined,
        size: fileStat.size,
      });
    }
    return await ctx.render({
      type: "dir",
      stat,
      files,
      path,
    });
  } else {
    return await ctx.render({
      type: "file",
      stat,
      path,
    });
  }
}

export const handler: Handlers = {
  GET,
};

export default function DirLists(props: PageProps<DirOrFileProps>) {
  const data = props.data;
  return (
    <>
      <Head>
        <title>Simple file server : {data.path}</title>
      </Head>
      <div class="p-4 mx-auto max-w-screen-md">
        {data.type === "dir"
          ? <DirList path={data.path} files={data.files}></DirList>
          : <FileViewer path={data.path}></FileViewer>}
      </div>
    </>
  );
}
