import proj4 from 'proj4';
import Bubble from '../../utils/popup/popup';
import { getDpi } from '../../utils/CommonUtils';
import { removeDivByClass } from '../../utils/ElementUtils';
import { intersect as Intersect, area as Area, length as Length, polygon, multiPolygon, lineString, multiLineString } from '@turf/turf';
import * as OpenLayersManager from './OpenLayersManager';
import { ImageSuperMapRest, TileSuperMapRest, Tianditu, FieldService, GetFeaturesByIDsParameters, GetFeaturesBySQLParameters, GetFeaturesByBoundsParameters, GetFeaturesByGeometryParameters, GetFeaturesByBufferParameters, GetGridCellInfosParameters, FieldParameters, FieldStatisticsParameters, FeatureService, QueryService, GridCellInfosService, SpatialAnalystService, DatasetOverlayAnalystParameters, GeometryBufferAnalystParameters, BufferSetting, BufferDistance, BufferEndType, QueryByDistanceParameters, QueryByGeometryParameters, QueryByBoundsParameters, QueryBySQLParameters, FilterParameter, SpatialQueryMode, LayerInfoService } from '@supermap/iclient-ol';
// 导入openlayers相关模块
import { Map as OlMap, View, Feature, CircleStyle, Fill, Style, Stroke, TileLayer, VectorLayer, Geometry, Point, LineString, Polygon, MultiPolygon, Circle, GeoJSON, VectorSource, TileWMS, WMTS, fromCircle, ImageLayer, Draw, defaultInteraction, createBox, getLength, getArea, Overlay, getCenter, TileGrid, WMTSTileGrid, ScaleLine, OverviewMap, MousePosition, defaultControls, unByKey, createStringXY } from './OpenLayersAPI';
import { getProjection } from '../../utils/Projection';
let mapConfig = {};
/**
 * @function OpenLayersUtils.setMapConfig
 * @description 设置地图配置
 * @param {object} config - 地图配置
 */
const setMapConfig = (config) => {
    mapConfig = config;
};
/**
 * @function OpenLayersUtils.createMap
 * @description 创建Map对象
 * @param {OpenLayersMapOptions} options - 地图参数
 * @return  map - 地图对象
 */
const createMap = (options) => {
    // 创建地图
    const map = new OlMap({
        view: new View({
            center: [0, 0],
            projection: getProjection(mapConfig.epsgCode),
            zoom: 1
        }),
        interactions: defaultInteraction({ doubleClickZoom: false }),
        controls: defaultControls({
            zoom: false,
            rotate: false,
            attribution: false
        }).extend([
            new ScaleLine(),
            new MousePosition({
                coordinateFormat: createStringXY(4) // 将坐标保留4位小数位，并转换为字符串
            })
        ]),
        ...options
    });
    // 如果没有自定义view,设置初始化范围
    if (!options.view && mapConfig.extent2D) {
        const { extent2D } = mapConfig;
        const { xMin, yMin, xMax, yMax, zoom } = extent2D;
        map.getView().fit([xMin, yMin, xMax, yMax], { maxZoom: zoom });
    }
    // 存储地图对象
    const id = typeof options.target === 'string' ? options.target : options.target.id;
    OpenLayersManager.addMap(map, id);
    return map;
};
/**
 * @function OpenLayersUtils.fullExtent
 * @description 全图
 * @param {OpenLayersMapType} map - 地图对象
 */
const fullExtent = (map) => {
    if (map) {
        const { xMin, yMin, xMax, yMax } = mapConfig.extent2D;
        let fitOption = {};
        mapConfig.zoom && (fitOption = { zoom: mapConfig.zoom });
        map.getView().fit([xMin, yMin, xMax, yMax], fitOption);
    }
};
/**
 * @function OpenLayersUtils.zoomIn
 * @description 放大地图
 * @param {OpenLayersMapType} map - 地图对象
 */
const zoomIn = (map) => {
    const view = map.getView();
    const zoom = view.getZoom();
    if (zoom && zoom <= view.getMaxZoom() - 1) {
        view.animate({ zoom: zoom + 1, duration: 250 });
    }
};
/**
 * @function OpenLayersUtils.zoomOut
 * @description 缩小地图
 * @param {OpenLayersMapType} map - 地图对象
 */
const zoomOut = (map) => {
    const view = map.getView();
    const zoom = view.getZoom() || 0;
    if (zoom && zoom >= view.getMinZoom() + 1) {
        view.animate({ zoom: zoom - 1, duration: 250 });
    }
};
/**
 * @function OpenLayersUtils.moveTo
 * @description 地图平移至目标位置
 * @param {OpenLayersMapType} map - 地图对象
 * @param {[number,number]} lnglat - 目标位置：坐标经纬度
 */
const moveTo = (map, lnglat) => {
    const view = map.getView();
    view.setCenter(lnglat);
};
/**
 * @function OpenLayersUtils.moveBy
 * @description 地图平移至目标位置
 * @param {OpenLayersMapType} map - 地图对象
 * @param {number[]} offset - 平移地图的偏移量[x,y],x方向横向平移距离(向右为正),y方向纵向平移距离(向下为正)
 */
const moveBy = (map, offset) => {
    const mapCenter = map.getView().getCenter() || []; // 获取当前地图中心点（投影坐标）
    const centerPix = map.getPixelFromCoordinate(mapCenter); // 投影坐标转为像素坐标
    const [x, y] = offset;
    const pixelX = centerPix[0] + x; // 平移横坐标
    const pixelY = centerPix[1] + y; // 平移纵坐标
    map.getView().animate({
        center: map.getCoordinateFromPixel([pixelX, pixelY]),
        duration: 1000,
        zoom: map.getView().getZoom() // 定义比例尺
    });
};
let overviewMapControl;
/**
 * @function OpenLayersUtils.addMiniMap
 * @description 添加鹰眼图
 * @param {OpenLayersMapType} map - 地图对象
 * @param {any} options - 鹰眼图层配置
 */
const addMiniMap = (map, options) => {
    const layers = [];
    if (options) {
        if (Array.isArray(options)) {
            options.forEach((item) => {
                layers.push(createLayer(item));
            });
        }
        else {
            layers.push(createLayer(options));
        }
    }
    // 添加鹰眼控件
    if (!overviewMapControl) {
        overviewMapControl = new OverviewMap({
            className: 'ol-overviewmap openLayers-minimap',
            collapsible: false,
            layers
        });
    }
    map.addControl(overviewMapControl);
};
/**
 * @function OpenLayersUtils.removeMiniMap
 * @description 移除鹰眼图
 * @param {OpenLayersMapType} map - 地图对象
 */
