import { Menubar } from 'primereact/menubar';
import React, { useContext, useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { AuthContext, TimeContext } from '../contexts';
import { Configuration } from '../services';
import { Airport } from '../services';
import { AirportOverview, BackendReturnStatus, IAuthState } from '../types';

export const NavBar: React.FC = () => {
  const [timestamp, setTimestamp] = useState<string>('');
  const [fullName, setFullName] = useState<string>('');
  const [menuTree, setMenuTree] = useState<any>(undefined);
  const authContext = useContext(AuthContext);
  const timeContext = useContext(TimeContext);
  const currentAuth = useRef<IAuthState>();
  const navigate = useNavigate();

  currentAuth.current = authContext.auth;

  const firBasedSubMenu = (airports: AirportOverview[], endpoint: string): any[] => {
    if (airports.length === 0) {
      return [{
        label: 'No airport available',
        disabled: true,
      }];
    }

    const firAirports: [string, AirportOverview[]][] = [];

    // cluster airports based on FIRs
    airports.forEach((airport) => {
      const idx = firAirports.findIndex((value) => value[0] === airport.flightInformationRegion);
      if (idx !== -1) {
        firAirports[idx][1].push(airport);
      } else {
        firAirports.push([airport.flightInformationRegion, [airport]]);
      }
    });

    // create the submenu for every FIR
    const retval: any[] = [];
    firAirports.forEach((fir) => {
      retval.push({
        label: fir[0],
        items: [],
      });

      // sort airports alphabetically
      fir[1].sort();

      // create the airport with the link
      fir[1].forEach((airport) => {
        retval[retval.length - 1].push({
          label: `${airport.icao} - ${airport.name}`,
          command: () => navigate(`${endpoint}?icao=${airport.icao}`),
        });
      });
    });

    return retval;
  }

  const updateMenuItems = async () => {
    if (currentAuth.current === undefined || !currentAuth.current.valid) return [];

    Airport.all().then((response) => {
      if (response.status !== BackendReturnStatus.Ok) return [];

      const newMenuTree: { label: string; items?: any[]; command?: () => void }[] = [
        {
          label: 'Airports',
          items: [] as any[],
        }
      ];

      // create the airports subtree
      const airportSubtree = firBasedSubMenu(response.airports, '/sequence');
      newMenuTree[0].items = airportSubtree;

      // collect all configuration airports
      const configurationAirports: AirportOverview[] = [];
      response.airports.forEach((airport) => {
        const idx = currentAuth.current?.user.airportConfigurationAccess.findIndex((value) => airport.icao === value);
        if (idx !== -1) configurationAirports.push(airport);
      });

      // create the configuration subtree
      if (configurationAirports.length !== 0) {
        const configurationSubtree = firBasedSubMenu(configurationAirports, '/configure/airport');
        newMenuTree[1].items = configurationSubtree;
      }

      if (currentAuth.current?.user.administrator) {
        newMenuTree.push({
          label: 'Administration',
          items: [
            {
              label: 'Users',
              command: () => navigate('/admin/users'),
            },
            {
              label: 'Airports',
              command: () => navigate('/admin/airports'),
            },
          ],
        });
      }

      newMenuTree.push({
        label: 'Logout',
        command: () => navigate('/logout'),
      });

      setMenuTree(newMenuTree);
    });
  }

  useEffect(() => {
    const event = new EventSource(`${Configuration.resourceServer}/airport/renew`);
    event.onmessage = () => {
      updateMenuItems();
    }

    const timeInterval = setInterval(() => {
      const serverUtcTime = new Date(new Date().getTime() + timeContext.offset);
      const hours = String(serverUtcTime.getUTCHours()).padStart(2, '0');
      const minutes = String(serverUtcTime.getUTCMinutes()).padStart(2, '0');
      const seconds = String(serverUtcTime.getUTCSeconds()).padStart(2, '0');
      if (currentAuth.current?.valid) {
        setTimestamp(`${hours}:${minutes}:${seconds}`);
      }
    }, 1000);

    return () => {
      clearInterval(timeInterval);
      event.close();
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    if (currentAuth.current?.valid) {
      if (currentAuth.current.user.fullName !== '') {
        setFullName(currentAuth.current.user.fullName);
      } else {
        setFullName(currentAuth.current.user.vatsimId);
      }
      updateMenuItems();
    } else {
      setFullName('');
      setMenuTree([]);
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [authContext]);

  if (menuTree === undefined || !currentAuth.current.valid) return <></>;

  const rightSideInfo = (
    <div>{fullName} | {timestamp}</div>
  );

  return (menuTree.length !== 0 ? <Menubar model={menuTree} end={rightSideInfo} /> : <></>);
};
