import { Button } from "components/Inputs/Button";
import { useAppLayout } from "contexts/AppLayoutContext";
import { UploadImageFragment } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { prettyLanguage, prettySlug } from "helpers/formatters";
import { getOgImage, ImageQuality, OgImage } from "helpers/img";
import { Immutable } from "helpers/types";
import { useMediaMobile } from "hooks/useMediaQuery";
import { AnchorIds } from "hooks/useScrollTopOnChange";
import Head from "next/head";
import { useRouter } from "next/router";
import { useEffect, useMemo, useState } from "react";
import { useSwipeable } from "react-swipeable";
import { OrderableList } from "./Inputs/OrderableList";
import { Select } from "./Inputs/Select";
import { MainPanel } from "./Panels/MainPanel";
import { Popup } from "./Popup";

interface Props extends AppStaticProps {
  subPanel?: React.ReactNode;
  subPanelIcon?: string;
  contentPanel?: React.ReactNode;
  title?: string;
  navTitle: string | null | undefined;
  thumbnail?: UploadImageFragment;
  description?: string;
}

export function AppLayout(props: Immutable<Props>): JSX.Element {
  const {
    langui,
    currencies,
    languages,
    subPanel,
    contentPanel,
    thumbnail,
    title,
    navTitle,
    description,
    subPanelIcon,
  } = props;
  const router = useRouter();
  const isMobile = useMediaMobile();
  const appLayout = useAppLayout();

  const sensibilitySwipe = 1.1;

  useMemo(() => {
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
    router.events?.on("routeChangeStart", () => {
      appLayout.setConfigPanelOpen(false);
      appLayout.setMainPanelOpen(false);
      appLayout.setSubPanelOpen(false);
    });
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
    router.events?.on("hashChangeStart", () => {
      appLayout.setSubPanelOpen(false);
    });
  }, [appLayout, router.events]);

  const handlers = useSwipeable({
    onSwipedLeft: (SwipeEventData) => {
      if (appLayout.menuGestures) {
        if (SwipeEventData.velocity < sensibilitySwipe) return;
        if (appLayout.mainPanelOpen) {
          appLayout.setMainPanelOpen(false);
        } else if (subPanel && contentPanel) {
          appLayout.setSubPanelOpen(true);
        }
      }
    },
    onSwipedRight: (SwipeEventData) => {
      if (appLayout.menuGestures) {
        if (SwipeEventData.velocity < sensibilitySwipe) return;
        if (appLayout.subPanelOpen) {
          appLayout.setSubPanelOpen(false);
        } else {
          appLayout.setMainPanelOpen(true);
        }
      }
    },
  });

  const turnSubIntoContent = subPanel && !contentPanel;

  const titlePrefix = "Accord’s Library";
  const metaImage: OgImage = thumbnail
    ? getOgImage(ImageQuality.Og, thumbnail)
    : {
        image: "/default_og.jpg",
        width: 1200,
        height: 630,
        alt: "Accord's Library Logo",
      };
  const ogTitle =
    title ?? navTitle ?? prettySlug(router.asPath.split("/").pop());

  const metaDescription = description ?? langui.default_description ?? "";

  useEffect(() => {
    document.getElementsByTagName("html")[0].style.fontSize = `${
      (appLayout.fontSize ?? 1) * 100
    }%`;
  }, [appLayout.fontSize]);

  const currencyOptions: string[] = [];
  currencies.map((currency) => {
    if (currency.attributes?.code)
      currencyOptions.push(currency.attributes.code);
  });
  const [currencySelect, setCurrencySelect] = useState<number>(-1);

  let defaultPreferredLanguages: string[] = [];

  if (router.locale && router.locales) {
    if (router.locale === "en") {
      defaultPreferredLanguages = [router.locale];
      router.locales.map((locale) => {
        if (locale !== router.locale) defaultPreferredLanguages.push(locale);
      });
    } else {
      defaultPreferredLanguages = [router.locale, "en"];
      router.locales.map((locale) => {
        if (locale !== router.locale && locale !== "en")
          defaultPreferredLanguages.push(locale);
      });
    }
  }

  useEffect(() => {
    if (appLayout.currency)
      setCurrencySelect(currencyOptions.indexOf(appLayout.currency));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [appLayout.currency]);

  useEffect(() => {
    if (currencySelect >= 0)
      appLayout.setCurrency(currencyOptions[currencySelect]);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currencySelect]);

  let gridCol = "";
  if (subPanel) {
    if (appLayout.mainPanelReduced) {
      gridCol = "grid-cols-[6rem_20rem_1fr]";
    } else {
      gridCol = "grid-cols-[20rem_20rem_1fr]";
    }
  } else if (appLayout.mainPanelReduced) {
    gridCol = "grid-cols-[6rem_0px_1fr]";
  } else {
    gridCol = "grid-cols-[20rem_0px_1fr]";
  }

  return (
    <div
      className={`${
        appLayout.darkMode ? "set-theme-dark" : "set-theme-light"
      } ${
        appLayout.dyslexic
          ? "set-theme-font-dyslexic"
          : "set-theme-font-standard"
      }`}
    >
      <div
        {...handlers}
        className={`fixed inset-0 touch-pan-y p-0 m-0 bg-light text-black grid
        [grid-template-areas:'main_sub_content'] ${gridCol} mobile:grid-cols-[1fr]
        mobile:grid-rows-[1fr_5rem] mobile:[grid-template-areas:'content''navbar']`}
      >
        <Head>
          <title>{`${titlePrefix} - ${ogTitle}`}</title>

          <meta
            name="twitter:title"
            content={`${titlePrefix} - ${ogTitle}`}
          ></meta>

          <meta name="description" content={metaDescription} />
          <meta name="twitter:description" content={metaDescription}></meta>

          <meta property="og:image" content={metaImage.image}></meta>
          <meta property="og:image:secure_url" content={metaImage.image}></meta>
          <meta
            property="og:image:width"
            content={metaImage.width.toString()}
          ></meta>
          <meta
            property="og:image:height"
            content={metaImage.height.toString()}
          ></meta>
          <meta property="og:image:alt" content={metaImage.alt}></meta>
          <meta property="og:image:type" content="image/jpeg"></meta>
          <meta name="twitter:card" content="summary_large_image"></meta>

          <meta name="twitter:image" content={metaImage.image}></meta>
        </Head>

        {/* Background when navbar is opened */}
        <div
          className={`[grid-area:content] mobile:z-10 absolute
          inset-0 transition-[backdrop-filter] duration-500 ${
            (appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
              ? "[backdrop-filter:blur(2px)]"
              : "pointer-events-none touch-none "
          }`}
        >
          <div
            className={`absolute bg-shade inset-0 transition-opacity duration-500 
        ${turnSubIntoContent ? "" : ""}
        ${
          (appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
            ? "opacity-60"
            : "opacity-0"
        }`}
            onClick={() => {
              appLayout.setMainPanelOpen(false);
              appLayout.setSubPanelOpen(false);
            }}
          ></div>
        </div>

        {/* Content panel */}
        <div
          id={AnchorIds.CONTENT_PANEL}
          className={`[grid-area:content] overflow-y-scroll bg-light texture-paper-dots`}
        >
          {contentPanel ? (
            contentPanel
          ) : (
            <div className="grid place-content-center h-full">
              <div
                className="text-dark border-dark border-2 border-dotted rounded-2xl
              p-8 grid grid-flow-col place-items-center gap-9 opacity-40"
              >
                <p className="text-4xl">❮</p>
                <p className="text-2xl w-64">{langui.select_option_sidebar}</p>
              </div>
            </div>
          )}
        </div>

        {/* Sub panel */}
        {subPanel && (
          <div
            className={`[grid-area:sub] mobile:[grid-area:content] mobile:z-10 mobile:w-[90%]
            mobile:justify-self-end border-r-[1px] mobile:border-r-0 mobile:border-l-[1px]
            border-black border-dotted overflow-y-scroll webkit-scrollbar:w-0
            [scrollbar-width:none] transition-transform duration-300 bg-light texture-paper-dots
          ${
            turnSubIntoContent
              ? "mobile:border-l-0 mobile:w-full"
              : !appLayout.subPanelOpen && "mobile:translate-x-[100vw]"
          }`}
          >
            {subPanel}
          </div>
        )}

        {/* Main panel */}
        <div
          className={`[grid-area:main] mobile:[grid-area:content] mobile:z-10 mobile:w-[90%]
          mobile:justify-self-start border-r-[1px] border-black border-dotted overflow-y-scroll
          webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 bg-light
          texture-paper-dots ${
            appLayout.mainPanelOpen ? "" : "mobile:-translate-x-full"
          }`}
        >
          <MainPanel langui={langui} />
        </div>

        {/* Navbar */}
        <div
          className="[grid-area:navbar] border-t-[1px] border-black border-dotted grid
          grid-cols-[5rem_1fr_5rem] place-items-center desktop:hidden bg-light texture-paper-dots"
        >
          <span
            className="material-icons mt-[.1em] cursor-pointer"
            onClick={() => {
              appLayout.setMainPanelOpen(!appLayout.mainPanelOpen);
              appLayout.setSubPanelOpen(false);
            }}
          >
            {appLayout.mainPanelOpen ? "close" : "menu"}
          </span>
          <p
            className={`font-black font-headers text-center overflow-hidden ${
              ogTitle && ogTitle.length > 30
                ? "text-xl max-h-14"
                : "text-2xl max-h-16"
            }`}
          >
            {ogTitle}
          </p>
          <span
            className="material-icons mt-[.1em] cursor-pointer"
            onClick={() => {
              appLayout.setSubPanelOpen(!appLayout.subPanelOpen);
              appLayout.setMainPanelOpen(false);
            }}
          >
            {subPanel && !turnSubIntoContent
              ? appLayout.subPanelOpen
                ? "close"
                : subPanelIcon
                ? subPanelIcon
                : "tune"
              : ""}
          </span>
        </div>

        <Popup
          state={appLayout.configPanelOpen}
          setState={appLayout.setConfigPanelOpen}
        >
          <h2 className="text-2xl">{langui.settings}</h2>

          <div
            className="mt-4 grid gap-16 justify-items-center
            text-center desktop:grid-cols-[auto_auto]"
          >
            {router.locales && (
              <div>
                <h3 className="text-xl">{langui.languages}</h3>
                {appLayout.preferredLanguages && (
                  <OrderableList
                    items={
                      appLayout.preferredLanguages.length > 0
                        ? new Map(
                            appLayout.preferredLanguages.map((locale) => [
                              locale,
                              prettyLanguage(locale, languages),
                            ])
                          )
                        : new Map(
                            defaultPreferredLanguages.map((locale) => [
                              locale,
                              prettyLanguage(locale, languages),
                            ])
                          )
                    }
                    insertLabels={
                      new Map([
                        [0, langui.primary_language],
                        [1, langui.secondary_language],
                      ])
                    }
                    onChange={(items) => {
                      const preferredLanguages = [...items].map(
                        ([code]) => code
                      );
                      appLayout.setPreferredLanguages(preferredLanguages);
                      if (router.locale !== preferredLanguages[0]) {
                        router.push(router.asPath, router.asPath, {
                          locale: preferredLanguages[0],
                        });
                      }
                    }}
                  />
                )}
              </div>
            )}
            <div className="grid gap-8 place-items-center text-center desktop:grid-cols-2">
              <div>
                <h3 className="text-xl">{langui.theme}</h3>
                <div className="flex flex-row">
                  <Button
                    onClick={() => {
                      appLayout.setDarkMode(false);
                      appLayout.setSelectedThemeMode(true);
                    }}
                    active={
                      appLayout.selectedThemeMode === true &&
                      appLayout.darkMode === false
                    }
                    className="rounded-r-none"
                  >
                    {langui.light}
                  </Button>
                  <Button
                    onClick={() => {
                      appLayout.setSelectedThemeMode(false);
                    }}
                    active={appLayout.selectedThemeMode === false}
                    className="rounded-l-none rounded-r-none border-x-0"
                  >
                    {langui.auto}
                  </Button>
                  <Button
                    onClick={() => {
                      appLayout.setDarkMode(true);
                      appLayout.setSelectedThemeMode(true);
                    }}
                    active={
                      appLayout.selectedThemeMode === true &&
                      appLayout.darkMode === true
                    }
                    className="rounded-l-none"
                  >
                    {langui.dark}
                  </Button>
                </div>
              </div>

              <div>
                <h3 className="text-xl">{langui.currency}</h3>
                <div>
                  <Select
                    options={currencyOptions}
                    state={currencySelect}
                    setState={setCurrencySelect}
                    className="w-28"
                  />
                </div>
              </div>

              <div>
                <h3 className="text-xl">{langui.font_size}</h3>
                <div className="flex flex-row">
                  <Button
                    className="rounded-r-none"
                    onClick={() =>
                      appLayout.setFontSize(
                        appLayout.fontSize
                          ? appLayout.fontSize / 1.05
                          : 1 / 1.05
                      )
                    }
                  >
                    <span className="material-icons !text-base">
                      text_decrease
                    </span>
                  </Button>
                  <Button
                    className="rounded-l-none rounded-r-none border-x-0"
                    onClick={() => appLayout.setFontSize(1)}
                  >
                    {((appLayout.fontSize ?? 1) * 100).toLocaleString(
                      undefined,
                      {
                        maximumFractionDigits: 0,
                      }
                    )}
                    %
                  </Button>
                  <Button
                    className="rounded-l-none"
                    onClick={() =>
                      appLayout.setFontSize(
                        appLayout.fontSize
                          ? appLayout.fontSize * 1.05
                          : 1 * 1.05
                      )
                    }
                  >
                    <span className="material-icons !text-base">
                      text_increase
                    </span>
                  </Button>
                </div>
              </div>

              <div>
                <h3 className="text-xl">{langui.font}</h3>
                <div className="grid gap-2">
                  <Button
                    active={appLayout.dyslexic === false}
                    onClick={() => appLayout.setDyslexic(false)}
                    className="font-zenMaruGothic"
                  >
                    Zen Maru Gothic
                  </Button>
                  <Button
                    active={appLayout.dyslexic === true}
                    onClick={() => appLayout.setDyslexic(true)}
                    className="font-openDyslexic"
                  >
                    OpenDyslexic
                  </Button>
                </div>
              </div>

              <div>
                <h3 className="text-xl">{langui.player_name}</h3>
                <input
                  type="text"
                  placeholder="<player>"
                  className="w-48"
                  onInput={(event) =>
                    appLayout.setPlayerName(
                      (event.target as HTMLInputElement).value
                    )
                  }
                  value={appLayout.playerName}
                />
              </div>
            </div>
          </div>
        </Popup>
      </div>
    </div>
  );
}