const removeMiniMap = (map) => {
    map.removeControl(overviewMapControl);
};
// 定义测量变量
const measureSourceMap = new Map();
let measureTooltipElement;
let measureTooltip;
// 初始化测量工具
const initMeasureDraw = (map) => {
    if (!map) {
        return null;
    }
    // 绘制图层
    const measureSource = new VectorSource({ wrapX: false });
    const drawLayer = new VectorLayer({
        style: measureFinishStyle,
        source: measureSource
    });
    map.addLayer(drawLayer);
    measureSourceMap.set(map.uid, measureSource);
};
// 创建一个新的测量提示
const createMeasureTooltip = (map) => {
    // 如果已经存在帮助提示框则移除
    if (measureTooltipElement) {
        measureTooltipElement.parentNode.removeChild(measureTooltipElement);
    }
    // 创建帮助提示要素的div
    measureTooltipElement = document.createElement('div');
    // 设置帮助提示要素的样式
    measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure';
    // 创建一个覆盖标注
    measureTooltip = new Overlay({
        element: measureTooltipElement,
        offset: [0, -15],
        positioning: 'bottom-center'
    });
    // 将覆盖标注添加到地图中
    map.addOverlay(measureTooltip);
};
// 计算长度/面积
const formatMeasure = (geometry) => {
    // 输出线段长度/图形面积
    let output;
    // 提示框的锚点坐标
    let tooltipCoord;
    if (geometry instanceof LineString) {
        // 计算平面距离
        const length = getLength(geometry, {
            projection: getProjection(mapConfig.epsgCode)
        });
        // 定义输出变量
        // 如果长度大于1000，则使用km单位，否则使用m单位
        if (length > 1000) {
            output = `长度：${Math.round((length / 1000) * 100) / 100} km`;
        }
        else {
            output = `长度：${Math.round(length * 100) / 100} m`;
        }
        tooltipCoord = geometry.getLastCoordinate();
    }
    else if (geometry instanceof Polygon) {
        // 计算平面距离
        const area = getArea(geometry, {
            projection: getProjection(mapConfig.epsgCode)
        });
        // 定义输出变量
        // 如果面积大于10000，则使用km²单位，否则使用m²单位
        if (area > 10000) {
            output = `面积：${Math.round((area / 1000000) * 100) / 100} km<sup>2</sup>`;
        }
        else {
            output = `面积：${Math.round(area * 100) / 100} m<sup>2</sup>`;
        }
        tooltipCoord = getCenter(geometry.getExtent());
    }
    return { output, tooltipCoord };
};
// 测量时草图样式
const measureStyle = new Style({
    fill: new Fill({
        color: 'rgba(1, 210, 241, 0.1)'
    }),
    stroke: new Stroke({
        color: 'yellow',
        width: 4
    })
});
// 测量结束图层样式
const measureFinishStyle = new Style({
    fill: new Fill({
        color: 'rgba(219, 241, 234, 0.2)'
    }),
    stroke: new Stroke({
        color: '#07f944',
        width: 4
    })
});
/**
 * @function OpenLayersUtils.startMeasure
 * @description 测量工具
 * @param {OpenLayersMapType} map - 地图对象
 * @param {string} type - 测量类型
 */
const startMeasure = (map, type) => {
    if (!measureSourceMap.has(map.uid)) {
        initMeasureDraw(map);
    }
    const measureSource = measureSourceMap.get(map.uid);
    measureSource?.clear();
    stopDraw(map); // 防止与手动绘制事件冲突
    createMeasureTooltip(map);
    // 勾绘矢量图形的类
    const draw = new Draw({
        style: measureStyle,
        // source代表勾绘的要素属于的数据集
        source: measureSource,
        // type 表示勾绘的要素包含的 geometry 类型
        type
    });
    map.getTargetElement().style.cursor = 'crosshair';
    // 绘制开始时触发的事件
    draw.on('drawstart', function (evt) {
        const sketch = evt.feature;
        // 定义一个事件监听，监听几何要素的change事件
        sketch.getGeometry().on('change', function (evt) {
            // 获取绘制的几何对象
            const geom = evt.target;
            const { output, tooltipCoord } = formatMeasure(geom);
            // 设置测量提示框的内标签为最终输出结果
            measureTooltipElement.innerHTML = output;
            measureTooltipElement.className =
                'ol-tooltip ol-tooltip-static draw_label';
            // 设置测量提示框的位置坐标
            measureTooltip.setPosition(tooltipCoord);
        });
    });
    // 绘制结束时触发的事件
    draw.on('drawend', function (e) {
        // 输出坐标信息
        const geometry = e.feature.getGeometry();
        const pointArr = geometry.getCoordinates();
        console.log('测量坐标：', pointArr);
        // 移除交互
        map.removeInteraction(draw);
        map.getTargetElement().style.cursor = 'default';
    });
    // 添加交互
    map.addInteraction(draw);
};
/**
 * @function OpenLayersUtils.clearMeasure
 * @description 清除测量工具
 */
const clearMeasure = () => {
    measureSourceMap.forEach((source) => {
        source?.clear();
    });
    if (measureTooltipElement && measureTooltipElement.parentNode) {
        measureTooltipElement.parentNode.removeChild(measureTooltipElement);
        measureTooltipElement = null;
    }
};
let coordMarkerLayer;
let coordSource;
let coordSingleClickFunc;
/**
 * @function OpenLayersUtils.startCoordPick
 * @description 坐标拾取
 * @param {OpenLayersMapType} map - 地图对象
 */
const startCoordPick = (map) => {
    let coordFeature;
    let BubbleDiv;
    let overlay;
    if (!coordMarkerLayer) {
        // 在地图上添加Mark
        coordMarkerLayer = new VectorLayer({
            zIndex: 99
        });
        coordSource = new VectorSource(); // 创建矢量图
        coordMarkerLayer.setSource(coordSource); // 设置图源
        const style = new Style({
            image: new CircleStyle({
                radius: 7,
                fill: new Fill({
                    color: '#ff0000'
                }),
                stroke: new Stroke({
                    color: '0000',
                    width: 1
                })
            })
        });
        coordMarkerLayer.setStyle(style); // 设置地图元素样式
        map.addLayer(coordMarkerLayer);
        BubbleDiv = new Bubble();
        overlay = new Overlay({
            offset: [10, 10]
        });
        map.addOverlay(overlay);
        coordSingleClickFunc = (evt) => {
            coordFeature && coordSource.removeFeature(coordFeature);
            coordFeature = new Feature({
                geometry: new Point(evt.coordinate)
            });
            coordSource.addFeature(coordFeature);
            BubbleDiv.create({
                lng: evt.coordinate[0] || 0,
                lat: evt.coordinate[1] || 0,
                type: 0 // openlayers
            });
            overlay.setElement(BubbleDiv.childNode);
            overlay.setPosition(evt.coordinate);
        };
    }
    // 单击获取地图坐标
    coordSingleClickFunc && map.un('singleclick', coordSingleClickFunc);
    coordSingleClickFunc && map.on('singleclick', coordSingleClickFunc);
};
/**
 * @function OpenLayersUtils.stopCoordPick
 * @description 清除坐标拾取
 * @param {OpenLayersMapType} map - 地图对象
 */
