import { useEffect, useState } from "preact/hooks";
import { EditorMode } from "./Editor.tsx";
import Button from "../components/form/Button.tsx";
import Input from "../components/form/Input.tsx";
import Checkbox from "../components/form/Checkbox.tsx";
import ThemeToggle from "./ThemeToggle.tsx";

interface TopBarProps {
  allowMode: EditorMode;
  isLogined: boolean;
  shared: boolean;
  title: string;
  id: string;
}

const settingsData: { [key: string]: string } = {};
const shareData: { [key: string]: boolean | string } = {};

export default function TopBar(props: TopBarProps) {
  const [mode, setMode] = useState(props.allowMode);

  const doLogout = async () => {
    const resp = await fetch("/api/user/logout");
    const respJson = await resp.json();
    if (respJson.success) {
      location.href = "/login";
      return true;
    }
    return false;
  };

  const goHome = () => {
    location.href = "/";
  };

  const download = () => {
    dispatchEvent(new CustomEvent("DownloadRequest", { detail: props.title }));
  };

  const showShare = () => {
    shareData["shared"] = shareData["submittedShared"] !== undefined
      ? shareData["submittedShared"] as boolean
      : props.shared;
    shareData["password"] = shareData["submittedPassword"] || "";
    globalThis.$modal?.show(
      "Share options",
      <div>
        <div style="display: flex; align-items: center">
          <Checkbox
            label="Share to friends"
            checked={shareData["shared"] as boolean}
            onChange={(e) => {
              shareData["shared"] = (e.target as HTMLInputElement).checked;
              const extraEl = document.querySelector(
                "#share-extra",
              ) as HTMLDivElement;
              extraEl.style.display = shareData["shared"] ? "flex" : "none";
            }}
          />
          <Button
            type="button"
            id="shared-button"
            className="ml-2"
            style={`${!shareData["shared"] ? ";visibility: hidden" : ""}`}
            onClick={async () => {
              await navigator.clipboard.writeText(
                location.href.split("?")[0],
              );
            }}
          >
            Copy Link
          </Button>
        </div>
        <div
          id="share-extra"
          style={`display: ${
            shareData["shared"] ? "flex" : "none"
          }; align-items: center; margin-top: 12px`}
        >
          <span style="margin-right: 8px; white-space: nowrap">
            Password (optional)
          </span>
          <Input
            type="password"
            placeholder="Password"
            value={shareData["password"] as string}
            onInput={(e) => {
              shareData["password"] = (e.target as HTMLInputElement).value;
            }}
          />
        </div>
      </div>,
      [
        {
          text: "Confirm",
          onClick: async () => {
            const resp = await fetch("/api/share", {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({
                id: props.id,
                shared: shareData["shared"],
                password: shareData["password"] || "",
              }),
            });
            const respJson = await resp.json();
            if (respJson.success) {
              shareData["submittedShared"] = shareData["shared"];
              shareData["submittedPassword"] = shareData["password"];
              globalThis.$modal?.hide();
            }
          },
        },
      ],
    );
  };

  const showSetting = () => {
    settingsData["title"] = settingsData["submittedTitle"] || props.title;
    globalThis.$modal?.show(
      "Post Settings",
      <div style="display: flex; align-items: center">
        <span style="margin-right: 8px">Title</span>
        <Input
          placeholder="Post title here"
          value={settingsData["title"]}
          onInput={(e) => {
            settingsData["title"] = (e.target as HTMLInputElement).value;
          }}
        />
      </div>,
      [
        {
          text: "Confirm",
          onClick: async () => {
            const resp = await fetch("/api/post", {
              method: "PUT",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({
                id: props.id,
                title: settingsData["title"],
              }),
            });
            const respJson = await resp.json();
            if (respJson.success) {
              settingsData["submittedTitle"] = settingsData["title"];
              document.title = settingsData["title"];
              globalThis.$modal?.hide();
            }
          },
        },
      ],
    );
  };

  // Event listener
  const modeChangeListener = (e: Event) => {
    const { detail } = e as CustomEvent;
    if (
      detail &&
      (props.allowMode === detail || props.allowMode === EditorMode.Both)
    ) {
      setMode(detail);
    }
  };

  // Event dispatcher
  const modeChangeDispatcher = (mode: EditorMode) => {
    dispatchEvent(new CustomEvent("ModeChange", { detail: mode }));
  };

  // Init event listeners
  useEffect(() => {
    addEventListener("ModeChange", modeChangeListener);

    return () => {
      removeEventListener("ModeChange", modeChangeListener);
    };
  }, []);

  return (
    <div className="w-full flex mb-3 justify-between box-border flex-shrink-0">
      <div
        className={`border border-gray-300 dark:border-gray-700 rounded box-border text-sm ${
          props.allowMode !== EditorMode.Both ? "hidden" : ""
        }`}
      >
        <Button
          variant={mode === EditorMode.Edit ? "primary" : "default"}
          className="rounded-tr-none rounded-br-none"
          id="edit"
          type="button"
          onClick={() => {
            modeChangeDispatcher(EditorMode.Edit);
          }}
        >
          Edit
        </Button>
        <Button
          variant={mode === EditorMode.Read ? "primary" : "default"}
          className="rounded-none"
          id="read"
          type="button"
          onClick={() => {
            modeChangeDispatcher(EditorMode.Read);
          }}
        >
          Read
        </Button>
        <Button
          variant={mode === EditorMode.Both ? "primary" : "default"}
          className="rounded-tl-none rounded-bl-none"
          id="both"
          type="button"
          onClick={() => {
            modeChangeDispatcher(EditorMode.Both);
          }}
        >
          Both
        </Button>
      </div>
      {!props.isLogined
        ? (
          <div className="flex items-center justify-center w-full">
            <span className="leading-[30px] text-2xl font-medium text-center flex-1">
              {props.title}
            </span>
            <i
              className="bi bi-download mr-3 text-base cursor-pointer hover:text-blue-600 dark:hover:text-blue-400"
              onClick={download}
              title="Download"
            />
            <ThemeToggle />
          </div>
        )
        : null}
      {props.isLogined
        ? (
          <div className="h-[30px] leading-[28px] box-border px-2 border border-gray-300 dark:border-gray-700 rounded">
            <i
              className="bi bi-box-arrow-left mr-4 text-base cursor-pointer h-4 w-4 hover:text-blue-600 dark:hover:text-blue-400"
              onClick={doLogout}
            />
            <i
              className="bi bi-house-door mr-4 text-base cursor-pointer h-4 w-4 hover:text-blue-600 dark:hover:text-blue-400"
              onClick={goHome}
            />
            <i
              className="bi bi-share mr-4 text-base cursor-pointer h-4 w-4 hover:text-blue-600 dark:hover:text-blue-400"
              onClick={showShare}
            />
            <i
              className="bi bi-download mr-4 text-base cursor-pointer h-4 w-4 hover:text-blue-600 dark:hover:text-blue-400"
              onClick={download}
              title="Download"
            />
            <i
              className="bi bi-gear mr-4 text-base cursor-pointer h-4 w-4 hover:text-blue-600 dark:hover:text-blue-400"
              onClick={showSetting}
            />
            <ThemeToggle />
          </div>
        )
        : null}
    </div>
  );
}
