import buffer from "@turf/buffer";
import { point } from "@turf/helpers";
import { polygon } from "@turf/helpers";
import disjoint from "@turf/boolean-disjoint";
import bbox from "@turf/bbox";
import GeoJSON from "ol/format/GeoJSON";
import { transformExtent } from "ol/proj";
import { formatArcgisVector } from "../../openlayers-utils/format-utilities";

const geoJSON = new GeoJSON();

export default {
  name: "vectorIdent",

  getReducer() {
    const initialData = {
      shouldRegister: true,
    };

    return (state = initialData, { type, payload }) => {
      switch (type) {
        case "VECTOR_IDENT_REGISTERED":
          return Object.assign({}, state, payload);
        default:
          return state;
      }
    };
  },

  doVectorIdentRegister:
    () =>
    ({ dispatch, store }) => {
      dispatch({
        type: "VECTOR_IDENT_REGISTERED",
        payload: { shouldRegister: false },
      });
      store.doIdentifyAddCollection({
        onIdentify: store.doVectorIdentFire,
      });
    },

  doVectorIdentFire:
    (callback) =>
    ({ dispatch, store }) => {
      const layers = store.selectVisibleLayers();
      const coords = store.selectIdentifyCoordinates();
      const resolution = store.selectResolution();
      let identifyFeature = {};
      const out = [];

      if (typeof coords[0] === "number") {
        const pt = point(coords);
        const radius = (resolution * 5) / 1000;
        identifyFeature = buffer(pt, radius, {
          units: "kilometers",
        });
      } else {
        identifyFeature = polygon(coords);
      }

      const identifyExtent = transformExtent(
        bbox(identifyFeature),
        "EPSG:4326",
        "EPSG:3857"
      );

      layers.forEach((lyr) => {
        if (lyr.identifyType === "arcgisvector") {
          const { mapLayer } = lyr;
          const outFeatures = [];
          const src = mapLayer.getSource();
          src.forEachFeatureIntersectingExtent(identifyExtent, (f) => {
            const geoJsonFeature = geoJSON.writeFeatureObject(f, {
              featureProjection: "EPSG:3857",
              dataProjection: "EPSG:4326",
            });
            if (!disjoint(identifyFeature, geoJsonFeature))
              outFeatures.push(geoJsonFeature);
          });
           //Column Filtering
           if (layers[0].identifyFields) {
            outFeatures.forEach((feature) => {
              if(feature.properties){
                for (const [key, value] of Object.entries(feature.properties)) {
                        let reducedProperties = {};
                        layers[0].identifyFields.forEach((property) => {
                          if (feature.properties[property]) {
                            reducedProperties[property] =
                            feature.properties[property];
                          }
                        });
                        feature.properties = reducedProperties; 
                 }
              }
            })
          }
          //Column Renaming
            if (layers[0].identifyRenameColums) {
              outFeatures.forEach((feature) => {
                if(feature.properties){
                  for (const [featureKey, featureValue] of Object.entries(feature.properties)) {
                    for (const [key, value] of Object.entries(layers[0].identifyRenameColums)){
                      if (featureKey === key) {
                        feature.properties[value] = feature.properties[featureKey];
                        delete feature.properties[featureKey];
                      }
                    }
                  }
                }
              })
            }
          out.push({
            dataset: lyr.uid,
            layerName: lyr.displayName,
            err: null,
            result: {
              [lyr.uid]: {
                type: "FeatureCollection",
                features: formatArcgisVector(outFeatures),
              },
            },
          });
        }
      });
      return callback(null, out);
    },

  reactVectorIdentShouldRegister: (state) => {
    if (state.vectorIdent.shouldRegister)
      return { actionCreator: "doVectorIdentRegister" };
  },
};