const stopCoordPick = (map) => {
    if (!map)
        return;
    coordSingleClickFunc && map.un('singleclick', coordSingleClickFunc);
    if (coordMarkerLayer) {
        map.removeLayer(coordMarkerLayer);
        coordMarkerLayer = null;
        coordSource = null;
    }
    removeDivByClass('popup-box');
};
const commonParams = { crossOrigin: 'anonymous' }; // 截图需要设置crossOrigin参数
const createWMSLayer = (layerOption) => {
    const layer = new TileLayer({
        source: new TileWMS({
            ...commonParams,
            url: layerOption.url,
            params: {
                FORMAT: layerOption.format || 'image/png',
                LAYERS: layerOption.layerName,
                STYLES: layerOption.style,
                VERSION: '1.1.1' // 1.3.0图层加不上
            }
        })
    });
    return layer;
};
const createWMTSLayer = (layerOption) => {
    const layer = new TileLayer({
        source: new WMTS({
            ...commonParams,
            url: layerOption.url,
            layer: layerOption.layerName,
            format: 'tiles',
            style: layerOption.style || 'default',
            wrapX: true,
            matrixSet: layerOption.matrixSet,
            tileGrid: getOLWMTSTileGrid(getProjection(mapConfig.epsgCode))
        })
    });
    return layer;
};
const createTDTLayer = (layerOption) => {
    const layer = new TileLayer({
        source: new Tianditu({
            ...commonParams,
            ...getTdtLayerParamsByType(layerOption.layerName),
            key: layerOption.token || mapConfig.tdtToken
        })
    });
    return layer;
};
const createTileSuperMapRestLayer = (layerOption) => {
    const layer = new TileLayer({
        source: new TileSuperMapRest({
            ...commonParams,
            prjCoordSys: layerOption.prjCoordSys,
            url: layerOption.url,
            tileGrid: getOLTileGrid(getProjection(mapConfig.epsgCode))
        })
    });
    return layer;
};
const getOLTileGrid = (projection) => {
    const extent = projection.getExtent();
    if (!extent?.length)
        return null;
    const tileGrid = new TileGrid({
        origin: [extent[0], extent[3]],
        resolutions: getResolutions(extent)
    });
    return tileGrid;
};
const getOLWMTSTileGrid = (projection) => {
    const extent = projection.getExtent();
    const tileGrid = new WMTSTileGrid({
        origin: [extent[0], extent[3]],
        resolutions: getResolutions(extent),
        matrixIds: getLevels()
    });
    return tileGrid;
};
const getResolutions = (extent) => {
    if (extent.length) {
        const resolutions = [];
        let temp = Math.abs(extent[0] - extent[2]) / 512;
        resolutions[0] = temp;
        for (let i = 1; i < 22; i++) {
            temp = temp / 2;
            resolutions[i] = temp;
        }
        return resolutions;
    }
    return [];
};
const getLevels = () => {
    const levels = [...new Array(23).keys()].map((el) => {
        return el + 1 + '';
    });
    return levels;
};
const createImageSuperMapRestLayer = (layerOption) => {
    const layer = new ImageLayer({
        source: new ImageSuperMapRest({
            ...commonParams,
            prjCoordSys: layerOption.prjCoordSys,
            url: layerOption.url
        })
    });
    return layer;
};
const createLayer = (layerOption) => {
    const { type } = layerOption;
    let layer;
    switch (type) {
        case 'WMS':
            layer = createWMSLayer(layerOption);
            break;
        case 'WMTS':
            layer = createWMTSLayer(layerOption);
            break;
        case 'TDT':
            layer = createTDTLayer(layerOption);
            break;
        case 'TileSuperMap':
            layer = createTileSuperMapRestLayer(layerOption);
            break;
        case 'ImageSuperMapRest':
            layer = createImageSuperMapRestLayer(layerOption);
            break;
    }
    return layer;
};
/**
 * @function addLayerFunc
 * @description 添加/创建地图图层方法
 * @param {OpenLayersMapType} map - 地图对象
 * @param {string} option - 图层参数  1、id:服务图层id  2、type:服务类型  3、其他参数
 */
const addLayerFunc = (map, layerOption) => {
    const { id } = layerOption;
    let layer = OpenLayersManager.getLayer(`${map.uid}-${id}`);
    if (layer?.getVisible && !layer?.getVisible()) {
        layer.setVisible(true);
    }
    if (layer) {
        const layerList = map.getLayers().getArray();
        if (layerList?.length && layerList.some((i) => i === layer)) {
            layer.setVisible(true);
            return layer;
        }
        map.addLayer(layer);
        return layer;
    }
    layer = createLayer(layerOption);
    if (layer) {
        map.addLayer(layer);
        OpenLayersManager.setLayer(`${map.uid}-${id}`, layer);
    }
    return layer;
};
/**
 * @function OpenLayersUtils.addLayer
 * @description 添加地图服务
 * @param {OpenLayersMapType} map - 地图对象
 * @param {string} option - 图层参数  1、id:服务图层id  2、type:服务类型  3、其他参数
 */
const addLayer = (map, option) => {
    return new Promise((resolve) => {
        if (Array.isArray(option)) {
            const layers = [];
            option.forEach((item) => {
                const layer = addLayerFunc(map, item);
                layers.push(layer);
            });
            resolve(layers);
        }
        else {
            const layer = addLayerFunc(map, option);
            resolve(layer);
        }
    });
};
// 根据类型获取天地图参数
const getTdtLayerParamsByType = (type) => {
    let params;
    switch (type) {
        case 'img':
            params = {
                layerType: 'img'
            };
            break;
        case 'img_label':
            params = {
                layerType: 'img',
                isLabel: true
            };
            break;
        case 'vec':
            params = {
                layerType: 'vec'
            };
            break;
        case 'vec_label':
            params = {
                layerType: 'vec',
                isLabel: true
            };
            break;
        case 'ter':
            params = {
                layerType: 'ter'
            };
            break;
        case 'ter_label':
            params = {
                layerType: 'ter',
                isLabel: true
            };
            break;
    }
    return params;
};
/**
 * @function OpenLayersUtils.removeLayer
 * @description 移除地图服务
 * @param {OpenLayersMapType} map - 地图对象
 * @param {LayerOption} option - 服务参数
 */
const removeLayer = (map, option) => {
    function removeLayerFunc({ id }) {
        const layer = OpenLayersManager.getLayer(`${map.uid}-${id}`);
        if (layer) {
            map.removeLayer(layer);
        }
    }
    if (Array.isArray(option)) {
        option.forEach((item) => {
            removeLayerFunc(item);
        });
    }
    else {
        removeLayerFunc(option);
    }
};
/**
 * @function OpenLayersUtils.pickAttribute
 * @description 属性拾取
 * @param {OpenLayersMapType} map - 地图对象
 * @param {string} url - 地图服务地址
 * @param {'Point' | 'Polyline' | 'Polygon'} type - 拾取图形类型
 * @param {FilterParameter[]} queryParams - 查询过滤条件参数数组
 */
