import Head from 'next/head'
import { ReactElement, useEffect, useState } from 'react'
import LayoutReadyOrNot from '../components/layout'
import styles from '/styles/ReadyOrNot.module.css'
import { NextPageWithLayout } from './_app';
import React from 'react';
import useSWR, { KeyedMutator, mutate } from 'swr';
import { useRouter } from 'next/router';
import Image from 'next/image'
import ReadyOrNotMap from '../interfaces/ReadyOrNot';

const fetcher = (url: string) => fetch(url).then((res) => res.json())

function useWindowSize() {
  const [windowSize, setWindowSize] = useState({
    width: 0,
    height: 0,
  });

  useEffect(() => {
    function handleResize() {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }
    
    window.addEventListener("resize", handleResize);

    handleResize();

    return () => window.removeEventListener("resize", handleResize);
  }, []);
  return windowSize.width <= 1080;
}

const ReadyOrNotMaps: NextPageWithLayout = () => {
  const [floor, setFloor] = useState(0);
  const { mapInfo, isLoadingInfo, isErrorInfo } = useMap(useRouter().query.map?.toString() || "a_lethal_obsession")
  const { mapImages, isLoadingImages, isErrorImages, mutateImage } = useImages(useRouter().query.map?.toString() || "a_lethal_obsession")
  const isMobile = useWindowSize();

  let infoHtml: ReactElement = <></>;
  let mapHtml: ReactElement = <></>;
  if (isErrorInfo) {
    infoHtml = (
      <h1 className={styles.title}>
        <a>Error loading page Data</a>
      </h1>
    )
  }
  else if (isLoadingInfo) {
    infoHtml = (
      <h1 className={styles.title}>
        <a>Loading...</a>
      </h1>
    )
  }
  else {
    const info = mapInfo
    infoHtml = (
      <h1 className={styles.title}>
        <a>{info.name} ({info.alias})</a>
      </h1>
    )

    if (isErrorImages) {
      mapHtml = <div className={styles.mapContainer}><p>Error loading Map or Map not present</p></div>
    }
    else if (isLoadingImages) {
      mapHtml = <div className={styles.mapContainer}><p>Loading...</p></div>
    }
    else if(info.floors){
      // TODO: ask Yahia if he would rather the buttons turn off at the corresponding limits
      // move to highest floor after going down from lowest
      if (floor < info.floors[0]) {
        setFloor(info.floors[info.floors.length-1])
      }
      // move to lowest floor after going up from highest
      if (floor > info.floors[info.floors.length-1]) {
        setFloor(info.floors[0])
      }

      // map the images to the corresponding floor number in an array
      let images: string[] = [];
      mapImages.forEach((image, index) => {
        // assign the floor number of the image position, since floors and images are synced from the info object this works
        images[info.floors[index]] = image
      });

      let inverseFloors = info.floors.slice(0);
      inverseFloors.reverse()
      
      mapHtml = (
        <div className={[styles.mapContainer, (isMobile ? styles.mc_mobile : styles.mc_desktop)].join(" ")}>
          <div className={[
              styles.floorIndicator,
              (isMobile ? styles.findicator_mobile : styles.findicator_desktop)
            ].join(" ")}>
            <p className={[
              styles.floorNumber, 
              (isMobile ? styles.fn_mobile : styles.fn_desktop)
            ].join(" ")}>{floor}</p>
            {inverseFloors.map((level: number, index: number) => (
              <div key={level} className={[
                styles.floorIcon, 
                (floor == level ? styles.fi_active : styles.fi_inactive), 
                (isMobile ? styles.fi_mobile : styles.fi_desktop)
              ].join(" ")} onClick={() => {setFloor(level)}}></div>
            ))}
          </div>
          <div className={[styles.map, (isMobile ? styles.map_mobile : styles.map_desktop)].join(" ")}>
            <Image alt="Floorplan" src={images[floor]} layout="fill" objectFit='contain'></Image>
          </div>
          <div className={[
            styles.floorSelection,
            (isMobile ? styles.fs_mobile : styles.fs_desktop)
          ].join(" ")}>
            <button className={[
              styles.floor_button,
              (isMobile ? styles.fb_mobile : "")
            ].join(" ")} onClick={() => setFloor(floor + 1)} >+</button>
            <button className={[
              styles.floor_button,
              (isMobile ? styles.fb_mobile : "")
            ].join(" ")} onClick={() => setFloor(floor - 1)} >-</button>
          </div>
        </div>
      )
    }
    else {
      mapHtml = <div className={styles.mapContainer}><p>Invalid or missing floor info: {info.floors}</p></div>
    }
  }

  // TODO: set background here depending on image loaded
  return (
    <>
      <Head>
        <title>Ready or Not</title>
        <meta charSet='utf-8' />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      {infoHtml}
      {mapHtml}
    </>
  )
}

ReadyOrNotMaps.getLayout = function getLayout(page: ReactElement) {
  return (
    <LayoutReadyOrNot>
      {page}
    </LayoutReadyOrNot>
  )
}

function useMap(path: string):{mapInfo: ReadyOrNotMap, isLoadingInfo: boolean, isErrorInfo: boolean} {
  const { data, error } = useSWR(`/api/${path}`, fetcher)

  return {
    mapInfo: data,
    isLoadingInfo: !error && !data,
    isErrorInfo: error
  }
}

function useImages(path: string):{mapImages: string[], isLoadingImages: boolean, isErrorImages: boolean, mutateImage: KeyedMutator<any>} {
  const { data, error, mutate } = useSWR(`/api/${path}/maps`, fetcher)

  return {
    mapImages: data,
    isLoadingImages: !error && !data,
    isErrorImages: error,
    mutateImage: mutate,
  }
}

export default ReadyOrNotMaps;