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 { getClient, Indexes, search, SearchResult } from "helpers/search";
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 { Ico, Icon } from "./Ico";
import { OrderableList } from "./Inputs/OrderableList";
import { Select } from "./Inputs/Select";
import { TextInput } from "./Inputs/TextInput";
import { MainPanel } from "./Panels/MainPanel";
import { Popup } from "./Popup";

interface Props extends AppStaticProps {
  subPanel?: React.ReactNode;
  subPanelIcon?: Icon;
  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 = Icon.Tune,
  } = props;
  const router = useRouter();
  const isMobile = useMediaMobile();
  const appLayout = useAppLayout();

  /*
   * const [searchQuery, setSearchQuery] = useState("");
   * const [searchResult, setSearchResult] = useState<SearchResult>();
   */

  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 client = getClient();
   * useEffect(() => {
   *   if (searchQuery.length > 1) {
   *     search(client, Indexes.Post, searchQuery).then((result) => {
   *       setSearchResult(result);
   *     });
   *   } else {
   *     setSearchResult(undefined);
   *   }
   *   // eslint-disable-next-line react-hooks/exhaustive-deps
   * }, [searchQuery]);
   */

  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 metaTitle = `${titlePrefix} - ${ogTitle}`;

  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 m-0 grid touch-pan-y bg-light p-0 text-black
        [grid-template-areas:'main_sub_content'] ${gridCol} mobile:grid-cols-[1fr]
        mobile:grid-rows-[1fr_5rem] mobile:[grid-template-areas:'content''navbar']`}
      >
        <Head>
          <title>{metaTitle}</title>
          <meta name="description" content={metaDescription} />

          <meta name="twitter:title" content={metaTitle}></meta>
          <meta name="twitter:description" content={metaDescription}></meta>
          <meta name="twitter:card" content="summary_large_image"></meta>
          <meta name="twitter:image" content={metaImage.image}></meta>

          <meta property="og:title" content={metaTitle} />
          <meta property="og:description" content={metaDescription} />
          <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>
        </Head>

        {/* Background when navbar is opened */}
        <div
          className={`absolute inset-0 transition-[backdrop-filter]
          duration-500 [grid-area:content] mobile:z-10 ${
            (appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
              ? "[backdrop-filter:blur(2px)]"
              : "pointer-events-none touch-none "
          }`}
        >
          <div
            className={`absolute inset-0 bg-shade 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.ContentPanel}
          className={`texture-paper-dots overflow-y-scroll bg-light [grid-area:content]`}
        >
          {contentPanel ? (
            contentPanel
          ) : (
            <div className="grid h-full place-content-center">
              <div
                className="grid grid-flow-col place-items-center gap-9 rounded-2xl
              border-2 border-dotted border-dark p-8 text-dark opacity-40"
              >
                <p className="text-4xl">❮</p>
                <p className="w-64 text-2xl">{langui.select_option_sidebar}</p>
              </div>
            </div>
          )}
        </div>

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

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

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

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

          <div
            className="mt-4 grid justify-items-center gap-16
            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 place-items-center gap-8 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"
                    text={langui.light}
                  />
                  <Button
                    onClick={() => {
                      appLayout.setSelectedThemeMode(false);
                    }}
                    active={appLayout.selectedThemeMode === false}
                    className="rounded-l-none rounded-r-none border-x-0"
                    text={langui.auto}
                  />
                  <Button
                    onClick={() => {
                      appLayout.setDarkMode(true);
                      appLayout.setSelectedThemeMode(true);
                    }}
                    active={
                      appLayout.selectedThemeMode === true &&
                      appLayout.darkMode === true
                    }
                    className="rounded-l-none"
                    text={langui.dark}
                  />
                </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
                      )
                    }
                    icon={Icon.TextDecrease}
                  />
                  <Button
                    className="rounded-l-none rounded-r-none border-x-0"
                    onClick={() => appLayout.setFontSize(1)}
                    text={`${((appLayout.fontSize ?? 1) * 100).toLocaleString(
                      undefined,
                      {
                        maximumFractionDigits: 0,
                      }
                    )}%`}
                  />
                  <Button
                    className="rounded-l-none"
                    onClick={() =>
                      appLayout.setFontSize(
                        appLayout.fontSize
                          ? appLayout.fontSize * 1.05
                          : 1 * 1.05
                      )
                    }
                    icon={Icon.TextIncrease}
                  />
                </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"
                    text="Zen Maru Gothic"
                  />
                  <Button
                    active={appLayout.dyslexic === true}
                    onClick={() => appLayout.setDyslexic(true)}
                    className="font-openDyslexic"
                    text="OpenDyslexic"
                  />
                </div>
              </div>

              <div>
                <h3 className="text-xl">{langui.player_name}</h3>
                <TextInput
                  placeholder="<player>"
                  className="w-48"
                  state={appLayout.playerName}
                  setState={appLayout.setPlayerName}
                />
              </div>
            </div>
          </div>
        </Popup>

        {/* <Popup
          state={appLayout.searchPanelOpen}
          setState={appLayout.setSearchPanelOpen}
        >
          <div className="grid place-items-center gap-2">
            TODO: add to langui
            <h2 className="text-2xl">{"Search"}</h2>
            <TextInput
              className="mb-6 w-full"
              placeholder={"Search query..."}
              state={searchQuery}
              setState={setSearchQuery}
            />
          </div>
          TODO: add to langui
          <div className="grid gap-4">
            <p className="font-headers text-xl">In news:</p>
            <div
              className="grid grid-cols-2 items-end gap-8
                desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] mobile:gap-4"
            >
              {searchResult?.hits.map((hit) => (
                <PreviewCard
                  key={hit.id}
                  href={hit.href}
                  title={hit.title}
                  thumbnailAspectRatio={"3/2"}
                  thumbnail={hit.thumbnail}
                  keepInfoVisible
                />
              ))}
            </div>
          </div>
        </Popup> */}
      </div>
    </div>
  );
}