const pickAttribute = (map, url, type, queryParams) => {
    return new Promise((resolve) => {
        draw(map, type, { continueDraw: true }, (geometry) => {
            const params = {
                url,
                type: 'Geometry',
                data: {
                    queryParams,
                    geometry
                }
            };
            map.getTargetElement().style.cursor = 'progress';
            queryMapService(params)
                .then((result) => {
                resolve(result);
            })
                .finally(() => {
                map.getTargetElement().style.cursor = 'default';
            });
        });
    });
};
/**
 * @function OpenLayersUtils.queryMapService
 * @description 地图服务查询
 * @param {OpenLayersQueryOption} option - 查询参数对象 1、url:图层地址 2、type：查询类型  3、查询参数
 */
const queryMapService = ({ url, type, data }) => {
    return new Promise((resolve) => {
        let param;
        switch (type) {
            case 'Bounds':
                param = new QueryByBoundsParameters(data);
                new QueryService(url).queryByBounds(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const recordSets = serviceResult.result.recordsets;
                    resolve(recordSets);
                });
                break;
            case 'Distance':
                param = new QueryByDistanceParameters(data);
                new QueryService(url).queryByDistance(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const recordSets = serviceResult.result.recordsets;
                    resolve(recordSets);
                });
                break;
            case 'Geometry':
                param = new QueryByGeometryParameters(data);
                new QueryService(url).queryByGeometry(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const recordSets = serviceResult.result.recordsets;
                    resolve(recordSets);
                });
                break;
            case 'SQL':
                param = new QueryBySQLParameters(data);
                new QueryService(url).queryBySQL(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const recordSets = serviceResult.result.recordsets;
                    resolve(recordSets);
                });
                break;
        }
    });
};
/**
 * @function OpenLayersUtils.queryLayerData
 * @description 数据集查询
 * @param {OpenLayersQueryOption} option - 查询参数对象 1、url:图层地址 2、type：查询类型  3、查询参数
 */
const queryLayerData = ({ url, type, data }) => {
    return new Promise((resolve) => {
        let param;
        switch (type) {
            case 'ID':
                param = new GetFeaturesByIDsParameters(data);
                new FeatureService(url).getFeaturesByIDs(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const featuers = serviceResult.result.features;
                    resolve(featuers);
                });
                break;
            case 'SQL':
                param = new GetFeaturesBySQLParameters(data);
                new FeatureService(url).getFeaturesBySQL(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const featuers = serviceResult.result.features;
                    resolve(featuers);
                });
                break;
            case 'Bounds':
                param = new GetFeaturesByBoundsParameters(data);
                new FeatureService(url).getFeaturesByBounds(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const featuers = serviceResult.result.features;
                    resolve(featuers);
                });
                break;
            case 'Geometry':
                param = new GetFeaturesByGeometryParameters(data);
                new FeatureService(url).getFeaturesByGeometry(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const featuers = serviceResult.result.features;
                    resolve(featuers);
                });
                break;
            case 'Buffer':
                param = new GetFeaturesByBufferParameters(data);
                new FeatureService(url).getFeaturesByBuffer(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const featuers = serviceResult.result.features;
                    resolve(featuers);
                });
                break;
            case 'GridCellInfo':
                param = new GetGridCellInfosParameters(data);
                new GridCellInfosService(url).getGridCellInfos(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const result = serviceResult.result;
                    resolve(result);
                });
                break;
            case 'Fields':
                param = new FieldParameters(data);
                new FieldService(url).getFields(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const result = serviceResult.result;
                    resolve(result);
                });
                break;
            case 'FieldStatisticsInfo':
                param = new FieldStatisticsParameters(data);
                new FieldService(url).getFieldStatisticsInfo(param, function (serviceResult) {
                    if (!serviceResult.result) {
                        console.log('查询结果为空');
                        return;
                    }
                    const result = serviceResult.result;
                    resolve(result);
                });
                break;
        }
    });
};
/**
 * @function OpenLayersUtils.changeLayerOpacity
 * @description 调整图层透明度
 * @param {string} option - 服务参数  1、id:服务id
 * @param {number} opacity - 透明度 0~1
 */
const changeLayerOpacity = (map, option, opacity) => {
    if (!option)
        return;
    function setLayerOpacity({ id }) {
        const layer = OpenLayersManager.getLayer(`${map.uid}-${id}`);
        if (layer && layer.setOpacity) {
            layer.setOpacity(opacity);
        }
    }
    if (Array.isArray(option)) {
        option.forEach((data) => {
            setLayerOpacity(data);
        });
    }
    else {
        setLayerOpacity(option);
    }
};
/**
 * @function OpenLayersUtils.extractElementByClick
 * @description 点击拾取（查询）地图要素
 * @param {OpenLayersMapType} map 地图对象
 * @param {Array<OpenLayersQueryOption>} options 查询参数对象数组< 1、url:图层地址 2、type：查询类型  3、查询参数 >
 * @param {Style} paintStyle 图层样式
 */
const fill = new Fill({
    color: 'rgba(205, 201, 200, 0.8)'
});
const stroke = new Stroke({
    color: '#0066FF',
    width: 1.25
});
let queryOptions = [];
let queryResultStyle = null;
let extractEventHandler = null;
const extractElementByClick = (map, options, paintStyle) => {
    try {
        queryOptions = options;
        extractEventHandler = map.on('singleclick', handleQuery);
        map.getTargetElement().style.cursor = 'crosshair';
        if (paintStyle)
            queryResultStyle = paintStyle;
        else
            queryResultStyle = new Style({
                fill,
                stroke
            });
    }
    catch (error) {
        console.log('查询失败', error);
    }
};
/**
 * @description 点击事件的回调函数，根据回调参数进行几何查询
 */
function handleQuery(e) {
    try {
        unByKey(extractEventHandler);
        e.target.getTargetElement().style.cursor = 'progress';
        const queryList = [];
        let query = null;
        const point = e.target.getEventCoordinate(e.originalEvent);
        queryOptions.forEach((el) => {
            el.data = { ...el.data, ...{ geometry: new Point(point) } };
            query = queryLayerData({ url: el.url, type: 'Geometry', data: el.data });
            queryList.push(query);
        });
        Promise.all(queryList)
            .then((res) => {
            if (res[res.length - 1].features &&
                res[res.length - 1].features.length) {
                hightLight(e.target, res[res.length - 1], queryResultStyle);
            }
            else {
                console.log('查询数据为空！');
                e.target.removeLayer(hightLightLayer); // 查询为空清除现有高亮
                hightLightLayer = null;
            }
            e.target.getTargetElement().style.cursor = 'crosshair';
            extractEventHandler = e.target.on('singleclick', handleQuery);
        })
            .catch((err) => {
            extractEventHandler = e.target.on('singleclick', handleQuery);
            e.target.getTargetElement().style.cursor = 'crosshair';
            console.log('OpenLayersUtils-handleQuery-Promise-error', err);
        });
    }
    catch (error) {
        console.log('查询失败', error);
    }
}
let hightLightLayer = null;
/**
 * @function hightLight
 * @description 高亮查询结果
 * @param {OpenLayersMapType} map 地图对象
 * @param {any} features 高亮数据源
 * @param {Style} paintStyle 图层样式
 */
