import React, { useEffect, useState } from "react";
import useStyles from "../useStyles";
import L from "leaflet";
import { MapContainer, TileLayer, Marker, Popup, useMap } from "react-leaflet";
import { Button } from "@material-ui/core";

import { useUserContext } from "../Contexts/UserContext";
import { useVehicleContext, VehicleProvider } from "../Contexts/VehicleContext";
import { VehiclePopUp } from "./popup";
import GreenMarkerIcon from "../../assets/green-marker.png";
import GrayMarkerIcon from "../../assets/gray-marker.png";
import { logger } from "../../services/monitoring";

const Component = () => {
  const classes = useStyles();
  const {
    token: {
      idToken: { jwtToken: token },
    },
  } = useUserContext();
  const { getConnections, getLocations, getState } = useVehicleContext();

  const REQUEST_INTERVAL = 10000;

  const [center, setCenter] = useState([0, 0]);
  const [zoom, setZoom] = useState(2);
  const [markers, setMarkers] = useState([]);

  useEffect(() => {
    if (!token) return;
    retrieveAndStoreLocations(token).then((points) => {
      centerAroundMarkers(points);
    });
    const id = setInterval(function () {
      retrieveAndStoreLocations(token);
    }, REQUEST_INTERVAL);
    return () => {
      clearInterval(id);
    };
    // eslint-disable-next-line
  }, [token]);

  const retrieveAndStoreLocations = (accessToken) => {
    return getLocations(accessToken)
      .then((result) => {
        if (result.data != null) {
          const points = result.data.map((point) => [
            point.latitude,
            point.longitude,
            point.vin,
          ]);
          setMarkers(points);
          return points;
        }
        return [];
      })
      .catch((error) => logger.warn(error.stack));
  };

  const centerAroundMarkers = (points) => {
    // if (markers == null) {
    //   markers = []
    // }
    // const coord = markers.reduce((coord, marker) => {
    //   coord[0] += marker[0] / markers.length;
    //   coord[1] += marker[1] / markers.length;
    //   return coord;
    // }, [0, 0])

    setCenter([37.0902, -95.7129]);
    setZoom(4.5);
  };

  const [connections, setConnections] = useState({});

  useEffect(() => {
    if (!token) return;
    if (markers.length > 0) {
      const vins = markers.map((marker) => marker[2]);
      getConnections(vins, token).then((conns) => {
        setConnections(conns);
      });
    }
    // eslint-disable-next-line
  }, [markers, token]);

  const [selectedVIN, setSelectedVIN] = useState(null);
  const [carState, setCarState] = useState(null);

  useEffect(() => {
    if (selectedVIN != null) {
      retrieveAndStoreCarState(selectedVIN);
      const id = setInterval(function () {
        retrieveAndStoreCarState(selectedVIN);
      }, REQUEST_INTERVAL);
      return () => {
        clearInterval(id);
      };
    }
    // eslint-disable-next-line
  }, [selectedVIN]);

  const selectCar = (e, vin) => {
    e.preventDefault();
    setSelectedVIN(vin);
  };

  const retrieveAndStoreCarState = (vin) => {
    getState(token, vin).then((results) => {
      setCarState({ ...results.data, vin: vin });
    });
  };

  const handleClose = () => {
    setSelectedVIN(null);
    setCarState(null);
  };

  function getCarIcon(vin) {
    let icon = GrayMarkerIcon;

    if (connections[vin]) {
      icon = GreenMarkerIcon;
    }

    return new L.Icon({
      iconUrl: icon,
      iconAnchor: [24, 42],
    });
  }

  return (
    <MapContainer
      center={center}
      zoom={zoom}
      style={{
        width: "100%",
        height: "900px",
      }}
    >
      <TileLayer
        attribution='&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <CenterFocus center={center} zoom={zoom} />

      {markers.map((marker) => (
        <Marker
          icon={getCarIcon(marker[2])}
          key={marker[2]}
          position={[marker[0], marker[1]]}
          title={marker[2]}
          opacity={0.9}
        >
          <Popup>
            <div align="center">
              <p className={classes.markerTitle}>
                <b>{marker[2]}</b>
              </p>
              <Button
                type="submit"
                variant="contained"
                color="primary"
                onClick={(e) => selectCar(e, marker[2])}
              >
                View Stats
              </Button>
            </div>
          </Popup>
        </Marker>
      ))}

      {carState ? (
        <VehiclePopUp
          key={carState.vin}
          vin={carState.vin}
          online={carState.online}
          battery={carState.battery}
          doors={carState.doors}
          location={carState.location}
          windows={carState.windows}
          trex_version={carState.trex_version}
          updated={carState.updated}
          className={classes.popup}
          onClose={handleClose}
        />
      ) : null}
    </MapContainer>
  );
};

const CenterFocus = ({ center, zoom }) => {
  const map = useMap();

  useEffect(() => {
    if (center[0] === 0 && center[1] === 0) {
      map.flyTo([0, 0], 2, { duration: 1.5 });
    } else {
      map.flyTo(center, zoom, { duration: 1.5 });
    }
  }, [center, zoom, map]);

  return null;
};

const VehicleMap = () => (
  <VehicleProvider>
    <Component />
  </VehicleProvider>
);

export default VehicleMap;
