import { useEffect, useRef } from "react";
import { useMap } from "react-map-gl/mapbox";
import { FeatureCollection } from "geojson";
import MapboxDraw from "@mapbox/mapbox-gl-draw";

interface Props {
  featureCollection: FeatureCollection;
  editMode?: "drawPolygon" | "drawLine" | "drawPoint" | "edit" | "none" | "delete";
  linePointLimit?: number;
  measurement?: boolean;
  onCreate: (event: any, objectToCut?: string, measurement?: boolean) => void;
  onUpdate: (event: any) => void;
}
const draw = new MapboxDraw({
  displayControlsDefault: false
});

export default function DrawController(props: Props) {
  const { featureCollection, editMode, onCreate, onUpdate, linePointLimit, measurement } = props;
  //const [shapeToCut, setShapeToCut] = useState();
  const cutRef = useRef(); //the object id for what shape to cut a hole
  const mRef = useRef<boolean>();
  const lineLimitRef = useRef<number | undefined>();
  //const pointsRef = useRef<number[][]>([]);
  const { current: map } = useMap();

  //use effect is just for adding and removing the controller from the map
  useEffect(() => {
    if (map) {
      if (editMode && editMode !== "none" && !map.hasControl(draw)) {
        map.addControl(draw);
      } else if ((!editMode || editMode === "none") && map.hasControl(draw)) {
        map.removeControl(draw);
      }
    }
  }, [map, editMode]);

  useEffect(() => {
    lineLimitRef.current = linePointLimit;
    mRef.current = measurement;
  }, [linePointLimit, measurement]);

  //useEffect for adding event handlers to the map
  useEffect(() => {
    if (map) {
      map.on("draw.create", e => {
        //console.log("draw create");
        //using refs rather than state variables you can effectively get the state in an event listener
        onCreate(e, cutRef.current, mRef.current);
      });
      map.on("draw.update", e => {
        onUpdate(e);
      });
      map.on("click", ["shapefill", "shapeborder"], e => {
        //set the ref to be undefined
        cutRef.current = undefined;
        if (map.hasControl(draw) && e.features) {
          let mode = draw.getMode();
          let id = e.features[0].properties?.objectKey;
          if (mode === "simple_select" && id) {
            if (draw.get(id)) {
              draw.changeMode("direct_select", {
                // The id of the feature that will be directly selected (required)
                featureId: id
              });
            }
          } else if (mode === "draw_polygon") {
            //if a feature was clicked on set ref to have its id
            cutRef.current = id;
            //setShapeToCut(id);
          }
        }
      });
      // map.on("click", e => {
      //   if (map.hasControl(draw) && draw.getMode() === "draw_line_string") {
      //     if (lineLimitRef.current) {
      //       pointsRef.current.push([e.lngLat.lng, e.lngLat.lat]);
      //       if (pointsRef.current.length === lineLimitRef.current) {
      //         draw.changeMode("simple_select"); //changing the mode causes the create event to fire
      //         pointsRef.current = [];
      //         draw.changeMode("draw_line_string");
      //       }
      //     }
      //   }
      // });
    }
  }, [map]); // eslint-disable-line react-hooks/exhaustive-deps

  //useEffect for changing draw mode for the controller based on the editor mode from the object controller
  useEffect(() => {
    if (editMode === "drawPolygon") {
      draw.deleteAll();
      draw.changeMode("draw_polygon");
    } else if (editMode === "drawLine") {
      draw.deleteAll();
      draw.changeMode("draw_line_string");
    } else if (editMode === "drawPoint") {
      draw.deleteAll();
      draw.changeMode("draw_point");
    } else if (editMode === "delete") {
      draw.deleteAll();
      draw.changeMode("simple_select");
    } else if (editMode === "edit") {
      draw.set(featureCollection);
      if (draw.getMode() !== "simple_select" && draw.getMode() !== "direct_select") {
        draw.changeMode("simple_select");
      }
    }
  }, [editMode, featureCollection]);

  return null;
}