function hightLight(map, features, paintStyle) {
    try {
        if (!hightLightLayer) {
            hightLightLayer = new VectorLayer();
            map.addLayer(hightLightLayer);
        }
        const geo = new GeoJSON();
        const featureArray = geo.readFeatures(features);
        const vectorSource = new VectorSource({
            features: featureArray,
            wrapX: false
        });
        hightLightLayer.setSource(vectorSource);
        hightLightLayer.setStyle(paintStyle);
        const view = map.getView();
        const extent = featureArray[0]?.getGeometry()?.getExtent();
        view.fit(extent, {
            duration: 700
        });
    }
    catch (error) {
        console.log('OpenLayersUtils-hightLight-error', error);
    }
}
/**
 * @function OpenLayersUtils.removeElement
 * @description 清除点击监听事件和查询结果
 * @param {OpenLayersMapType} map - 地图对象
 */
const removeElement = (map) => {
    try {
        unByKey(extractEventHandler);
        map.getTargetElement().style.cursor = 'default';
        map.removeLayer(hightLightLayer); // 清除高亮图层
        hightLightLayer = null;
    }
    catch (error) {
        console.log('OpenLayersUtils-removeElement-error', error);
    }
};
let positionSource;
let positionLayer;
const style = new Style({
    image: new CircleStyle({
        fill: new Fill({
            color: '#e27728'
        }),
        stroke: new Stroke({
            color: '#ffffff',
            width: 2
        }),
        radius: 8
    }),
    fill: new Fill({
        color: '#e27728ba'
    }),
    stroke: new Stroke({
        color: '#ffffff',
        width: 2
    })
});
/**
 * @function OpenLayersUtils.setLocateCoordinate
 * @description 坐标定位
 * @param {OpenLayersMapType} map - 地图对象
 * @param {number[]} coordinate - 坐标数组
 * @param {'Point' | 'Polyline' | 'Polygon'} type - 类型
 */
const setLocateCoordinate = (map, coordinate, type) => {
    if (!map || !coordinate)
        return;
    if (!positionSource && !positionLayer) {
        positionSource = new VectorSource();
        positionLayer = new VectorLayer({
            source: positionSource,
            zIndex: 100
        });
        map.addLayer(positionLayer);
    }
    else {
        resetLocateCoordinate();
    }
    let geometry;
    let center;
    switch (type) {
        case 'Point':
            geometry = new Point(coordinate);
            center = coordinate;
            break;
        case 'Polyline':
            geometry = new LineString(coordinate);
            break;
        case 'Polygon':
            geometry = new Polygon(coordinate);
            break;
    }
    const feature = new Feature({ geometry });
    // 添加点的样式
    feature.setStyle(style);
    // 添加点的feature
    positionSource.addFeature(feature);
    const view = map.getView();
    if (center) {
        // 点类型使用setCenter去定位、避免层级放太大
        view.setCenter(center);
    }
    else {
        view.fit(geometry);
    }
};
/**
 * @function OpenLayersUtils.resetLocateCoordinate
 * @description 重置坐标定位
 */
const resetLocateCoordinate = () => {
    positionSource && positionSource.clear();
};
// 根据相机获取缩放层级
function getScaleByCamera(viewer, camera) {
    // dpi
    const frustum = camera.frustum;
    const { fovy } = frustum;
    const { pitch, position } = camera;
    const z = position.z;
    // 距离
    const distance = z / Math.sin(Math.abs(pitch));
    const angle = fovy / 2;
    const len = Math.tan(angle) * distance * 2;
    // dpi
    const dpi = getDpi();
    const container = viewer.container;
    const scale = len / ((container.clientHeight / dpi) * 0.0254);
    return scale;
}
// 笛卡尔转坐标
function projPoint(position) {
    const curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);
    // 弧度转经纬度
    const lat = Cesium.Math.toDegrees(curPosition.latitude);
    const lng = Cesium.Math.toDegrees(curPosition.longitude);
    const point = proj4('EPSG:4326', mapConfig.epsgCode || 'EPSG:3857', [
        lng,
        lat
    ]);
    return point;
}
// 获取视图中点
function getViewerCenter(viewer) {
    const result = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2));
    return result;
}
// 计算resolution
function getResolution(map, scale) {
    const dpi = getDpi();
    const proj = map.getView().getProjection();
    const mapUnitMeter = proj.getMetersPerUnit();
    const resolution = (0.0254 * scale) / mapUnitMeter / dpi;
    return resolution;
}
/**
 * @function OpenLayersUtils.syntaxView
 * @description 二维视图同步
 * @param {OpenLayersMapType} map - 二维地图对象
 * @param {CesiumMapType} viewer - 三维地图对象
 */
const syntaxView = (map, viewer) => {
    const camera = viewer.camera;
    const scale = getScaleByCamera(viewer, camera);
    const center = projPoint(getViewerCenter(viewer)); // 笛卡尔转坐标
    const view = map.getView();
    const resolution = getResolution(map, scale);
    view.setResolution(resolution);
    view.setCenter(center);
};
/**
 * @function OpenLayersUtils.layerClear
 * @description 图层清理
 * @param {OpenLayersMapType} map - 地图对象
 * @param {string[]} 底图图层ID
 */
const layerClear = (map, baseLayerIds = []) => {
    const baseLayers = baseLayerIds.map((layerId) => OpenLayersManager.getLayer(`${map.uid}-${layerId}`));
    const layers = map.getLayers().getArray();
    clearDraw(map);
    layers.forEach((layer) => {
        if (!baseLayers.includes(layer)) {
            layer.setVisible(false);
        }
    });
};
/**
 * @function OpenLayersUtils.clear
 * @description 清除分析结果
 * @param {OpenLayersMapType} map - 地图对象
 */
const clear = (map) => {
    stopCoordPick(map); // 清除二维坐标拾取
    removeMiniMap(map); // 移除二维鹰眼图
    clearMeasure(); // 清除二维测量结果
    resetLocateCoordinate(); // 清除二维坐标定位
    clearDraw(map); // 清除手动绘制
};
let drawObj;
let drawSource;
const collectDraw = [];
let vector;
let lastFeature;
/**
 * @function OpenLayersUtils.draw
 * @description 手动绘制
 * @param {OpenLayersMapType} map - 地图对象
 * @param {DrawingMode} drawingMode - 绘制模式
 * @param {object} options - 绘制配置参数
 * @param {boolean} options.continueDraw - 是否连续绘制 默认：true
 * @param {boolean} options.removeLast - 是否移除上一次绘制的图形 默认：true
 * @param {Function} callback - 回调函数
 */
