import v4 from "uuid";
import GeoJSON from "ol/format/GeoJSON";
import { getLayer } from "../../openlayers-utils/layer-utilities";
import shp from "shpjs";
import KMLConvert from "@mapbox/togeojson";
import extractFiles from "extract-files/extractFiles.mjs";
import isExtractableFile from "extract-files/isExtractableFile.mjs";

export default {
  name: "addData",

  getReducer() {
    const initialData = {
      shouldAddListeners: false,
    };

    return (state = initialData, { type, payload }) => {
      switch (type) {
        case "ADD_DATA_ADDED_GEOJSON":
          return Object.assign({}, state, payload);
        case "MAP_INITIALIZED":
          return Object.assign({}, state, {
            shouldAddListeners: true,
          });
        case "TURN_OFF_ADD_LISTENERS":
          return Object.assign({}, state, {
            shouldAddListeners: false,
          });
        default:
          return state;
      }
    };
  },

  doDispatchNotification:
    (message) =>
    ({ dispatch, store }) => {
      store.doNotificationsFire({
        title: "Add Data Error",
        message: message,
        level: "danger",
      });
    },

  doAddDataFile:
    (file) =>
    ({ dispatch, store }) => {
      store.doBasicToolbarDeactivate();
      let uid, options;
      let reader = new FileReader();

      if (file && file.name.match(/\.(geojson|json)$/)) {
        reader.onload = function () {
          try {
            const data = JSON.parse(reader.result);
            store.doAddDataGeojson(file.name, data);
          } catch (err) {
            store.doDispatchNotification(err.message || "Error adding data");
          }
        };
        reader.readAsText(file);
      } else if (file && file.name.match(/\.(zip)$/)) {
        reader.onload = function (e) {
          try {
            const buffer = e.currentTarget.result;
            shp(buffer)
              .then((geojson) => {
                console.log(geojson);
                store.doAddDataGeojson(file.name, geojson);
              })
              .catch((err) => {
                store.doDispatchNotification(
                  err.message || "Error adding data"
                );
              });
          } catch (err) {
            store.doDispatchNotification(err.message || "Error adding data");
          }
        };
        reader.readAsArrayBuffer(file);
      } else if (file && file.name.match(/\.(kml)$/)) {
        reader.onload = function (e) {
          try {
            let fileInfo = e.currentTarget.result;
            let utf8decoder = new TextDecoder();
            let u8arr = new Uint8Array(fileInfo);
            let decodedFileInfo = utf8decoder.decode(u8arr);
            console.log(decodedFileInfo);

            // read in our KML file and then parse it
            const parsedKML = new DOMParser().parseFromString(
              decodedFileInfo,
              "text/html"
            );
            // convert our kml to geojson and store the results
            const geojson = KMLConvert.kml(parsedKML);
            store.doAddDataGeojson(file.name, geojson);
          } catch (err) {
            store.doDispatchNotification(err.message || "Error adding data");
          }
        };
        reader.readAsArrayBuffer(file);
      } else if (file && file.name.match(/\.(kmz)$/)) {
        reader.onload = function (e) {
          try {
            let fileInfo = e.currentTarget.result;
            let utf8decoder = new TextDecoder();
            let u8arr = new Uint8Array(fileInfo);
            let decodedFileInfo = utf8decoder.decode(u8arr);
            console.log(decodedFileInfo);

            // read in our KML file and then parse it
            // const KMZ = new DOMParser().parseFromString(decodedFileInfo);
            // convert our kml to geojson and store the results
            // const geojson = KMLConvert.kml(parsedKML);

            // const file1 = new File(["1"], "BuxtonNC.kmz", {
            //   type: "text/plain",
            // });

            // const value = {
            //   a: file1,
            // };

            // const { clone, files } = extractFiles(
            //   value,
            //   isExtractableFile,
            //   "prefix"
            // );

            // store.doAddDataGeojson(file.name, geojson);
          } catch (err) {
            store.doDispatchNotification(err.message || "Error adding data");
          }
        };

        reader.readAsArrayBuffer(file);
      } else {
        if (file) {
          store.doDispatchNotification(
            `${file.name} is not a supported GeoJSON or shapfile file type`
          );
        }
      }
    },

  doAddDataGeojson:
    (filename, geojson) =>
    ({ dispatch, store }) => {
      store.doSetCursor("wait");
      const parentUid = store.selectTreeViewRootId();
      const uid = v4();

      const mapLayer = getLayer({
        serviceType: "LocalVector",
        visible: true,
      });

      const features = new GeoJSON().readFeatures(geojson, {
        dataProjection: "EPSG:4326",
        featureProjection: "EPSG:3857",
      });

      const src = mapLayer.getSource();
      src.addFeatures(features);

      if (store.hasOwnProperty("doGeojsonIdentAddFeatures")) {
        store.doGeojsonIdentAddFeatures(uid, geojson, mapLayer);
      }

      store.doAddLayer({
        uid: uid,
        displayName: filename,
        parentUid: parentUid,
        mapLayer: mapLayer,
        serviceType: "LocalVector",
        visible: true,
        zoomTo: true,
      });

      store.doSetCursor();
      dispatch({ type: "ADD_DATA_ADDED_GEOJSON", payload: { key: uid } });
    },

  doMapDropDataFile:
    (e) =>
    ({ dispatch, store }) => {
      e.preventDefault();
      e.stopPropagation();
      const files = e.dataTransfer.files;
      const file = files[0];
      store.doAddDataFile(file);
    },

  doAddMapDragDropListeners:
    () =>
    ({ dispatch, store }) => {
      dispatch({ type: "TURN_OFF_ADD_LISTENERS" });
      const olMap = store.selectMap();
      const map = olMap.getTargetElement();

      map.addEventListener(
        "dragleave",
        function (e) {
          e = e || event;
          e.preventDefault();
        },
        false
      );
      map.addEventListener(
        "dragover",
        function (e) {
          e = e || event;
          e.preventDefault();
        },
        false
      );
      map.addEventListener("drop", store.doMapDropDataFile, false);
    },

  reactshouldAddListeners: (state) => {
    if (state.addData.shouldAddListeners)
      return { actionCreator: "doAddMapDragDropListeners" };
  },
};
