/**
 * @file Menu component
 */

import {
  IonContent,
  IonIcon,
  IonImg,
  IonItem,
  IonLabel,
  IonList,
  IonListHeader,
  IonMenu,
  IonMenuToggle,
} from "@ionic/react";
import {
  createOutline,
  createSharp,
  homeOutline,
  homeSharp,
  lockClosedOutline,
  lockClosedSharp,
  navigateCircleOutline,
  navigateCircleSharp,
  settingsOutline,
  settingsSharp,
} from "ionicons/icons";
import {FC, useRef} from "react";
import {useLocation} from "react-router-dom";

import logo from "~/assets/logo.png";
import {useEphemeralStore} from "~/lib/stores/ephemeral";
import {AuthState} from "~/lib/types";
import {getAuthState} from "~/lib/utils";

/**
 * Menu navigation item position
 */
enum NavItemPosition {
  TOP = "top",
  BOTTOM = "bottom",
}

/**
 * Menu navigation item
 */
interface NavItem {
  /**
   * Item URL
   */
  url: string;

  /**
   * Required authentication state to show this item or undefined if the item is always available
   */
  requiredState: AuthState | undefined;

  /**
   * Item position
   */
  position: NavItemPosition;

  /**
   * iOS icon
   */
  iosIcon: string;

  /**
   * Material Design icon
   */
  mdIcon: string;

  /**
   * Item title
   */
  title: string;
}

/**
 * Menu navigation items
 */
const navItems: NavItem[] = [
  {
    title: "Home",
    requiredState: AuthState.UNAUTHENTICATED,
    url: "/",
    position: NavItemPosition.TOP,
    iosIcon: homeOutline,
    mdIcon: homeSharp,
  },
  {
    title: "Authentication",
    requiredState: AuthState.UNAUTHENTICATED,
    url: "/auth/1",
    position: NavItemPosition.TOP,
    iosIcon: lockClosedOutline,
    mdIcon: lockClosedSharp,
  },
  {
    title: "Nearby",
    requiredState: AuthState.AUTHENTICATED_TERMS,
    url: "/nearby",
    position: NavItemPosition.TOP,
    iosIcon: navigateCircleOutline,
    mdIcon: navigateCircleSharp,
  },
  {
    title: "Create Post",
    requiredState: AuthState.AUTHENTICATED_TERMS,
    url: "/posts/create/1",
    position: NavItemPosition.TOP,
    iosIcon: createOutline,
    mdIcon: createSharp,
  },
  {
    title: "Settings",
    requiredState: AuthState.AUTHENTICATED_TERMS,
    url: "/settings",
    position: NavItemPosition.BOTTOM,
    iosIcon: settingsOutline,
    mdIcon: settingsSharp,
  },
];

/**
 * Navigation item component
 * @param item Navigation item
 * @returns JSX
 */
const NavItem: FC<NavItem> = item => {
  // Hooks
  const location = useLocation();

  return (
    <IonMenuToggle autoHide={false}>
      <IonItem
        className={location.pathname === item.url ? "selected" : ""}
        routerLink={item.url}
        routerDirection="none"
        lines="none"
        detail={false}
      >
        <IonIcon
          aria-hidden="true"
          slot="start"
          ios={item.iosIcon}
          md={item.mdIcon}
        />

        <IonLabel>{item.title}</IonLabel>
      </IonItem>
    </IonMenuToggle>
  );
};

/**
 * Menu component
 * @returns JSX
 */
export const Menu: FC = () => {
  // Hooks
  const user = useEphemeralStore(state => state.user);
  const menu = useRef<HTMLIonMenuElement>(null);

  return (
    <IonMenu contentId="main" type="overlay" ref={menu}>
      <IonContent>
        <IonList className="flex flex-col h-full py-4">
          <IonListHeader className="p-0">
            <div className="flex flex-row items-center justify-center my-8 w-full">
              <IonImg alt="Beacon logo" className="h-14 w-14 mr-2" src={logo} />
              <span className="ml-2 text-3xl">Beacon</span>
            </div>
          </IonListHeader>

          {navItems
            .filter(
              navItem =>
                user !== undefined &&
                navItem.position === NavItemPosition.TOP &&
                (navItem.requiredState === undefined ||
                  navItem.requiredState === getAuthState(user)),
            )
            .map((navItem, index) => (
              <NavItem key={index} {...navItem} />
            ))}

          <div className="flex-1" />

          {navItems
            .filter(
              navItem =>
                user !== undefined &&
                navItem.position === NavItemPosition.BOTTOM &&
                (navItem.requiredState === undefined ||
                  navItem.requiredState === getAuthState(user)),
            )
            .map((navItem, index) => (
              <NavItem key={index} {...navItem} />
            ))}
        </IonList>
      </IonContent>
    </IonMenu>
  );
};