const draw = (map, drawingMode, options = {
    continueDraw: true,
    removeLast: true
}, callback) => {
    const { continueDraw, removeLast } = options;
    if (drawObj) {
        map.removeInteraction(drawObj);
    }
    if (!vector) {
        // 配置矢量数据源
        drawSource = new VectorSource({
            wrapX: false
        });
        // 添加矢量图层
        vector = new VectorLayer({
            zIndex: Infinity,
            source: drawSource
        });
        map.addLayer(vector);
    }
    const drawOptions = {
        source: drawSource,
        type: drawingMode,
        snapTolerance: 20
    };
    if (drawingMode === 'Rectangle') {
        drawOptions.type = 'Circle';
        drawOptions.geometryFunction = createBox();
    }
    else if (drawingMode === 'Polyline') {
        drawOptions.type = 'LineString';
    }
    try {
        drawObj = new Draw(drawOptions);
        map.addInteraction(drawObj);
        collectDraw.push(drawObj);
        drawObj.on('drawend', (event) => {
            if (lastFeature && removeLast) {
                drawSource.removeFeature(lastFeature);
            }
            lastFeature = event.feature;
            callback && callback(event.feature && event.feature.getGeometry());
            if (!continueDraw) {
                map.removeInteraction(drawObj);
            }
        });
    }
    catch (error) {
        console.log('drawing' + error);
    }
    return drawObj;
};
/**
 * @function OpenLayersUtils.clearDraw
 * @description 清除手动绘制
 * @param {OpenLayersMapType} map - 地图对象
 */
const clearDraw = (map) => {
    if (drawObj) {
        stopDraw(map);
        drawSource.clear();
        map.removeLayer(drawSource);
        drawObj = null;
        lastFeature = null;
    }
};
/**
 * @function OpenLayersUtils.clearDraw
 * @description 停止手动绘制
 * @param {OpenLayersMapType} map - 地图对象
 */
const stopDraw = (map) => {
    drawObj && map.removeInteraction(drawObj);
};
// 卷帘监听器存储相关
const swipeListenerMap = new Map();
function prerenderListener(event, direction, swipeRatio, type) {
    const ctx = event.context;
    ctx.restore();
    ctx.save();
    ctx.beginPath();
    switch (direction) {
        case 'horizontal':
            const width = ctx.canvas.width * swipeRatio;
            if (type === 'leading') {
                ctx.rect(0, 0, width, ctx.canvas.height);
            }
            else if (type === 'trailing') {
                ctx.rect(width, 0, ctx.canvas.width - width, ctx.canvas.height);
            }
            break;
        case 'vertical':
            const height = ctx.canvas.height * swipeRatio;
            if (type === 'leading') {
                ctx.rect(0, 0, ctx.canvas.width, height);
            }
            else if (type === 'trailing') {
                ctx.rect(0, height, ctx.canvas.width, ctx.canvas.height - height);
            }
            break;
    }
    ctx.clip();
}
function postrenderListener(event) {
    const ctx = event.context;
    ctx.restore();
}
/**
 * @function OpenLayersUtils.changeLayerSwipe
 * @description 卷帘分析
 * @param {OpenLayersMapType} map - 地图对象
 * @param {string[]} leadingLayerIds - 卷帘左侧/上侧图层id集合
 * @param {string[]} trailingLayerIds - 卷帘右侧/下侧图层id集合
 * @param {'horizontal' | 'vertical'} direction - 卷帘方向: horizontal-水平、vertical-垂直
 * @param {number} [swipeRatio] - 卷帘比例数值 默认值:0.5
 */
const changeLayerSwipe = (map, leadingLayerIds, trailingLayerIds, direction, swipeRatio = 0.5) => {
    // 卷帘左侧/上侧图层
    leadingLayerIds.forEach((id) => {
        const layerId = `${map.uid}-${id}`;
        const leadingLayer = OpenLayersManager.getLayer(layerId);
        if (swipeListenerMap.has(`${layerId}-lpr`)) {
            unByKey(swipeListenerMap.get(`${layerId}-lpr`));
        }
        const prerender = leadingLayer.on('prerender', (event) => {
            prerenderListener(event, direction, swipeRatio, 'leading');
        });
        prerender && swipeListenerMap.set(`${layerId}-lpr`, prerender);
        if (!swipeListenerMap.has(`${layerId}-lpo`)) {
            const postrender = leadingLayer.on('postrender', postrenderListener);
            postrender && swipeListenerMap.set(`${layerId}-lpo`, postrender);
        }
    });
    // 卷帘右侧/下侧图层
    trailingLayerIds.forEach((id) => {
        const layerId = `${map.uid}-${id}`;
        const trailingLayer = OpenLayersManager.getLayer(layerId);
        if (swipeListenerMap.has(`${layerId}-tpr`)) {
            unByKey(swipeListenerMap.get(`${layerId}-tpr`));
        }
        const prerender = trailingLayer.on('prerender', (event) => {
            prerenderListener(event, direction, swipeRatio, 'trailing');
        });
        prerender && swipeListenerMap.set(`${layerId}-tpr`, prerender);
        if (!swipeListenerMap.has(`${layerId}-tpo`)) {
            const postrender = trailingLayer.on('postrender', postrenderListener);
            postrender && swipeListenerMap.set(`${layerId}-tpo`, postrender);
        }
    });
    map.render();
};
/**
 * @function OpenLayersUtils.spatialRelationsAnalysis
 * @description 空间关系运算
 * @param {RelationsOption} options - 空间关系运算分析参数
 * @param {string} options.url - 服务地址
 * @param {string} options.operateDataset - 数据集名称
 * @param {string} options.sourceDataset - 源数据集名称
 * @param {OverlayOperationType} options.operation - 操作枚举值 CLIP ERASE IDENTITY INTERSECT UNION UPDATE XOR
 * @return 空间关系运算结果
 */
const spatialRelationsAnalysis = (options) => {
    return new Promise((resolve) => {
        const { url, operateDataset, sourceDataset, operation } = options;
        const params = new DatasetOverlayAnalystParameters({
            operateDataset,
            sourceDataset,
            operation
        });
        new SpatialAnalystService(url).overlayAnalysis(params, (serviceResult) => {
            const recordset = serviceResult?.result?.recordset;
            if (recordset) {
                resolve(recordset);
            }
            else {
                console.log('分析结果为空');
            }
        });
    });
};
// 转换成Geometry对象
function converToGeometry(geo) {
    let geometry;
    if (geo instanceof Geometry) {
        if (geo instanceof Circle) {
            geometry = fromCircle(geo);
        }
        geometry = geo;
    }
    else if (geo.type === 'FeatureCollection') {
        const features = new GeoJSON().readFeatures(geo);
        const geometries = features.map((item) => item.getGeometry());
        geometry = new MultiPolygon(geometries);
    }
    else if (geo.type === 'Feature') {
        const features = new GeoJSON().readFeature(geo);
        geometry = features.getGeometry();
    }
    else {
        geometry = new GeoJSON().readGeometry(geo);
    }
    return geometry;
}
// 获取分析geometry
function getAnalysisGeometry(geometry) {
    if (Array.isArray(geometry)) {
        if (geometry.length > 1) {
            geometry = geometry.map((item) => converToGeometry(item));
            return new MultiPolygon(geometry);
        }
        else {
            return converToGeometry(geometry[0]);
        }
    }
    else {
        return converToGeometry(geometry);
    }
}
/**
 * @function OpenLayersUtils.bufferAnalysis
 * @description 几何对象缓冲区分析
 * @param {BufferOption} options - 缓冲区分析参数
 * @param {string} options.url - 服务地址
 * @param {string} options.layerName - 图层名称
 * @param {GeoJSON.Geometry|Geometry} options.geometry - 要做缓冲区分析的几何对象(支持GeoJSON或ol/geom/Geometry)
 * @param {number} options.distance - 缓冲距离
 * @param {boolean} options.isCloseClip - 是否关闭结果裁切-只保留相交部分（默认不关闭）
 * @return bufferResult:缓冲区几何图形，queryResult：根据缓冲区进行叠加分析的结果
 */
