/* COPYRIGHT Esri - https://js.arcgis.com/1.2/LICENSE.txt */
import * as unionOperator from "@arcgis/core/geometry/operators/unionOperator";
import * as projectOperator from "@arcgis/core/geometry/operators/projectOperator";
import * as webMercatorUtils from "@arcgis/core/geometry/support/webMercatorUtils";
async function queryObjectIds(geometries, layer) {
  let ids = [];
  const queryDefs = geometries ? geometries.map((g) => _intersectQuery(g, layer)) : [Promise.resolve()];
  const results = await Promise.all(queryDefs);
  results.forEach((resultIds) => {
    ids = [...ids, ...resultIds || []];
  });
  return ids;
}
async function queryFeaturesByID(ids, layer, graphics, returnGeometry, outSpatialReference, fields) {
  const num = layer.capabilities?.query.maxRecordCount || 1e3;
  const start = 0;
  if (ids.length === 0) {
    ids = await layer.queryObjectIds();
  }
  const q = layer.createQuery();
  q.returnGeometry = returnGeometry;
  q.objectIds = ids.slice(start, num);
  if (outSpatialReference) {
    q.outSpatialReference = outSpatialReference;
  }
  if (fields) {
    const layerFields = layer.fields.map((f) => f.name.toLowerCase());
    q.outFields = fields.filter((f) => layerFields.indexOf(f.toLowerCase()) > -1);
  }
  const result = await layer.queryFeatures(q);
  graphics = graphics.concat(result.features);
  const remainingIds = ids.slice(num, ids.length);
  return remainingIds.length > 0 ? queryFeaturesByID(remainingIds, layer, graphics, returnGeometry, outSpatialReference, fields) : Promise.resolve(graphics);
}
async function queryFeaturesByGlobalID(globalIds, layer) {
  const globalIdField = layer.globalIdField;
  if (!globalIdField) {
    return [];
  }
  const q = layer.createQuery();
  q.returnGeometry = false;
  q.outFields = [layer.objectIdField];
  q.where = globalIds.map((g) => `${globalIdField} = '${g}'`).join(" or ");
  const result = await layer.queryFeatures(q);
  return result.features;
}
async function queryFeaturesByGeometry(start, layer, geometry, featuresCollection) {
  const num = layer.capabilities?.query.maxRecordCount || 1e3;
  const query = layer.createQuery();
  query.start = start;
  query.num = num;
  query.geometry = geometry;
  const result = await layer.queryFeatures(query);
  featuresCollection[layer.id] = featuresCollection[layer.id].concat(result.features);
  return result.exceededTransferLimit ? queryFeaturesByGeometry(start += num, layer, geometry, featuresCollection) : Promise.resolve(featuresCollection);
}
async function queryExtent(ids, layer) {
  const query = layer.createQuery();
  query.objectIds = ids;
  return layer.queryExtent(query);
}
function getQueryGeoms(geometries) {
  const unionGeoms = [];
  const unionPolygon = _unionGeoms(geometries, "polygon");
  if (unionPolygon) {
    unionGeoms.push(unionPolygon);
  }
  const unionPolyline = _unionGeoms(geometries, "polyline");
  if (unionPolyline) {
    unionGeoms.push(unionPolyline);
  }
  const unionPoint = _unionGeoms(geometries, "point");
  if (unionPoint) {
    unionGeoms.push(unionPoint);
  }
  return unionGeoms;
}
function _unionGeoms(geometries, type) {
  const geoms = (geometries || []).filter((g) => g.type === type);
  return geoms.length <= 1 ? geoms[0] : unionOperator.executeMany(geoms);
}
async function _intersectQuery(geometry, layer) {
  const q = layer.createQuery();
  q.spatialRelationship = "intersects";
  q.geometry = geometry;
  return layer.queryObjectIds(q);
}
async function projectToSpatialReference(inputGeometry, targetSR) {
  if (!targetSR) {
    console.error("Target spatial reference is undefined");
    return inputGeometry;
  }
  if (!inputGeometry.spatialReference) {
    console.error("Input geometry does not have a spatial reference");
    return inputGeometry;
  }
  if (inputGeometry.spatialReference.equals(targetSR)) {
    return inputGeometry;
  }
  if (targetSR.isWGS84 || targetSR.wkid === 4326) {
    return inputGeometry;
  }
  if (inputGeometry.spatialReference.isWGS84 || inputGeometry.spatialReference.wkid === 4326) {
    const projectedGeometry2 = webMercatorUtils.project(inputGeometry, targetSR);
    return projectedGeometry2;
  }
  await projectOperator.load();
  const projectedGeometry = projectOperator.execute(inputGeometry, targetSR);
  return projectedGeometry;
}
export {
  queryFeaturesByID as a,
  queryFeaturesByGlobalID as b,
  queryObjectIds as c,
  queryFeaturesByGeometry as d,
  getQueryGeoms as g,
  projectToSpatialReference as p,
  queryExtent as q
};
