import async from "async";
import { formatArcgisrest} from "../../openlayers-utils/format-utilities";

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 coords = store.selectIdentifyCoordinates();
      const visibleLayers = store.selectVisibleLayers();
      let featureType = "Point";

      if (!visibleLayers.length) return callback(null, []);

      //http://resources.esri.com/help/9.3/arcgisserver/apis/rest/identify.html
      const params = {
        sr: 4326,
        tolerance: 2,
        returnGeometry: true,
        mapExtent: store.selectMapExtent(),
        imageDisplay: store.selectMapImageDisplay(),
        f: "json",
      };

      if (typeof coords[0] === "number") {
        params.geometry = coords.join(",");
        params.geometryType = "esriGeometryPoint";
      } else {
        params.geometryType = "esriGeometryPolygon";
        featureType = "Polygon";
        params.geometry = encodeURIComponent(
          JSON.stringify({
            spatialReference: { wkid: 4326 },
            rings: [coords[0]],
          })
        );
      }

      const queries = [];

      visibleLayers.forEach((visibleLayer) => {
        if (visibleLayer.identifyType === "arcgisrest") {
          const src = visibleLayer.mapLayer.getSource();
          const root = !!src.getUrl ? src.getUrl() : src.getUrls()[0];
          const layerList = visibleLayer.layerList;
          params["layers"] = `all:${layerList}`;
          const p = Object.assign({}, params, { root: root });

          const url = formatUrl(p);
          queries.push((cb) => {
            anonGet(url, (err, response, body) => {
              if (err || response.statusCode !== 200) {
                cb(`Error for ${visibleLayer.displayName}`);
              } else {
                try {
                   const data = JSON.parse(body);
                  //Column Filtering
                  if (visibleLayer.identifyFields) { 
                    data.results.forEach((result) => {
                      if(result.attributes){
                        for (const [key, value] of Object.entries(result.attributes)) {
                            let reducedProperties = {};
                            visibleLayer.identifyFields.forEach((property) => {
                                if (result.attributes[property]) {
                                  reducedProperties[property] =
                                  result.attributes[property];
                                }
                              });
                              result.attributes = reducedProperties;
                       }
                    }
                  })
                }
              // Column Renaming
                if (visibleLayer.identifyRenameColums) {
                  data.results.forEach((result) => {
                  if(result.attributes){
                    for (const [featureKey, featureValue] of Object.entries(result.attributes)) {
                            for (const [key, value] of Object.entries(visibleLayer.identifyRenameColums)){
                              if (featureKey === key) {
                                result.attributes[value] = result.attributes[featureKey];
                                delete result.attributes[featureKey];
                              }
                          }
                     }
                  }
                })
              } 
                cb(null, {
                    dataset: visibleLayer.uid,
                    layerName: visibleLayer.displayName,
                    err: null,
                    result: {
                      [visibleLayer.uid]: {
                        type: "FeatureCollection",
                        features: data.results.map((feat) => {
                          return {
                            type: "Feature",
                            geometry: {
                              type: featureType,
                              coordinates: coords,
                            },
                            properties: formatArcgisrest(feat.attributes),
                          };
                        }),
                      },
                    },
                  });
                } catch (err) {
                  
                  cb(`Error for ${visibleLayer.displayName}`,err);
                }
              }
            });
          });
        }
      });

      async.parallel(queries, (err, results) => {
        callback(err, results);
      });
    },

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