const bufferAnalysis = (options) => {
    return new Promise((resolve, reject) => {
        try {
            const { url, layerName, geometry, distance, isCloseClip } = options || {};
            const params = new GeometryBufferAnalystParameters({
                sourceGeometry: getAnalysisGeometry(geometry),
                sourceGeometrySRID: mapConfig.epsgCode?.replace(/[^\d]/g, '') || '3857',
                bufferSetting: new BufferSetting({
                    endType: BufferEndType.ROUND,
                    leftDistance: new BufferDistance({ value: distance }),
                    rightDistance: new BufferDistance({ value: distance }),
                    semicircleLineSegment: 10 // 圆头缓冲圆弧处线段的个数
                })
            });
            new SpatialAnalystService('/supermap-host/iserver/services/spatialanalyst-sample/restjsr/spatialanalyst' // 超图服务器空间分析服务代理
            ).bufferAnalysis(params, (bufferServiceResult) => {
                const resultGeometry = bufferServiceResult?.result?.resultGeometry;
                if (resultGeometry) {
                    const bufferGeometry = resultGeometry?.geometry;
                    if (!bufferGeometry) {
                        reject('缓冲区几何对象为空');
                    }
                    // 根据缓冲区几何做叠加分析
                    overlayAnalysis({
                        url,
                        layerName,
                        geometry: bufferGeometry,
                        isCloseClip
                    }).then((queryFeatures) => {
                        resolve({
                            bufferResult: resultGeometry,
                            queryResult: queryFeatures // 压盖图层地块
                        });
                    });
                }
                else {
                    reject('缓冲区分析结果为空');
                }
            });
        }
        catch (err) {
            reject(err);
        }
    });
};
/**
 * @function OpenLayersUtils.overlayAnalysis
 * @description 叠加分析
 * @param {OverlayOption} options - 分析参数
 * @param {string} options.url - 服务地址
 * @param {string} options.layerName - 图层名称
 * @param {GeoJSON.Geometry|Geometry} options.geometry - 几何对象(支持GeoJSON或ol/geom/Geometry)
 * @param {boolean} options.isCloseClip - 是否关闭结果裁切,只保留相交部分（默认不关闭）
 * @return 叠加分析结果
 */
const overlayAnalysis = (options) => {
    return new Promise((resolve, reject) => {
        try {
            const { url, layerName, geometry, isCloseClip } = options;
            let currentIsCloseClip = isCloseClip;
            const queryGeometry = getAnalysisGeometry(geometry); // 统一转换成Geometry对象
            const queryByGeometryParameters = new QueryByGeometryParameters({
                queryParams: [
                    new FilterParameter({
                        name: layerName
                    })
                ],
                geometry: queryGeometry,
                spatialQueryMode: SpatialQueryMode.INTERSECT
            });
            // 几何对象查询
            new QueryService(url).queryByGeometry(queryByGeometryParameters, function (queryServiceResult) {
                const queryFeatures = queryServiceResult?.result?.recordsets[0]?.features;
                queryFeatures.features[0].geometry.type === 'Point' &&
                    (currentIsCloseClip = true);
                if (!currentIsCloseClip && queryFeatures) {
                    const geojson = JSON.parse(new GeoJSON().writeGeometry(queryGeometry));
                    queryFeatures.features = queryFeatures.features.map((feature) => Intersect(geojson, feature, { properties: feature.properties }) // 进行相交，保留重叠部分
                    );
                }
                if (queryFeatures?.features?.length) {
                    resolve(queryFeatures);
                }
                else {
                    reject('叠加分析结果为空');
                }
            });
        }
        catch (err) {
            reject(err);
        }
    });
};
const geojosnStyle = new Style({
    stroke: new Stroke({
        color: '#ffff00',
        width: 2
    }),
    fill: new Fill({
        color: '#89cff06b'
    }),
    image: new CircleStyle({
        radius: 3,
        fill: new Fill({
            color: '#ff0000'
        }),
        stroke: new Stroke({
            color: '#000',
            width: 1
        })
    })
});
/**
 * @function OpenLayersUtils.addGeoJSONLayer
 * @description 添加GeoJSON数据图层
 * @param {OpenLayersMapType} map - 地图对象
 * @param {any} geojson - GeoJSON数据
 * @param {Style} style - 图层样式
 * @return GeoJSON数据图层
 */
const addGeoJSONLayer = (map, geojson, style) => {
    const vectorSource = new VectorSource({
        features: new GeoJSON().readFeatures(geojson),
        wrapX: false
    });
    const resultLayer = new VectorLayer({
        source: vectorSource,
        style: style || geojosnStyle
    });
    map.addLayer(resultLayer);
    return resultLayer;
};
/**
 * @function OpenLayersUtils.getLayersInfo
 * @description 获取图层信息
 * @param {string} url - 服务地址
 */
const getLayersInfo = (url) => {
    return new Promise((resolve) => {
        new LayerInfoService(url).getLayersInfo((serviceResult) => {
            resolve(serviceResult?.result);
        });
    });
};
/**
 * @function OpenLayersUtils.queryMapServiceStatistics
 * @description 地图服务查询统计
 * @param {string} url - 服务地址
 * @param {SearchOption} options - 查询条件
 */
