import { Box } from "@mui/material";
import DisplayDrawer from "common/DisplayDrawer";
import DeviceViewer from "device/DeviceViewer";
import MapMarkerSettings from "maps/MapMarkerSettings";
import { Device } from "models";
import { pond } from "protobuf-ts/pond";
import { useDeviceAPI, useGlobalState, useSnackbar } from "providers";
import React, { useEffect, useState } from "react";

interface Props {
  open: boolean;
  onClose: () => void;
  selectedDevice: string;
  devices: Map<string, Device>;
  removeMarker: (key: string) => void;
  updateMarker: (key: string, newSettings: pond.DeviceSettings) => void;
  moveMap: (long: number, lat: number) => void;
}

export default function DeviceDrawer(props: Props) {
  const { open, onClose, selectedDevice, devices, removeMarker, updateMarker, moveMap } = props;
  const [{as}] = useGlobalState();
  const [device, setDevice] = useState<Device>(Device.create());
  const [openMarkerSettings, setOpenMarkerSettings] = useState(false);
  const deviceAPI = useDeviceAPI();
  const { openSnack } = useSnackbar();

  useEffect(() => {
    let d = devices.get(selectedDevice);
    if (d) {
      setDevice(d);
    }
  }, [selectedDevice, devices]);

  const closeDrawer = () => {
    onClose();
  };

  const displayNext = () => {
    let devArr = Array.from(devices.values());
    let index = devArr.indexOf(device);
    let found = false;
    do {
      if (index === devArr.length - 1) {
        index = 0;
      } else {
        index++;
      }
      let nextDev = devArr[index];
      if (
        nextDev.location().longitude !== 0 &&
        nextDev.location().longitude !== 0 &&
        nextDev.location().latitude !== undefined &&
        nextDev.location().longitude !== undefined
      ) {
        setDevice(nextDev);
        moveMap(nextDev.location().longitude, nextDev.location().latitude);
        found = true;
      }
    } while (!found);
  };

  const displayPrev = () => {
    let devArr = Array.from(devices.values());
    let index = devArr.indexOf(device);
    let found = false;
    do {
      if (index === 0) {
        index = devArr.length - 1;
      } else {
        index--;
      }
      let nextDev = devArr[index];
      if (
        nextDev.location().longitude !== 0 &&
        nextDev.location().longitude !== 0 &&
        nextDev.location().latitude !== undefined &&
        nextDev.location().longitude !== undefined
      ) {
        setDevice(nextDev);
        moveMap(nextDev.location().longitude, nextDev.location().latitude);
        found = true;
      }
    } while (!found);
  };

  const drawerBody = () => {
    return device.id() !== 0 ? <DeviceViewer device={device} isMobile={true} /> : <Box></Box>;
  };

  /**
   * function to remove the marker and coordinates from the object
   */
  const remove = () => {
    //set the long/lat of the yard to 0 and call an update
    let settings = device.settings;
    settings.longitude = 0;
    settings.latitude = 0;
    deviceAPI
      .update(device.id(), settings, as)
      .then(resp => {
        openSnack("Marker Removed");
        //then use the removeMarker prop function to update the markers in the parent map
        removeMarker(device.id().toString());
      })
      .catch(err => {
        openSnack("Failed to remove marker");
      });
  };

  /**
   * function to update the settings of the marker
   */
  const update = () => {
    setOpenMarkerSettings(true);
  };

  return (
    <React.Fragment>
      <DisplayDrawer
        open={open}
        onClose={closeDrawer}
        displayNext={displayNext}
        displayPrev={displayPrev}
        title={device.name()}
        width={"40vw"}
        drawerBody={drawerBody()}
        updateElement={update}
        removeElement={remove}
      />
      <MapMarkerSettings
        close={() => {
          setOpenMarkerSettings(false);
        }}
        open={openMarkerSettings}
        theme={device.settings.theme ?? pond.ObjectTheme.create()}
        colourControl
        updateObject={newTheme => {
          let settings = device.settings;
          settings.theme = newTheme;
          deviceAPI
            .update(device.id(), settings, as)
            .then(resp => {
              openSnack("marker settings updated");
              updateMarker(device.id().toString(), settings);
            })
            .catch(() => {
              openSnack("failed to update marker settings");
            });
        }}
      />
    </React.Fragment>
  );
}
