import async from "async";
import EsriJSON from "ol/format/EsriJSON";
import { formatArcgisrest } from "../../../openlayers-utils/format-utilities";
const esrijsonFormat = new EsriJSON();

function formatUrl(options) {
  let url = `${options.root}/identify?`;
  const params = [];
  for (var key in options) {
    if (key !== "root") params.push(key + "=" + options[key].toString());
  }
  url += params.join("&");
  return url;
}

export default {
  name: "arcGisRestIdent",

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

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

  doArcGisRestIdentRegister:
    () =>
    ({ dispatch, store }) => {
      dispatch({
        type: "ARCGIS_IDENT_REGISTERED",
        payload: { shouldRegister: false },
      });
      store.doIdentifyAddCollection({
        onIdentify: store.doArcGisRestIdentFire,
      });
    },

  doArcGisRestIdentFire:
    (callback) =>
    ({ store, anonGet }) => {
      const visibleLayers = store.selectVisibleLayers();
      if (!visibleLayers.length) return callback(null, []);

      const queries = [];
      const featureType = "Polygon";
      const identifyFeature = store.doSetIdentifyFeature();

      //https://developers.arcgis.com/rest/services-reference/enterprise/identify-map-service-.htm
      const params = {
        sr: 4326,
        tolerance: 2,
        returnGeometry: true,
        mapExtent: store.selectMapExtent(),
        imageDisplay: store.selectMapImageDisplay(),
        f: "json",
        geometryType: "esriGeometryPolygon",
        geometry: encodeURIComponent(
          JSON.stringify({
            spatialReference: { wkid: 4326 },
            rings: [identifyFeature.geometry.coordinates[0]],
          })
        ),
      };

      visibleLayers.forEach((visibleLayer) => {
        if (
          visibleLayer.identifyType &&
          visibleLayer.identifyType === "arcgisrest"
        ) {
          const layerList = visibleLayer.layerList;
          params["layers"] = `all:${layerList}`;
          const p = Object.assign({}, params, { root: visibleLayer.url });
          const url = formatUrl(p);

          queries.push((cb) => {
            anonGet(url, (err, response, body) => {
              if (err || response.statusCode !== 200) {
                cb(null, {
                  dataset: visibleLayer.uid,
                  layerName: visibleLayer.displayName,
                  err: `Error for ${visibleLayer.displayName}`,
                  result: { [visibleLayer.uid]: {} },
                });
              } else {
                try {
                  const data = JSON.parse(body);

                  if (data.results.length) {
                    cb(null, {
                      dataset: visibleLayer.uid,
                      layerName: visibleLayer.displayName,
                      err: null,
                      result: {
                        [visibleLayer.uid]: {
                          type: "FeatureCollection",
                          features: data.results.map((feat) => {
                            const esriFeat = esrijsonFormat.readFeature(feat, {
                              featureProjection: "EPSG:3857",
                            });
                            const featGeometry = esriFeat.getGeometry();

                            return {
                              type: "Feature",
                              geometry: {
                                type: featGeometry.getType(),
                                coordinates: featGeometry.getCoordinates(),
                              },
                              properties: formatArcgisrest(feat.attributes),
                            };
                          }),
                        },
                      },
                    });
                  } else {
                    cb(null, {
                      dataset: visibleLayer.uid,
                      layerName: visibleLayer.displayName,
                      err: null,
                      result: { [visibleLayer.uid]: {} },
                    });
                  }
                } catch (err) {
                  console.log(err);
                  cb(null, {
                    dataset: visibleLayer.uid,
                    layerName: visibleLayer.displayName,
                    err: `Error for ${visibleLayer.displayName}`,
                    result: { [visibleLayer.uid]: {} },
                  });
                }
              }
            });
          });
        }
      });
      //https://caolan.github.io/async/v3/docs.html#parallel
      async.parallel(queries, (err, results) => {
        callback(err, results);
      });
    },

  reactArcGisRestIdentShouldRegister: (state) => {
    if (state.arcGisRestIdent.shouldRegister)
      return { actionCreator: "doArcGisRestIdentRegister" };
  },
};