const queryMapServiceStatistics = ({ url, options }) => {
    const promise = new Promise((resolve, reject) => {
        const search = options.search;
        const summary = options.summary;
        const queryParams = [];
        if (Array.isArray(search)) {
            search.forEach((item) => {
                if (!item?.layerName)
                    return; // 超图服务查询必须要有图层名称
                const attributeFilter = getWhere(item);
                queryParams.push({
                    name: item.layerName,
                    attributeFilter
                });
            });
        }
        else {
            if (!search?.layerName)
                return; // 超图服务查询必须要有图层名称
            const attributeFilter = getWhere(search);
            queryParams.push({
                name: search.layerName,
                attributeFilter
            });
        }
        if (!queryParams.length)
            reject('查询条件为空');
        let result;
        if (options?.geometry) {
            const geometry = getAnalysisGeometry(options.geometry);
            const queryParam = new QueryByGeometryParameters({
                queryParams,
                geometry,
                returnFeatureWithFieldCaption: true
            });
            new QueryService(url).queryByGeometry(queryParam, function (serviceResult) {
                if (!serviceResult.result) {
                    reject('查询结果为空');
                }
                const recordSets = serviceResult.result.recordsets;
                if (summary) {
                    result = statisticsSummary(recordSets, summary, geometry);
                }
                else {
                    result = recordSets;
                }
                resolve(result);
            });
        }
        else {
            const queryParam = new QueryBySQLParameters({
                queryParams,
                returnFeatureWithFieldCaption: true
            });
            new QueryService(url).queryBySQL(queryParam, function (serviceResult) {
                if (!serviceResult.result) {
                    reject('查询结果为空');
                }
                const recordSets = serviceResult.result.recordsets;
                if (summary) {
                    result = statisticsSummary(recordSets, summary);
                }
                else {
                    result = recordSets;
                }
                resolve(result);
            });
        }
    });
    return promise;
};
/**
 * @function OpenLayersUtils.getWhere
 * @description 条件拼接
 * @param {WhereOption} - 条件选项
 */
const getWhere = ({ where, connection }) => {
    let whereStr = '';
    if (where && where.length > 0) {
        const whereArr = [];
        where?.forEach((el) => {
            const { field, type, value } = el;
            const val = typeof value === 'string' ? `'${value}'` : value;
            switch (type) {
                case 'like':
                    whereArr.push(`${field} like '%${value}%'`);
                    break;
                case '<>':
                    whereArr.push(`${field} <> ${val}`);
                    break;
                case '=':
                    whereArr.push(`${field} = ${val}`);
                    break;
                case 'in':
                    const _val = Array.isArray(value) ? value : [value];
                    const str = _val
                        .map((el) => {
                        return typeof el === 'string' ? `'${el}'` : el;
                    })
                        .join(',');
                    whereArr.push(`${field} in (${str})`);
                    break;
                case 'not in':
                    const _val2 = Array.isArray(value) ? value : [value];
                    const str2 = _val2
                        .map((el) => {
                        return typeof el === 'string' ? `'${el}'` : el;
                    })
                        .join(',');
                    whereArr.push(`${field} not in (${str2})`);
                    break;
                case 'is null':
                    whereArr.push(`${field} is null`);
                    break;
                case 'is not null':
                    whereArr.push(`${field} is not null`);
                    break;
                default:
                    whereArr.push(`${field} ${type} ${value}`);
                    break;
            }
        });
        whereStr = whereArr[0];
        for (let i = 1; i < whereArr.length; i++) {
            const con = connection && connection[i - 1] ? connection[i - 1] : 'and';
            const str = whereArr[i];
            whereStr += ' ' + con + ' ' + str;
        }
    }
    return whereStr;
};
/**
 * @function OpenLayersUtils.statisticsSummary
 * @description 统计汇总
 * @param {any}datas - 查询结果
 * @param {SummaryOption}summary - 汇总条件
 * @param {any}intersectGeoJSON - 相交图形
 */
const statisticsSummary = (datas, summary, intersectGeoJSON) => {
    const { statisticalField, areaField, lengthField, spatialCRS } = summary;
    const resultMap = new Map();
    const resultList = [];
    datas.forEach((item) => {
        item.features.features.forEach((feature) => {
            let resultFeature = feature;
            const { geometry, properties } = feature;
            if (intersectGeoJSON) {
                // 叠加获取相交部分
                const geojson = JSON.parse(new GeoJSON().writeGeometry(intersectGeoJSON));
                const intersectGeometry = Intersect(geojson, geometry, {
                    properties
                }); // 进行相交，保留重叠部分
                let coordinates = intersectGeometry?.geometry.coordinates;
                if (spatialCRS && spatialCRS !== 'EPSG:4326') {
                    coordinates = transformCoorsTo84(intersectGeometry?.geometry.coordinates, spatialCRS);
                }
                const type = geometry.type;
                let calcFeature, intersectArea = 0, intersectLength = 0;
                switch (type) {
                    case 'Polygon':
                    case 'MultiPolygon':
                        if (coordinates.length > 1) {
                            calcFeature = multiPolygon(coordinates);
                        }
                        else {
                            calcFeature = polygon(coordinates);
                        }
                        break;
                    case 'LineString':
                        calcFeature = lineString(coordinates);
                        break;
                    case 'MultiLineString':
                        calcFeature = multiLineString(coordinates);
                        break;
                }
                try {
                    intersectArea = Area(calcFeature); // 单位：平方米
                    intersectLength = Length(calcFeature) * 1000; // 单位：米
                }
                catch (err) {
                    console.warn(err);
                }
                resultFeature = intersectGeometry;
                properties[areaField] = intersectArea;
                properties[lengthField] = intersectLength;
            }
            const name = properties[statisticalField];
            const geometryArea = Number(properties[areaField]);
            const geometryLength = Number(properties[lengthField]);
            if (resultMap.has(name)) {
                const item = resultMap.get(name);
                item.index++;
                item.area += geometryArea;
                item.length += geometryLength;
                item.geometryList.push(resultFeature);
            }
            else {
                resultMap.set(name, {
                    index: 1,
                    area: geometryArea,
                    length: geometryLength,
                    geometryList: [resultFeature]
                });
            }
        });
    });
    resultMap.forEach(({ index, area, length, geometryList }, key) => {
        const obj = {
            name: key,
            num: index,
            area: Number(area.toFixed(2)),
            length: Number(length.toFixed(2)),
            geometry: geometryList
        };
        resultList.push(obj);
    });
    return resultList;
};
/**
 * @function OpenLayersUtils.transformCoorsTo84
 * @description 坐标转换到WGS84
 * @param {any} coordinates  -坐标
 * @param {string} spatialCRS -坐标系
 */
const transformCoorsTo84 = (coordinates, spatialCRS) => {
    if (coordinates?.length === 2 &&
        typeof coordinates[0] === 'number' &&
        coordinates.every(Number.isFinite)) {
        return proj4(spatialCRS, 'EPSG:4326', coordinates);
    }
    else {
        return coordinates.map((item) => transformCoorsTo84(item, spatialCRS));
    }
};
export { createMap, setMapConfig, fullExtent, zoomIn, zoomOut, moveTo, moveBy, addMiniMap, removeMiniMap, startMeasure, clearMeasure, startCoordPick, stopCoordPick, addLayer, removeLayer, queryLayerData, queryMapService, changeLayerOpacity, extractElementByClick, removeElement, setLocateCoordinate, resetLocateCoordinate, changeLayerSwipe, syntaxView, draw, clearDraw, spatialRelationsAnalysis, bufferAnalysis, overlayAnalysis, layerClear, clear, addGeoJSONLayer, getLayersInfo, pickAttribute, queryMapServiceStatistics, getAnalysisGeometry };
