    import { FeatureLayer } from '../baseLayer'
    import { Zondy } from '../../../base'
    import { LayerType, LoadStatus } from '../../../base/enum'
    import {Log, defaultValue, isNull, toJSON} from '../../../util'
    import { FeatureServer, ResourceServer } from '../../../service'
    import { Extent, SpatialReference } from '../../../base/geometry'
    import epsg from '../../../base/EPSG'
    import {getBaseUrl, jsonClone} from '../../../util/Utils'
    import LabelClass from '../../support/LabelClass'

    /**
     * IGS要素图层，<br>
     * 目前二维和三维上支持4326(包括4490，4214以及4610)，3857以及EPSG支持的自定义坐标系，要素服务会自动读取元信息上的坐标系，不需要用户指定
     * <br><br>[ES5引入方式]：<br/>
     * Zondy.Layer.IGSFeatureLayer() <br/>
     * [ES6引入方式]：<br/>
     * import { IGSFeatureLayer } from "@mapgis/webclient-common" <br/>
     * <br/>
     * 针对图层的操作请在图层加载完毕事件中进行<br/>
     * Layer.on('layerview-created', function (result) {<br/>
     *   console.log("加载完毕:", result.layer)<br/>
     * });<br/>
     * 如果不想在该事件中放入业务代码，则请确认图层资源已加载完毕后再进行操作<br/>
     * if(layer.loadStatus === 'loaded') {<br/>
     *   // 你的业务逻辑<br/>
     * }
     * @class IGSFeatureLayer
     * @moduleEX LayerModule
     * @classdesc IGS地图图层
     * @extends FeatureLayer
     * @fires Layer#图层加载完毕事件
     * @fires Layer#图层销毁完毕事件
     * @fires Layer#图层更新完毕事件
     * @fires Layer#图层显隐更新完毕事件
     * @fires Layer#图层透明度更新完毕事件
     * @fires Layer#图层刷新完毕事件
     * @fires IGSFeatureLayer#图层样式更新完毕事件
     * @param {Object} options 构造参数
     * @param {String} [options.url] 服务基地址，<br/>
     * 1、IGS2.0服务：http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer<br/>
     * 示例如下：<br/>
     * <a href='#add-IGSFeatureLayer'>[1、添加IGS要素图层-不指定图层]</a><br/>
     * <a href='#IGSFeatureLayer-id'>[2、添加IGS要素图层-指定图层id]</a><br/>
     * <a href='#IGSFeatureLayer-url'>[3、添加IGS要素图层-在基地址中指定图层id]</a><br/>
     * 2、IGS1.0服务：http://{ip}:{port}/igs/rest/mrfs/docs/{ServiceName}<br/>
     * 示例如下：<br/>
     * <a href='#IGSFeatureLayer-IGS1.0'>[1、添加IGS要素图层-IGS1.0]</a><br/>
     * 3、GDBP服务，注意该服务不支持注记：http://{ip}:{port}/igs/rest/mrfs/layer<br/>
     * 示例如下：<br/>
     * <a href='#IGSFeatureLayer-gdbp'>[1、指定一个gdbp地址来渲染要素]</a><br/>
     * 4、删除图层方法：<a href='#remove-layer'>[删除图层]</a>
     * @param {Number|String} [options.sublayerId = 0] 要素服务的子图层id，不指定则查询第0个图层，指定时，则查询指定layerId的图层
     * @param {String} [options.gdbp] 指定一个gdbp数据源来加载图形，格式如下：gdbp://MapGisLocal/武汉市/ds/4326矢量/sfcls/武汉市区划4326
     * @param {String} [options.id] 图层id，图层的唯一标识，不指定则给一个随机id
     * @param {Number} [options.opacity = 1] 图层透明度，0到1之间的值，0为完全透明，1为不透明，参考示例：<a href='#opacity'>[设置图层透明度]</a>
     * @param {Boolean} [options.visible = true] 图层显示或隐藏，true则显示，false则隐藏，参考示例：<a href='#visible'>[设置图层显示或隐藏]</a>
     * @param {String} [options.renderMode = 'client'] 渲染模式，分为客户端渲染'client'和服务器端渲染'server'
     * @param {Renderer} [options.renderer] 渲染样式，<br>
     * 目前支持如下样式：<br/>
     * [1、单值专题图]{@link UniqueValueRenderer}<br/>
     * [2、分段专题图]{@link ClassBreakRenderer}<br/>
     * [3、统一专题图]{@link SimpleRenderer}<br/>
     * 参考示例：<br/>
     * <a href='#UniqueValueRenderer'>[1、单值专题图]</a><br/>
     * <a href='#ClassBreakRenderer'>[2、分段专题图]</a><br/>
     * <a href='#SimpleRenderer'>[3、统一专题图]</a><br/>
     * @param {String} [options.definitionExpression = ''] sql语句查询，例如name='中国'
     * @param {Boolean} [options.labelsVisible = false] 是否开启动态注记，仅支持三维场景
     * @param {Array<LabelClass>} [options.labelingInfo = []] 注记样式数组，可以和renderer同时启用，默认取数组的第一个样式，
     * 仅支持三维场景，参考示例：<a href='#add-labelingInfo'>[注记样式]</a><br/>
     * @param {Number} [options.minScale = null] 最小比例尺，只有当地图视图的比例尺大于最小比例尺时显示要素图层
     * @param {Number} [options.maxScale = null] 最大比例尺，只有当地图视图的比例尺小于最大比例尺时显示要素图层
     * @param {String} [options.tokenKey = 'token'] token名
     * @param {String} [options.tokenValue] token值，只有当tokenValue存在时，才会绑定token
     * @param {Boolean} [options.supportArc3 = true] 是否返回三点弧段数据，为true则返回三个点代表三点弧段，否则返回离散的点
     *
     * @summary <h5>支持如下方法：</h5>
     * <a href='#load'>[1、加载图层资源]</a><br/>
     * <a href='#queryFeatures'>[2、指定图层的要素查询]</a><br/>
     * <a href='#queryFeaturesCount'>[3、查询要素数量]</a><br/>
     * <a href='#fromJSON'>[4、通过传入的json构造并返回一个新的几何对象]</a><br/>
     * [5、导出为json对象]{@link OGCLayer#toJSON}<br/>
     * [6、克隆几何对象]{@link OGCLayer#clone}
     *
     * @example <caption><h7 id='add-IGSFeatureLayer'>添加IGS要素图层-不指定图层</h7></caption>
     * // ES5引入方式
     * const { Map , MapView } = Zondy
     * const { IGSFeatureLayer } = Zondy.Layer
     * // ES6引入方式
     * import { Map , MapView, IGSFeatureLayer} from "@mapgis/webclient-common"
     * // 初始化图层管理容器
     * const map = new Map();
     * // 初始化地图视图对象
     * const mapView = new MapView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 添加图层
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer'
     * })
     * map.add(igsFeatureLayer)
     *
     * @example <caption><h7 id='IGSFeatureLayer-id'>添加IGS要素图层-指定图层id</h7></caption>
     * // ES5引入方式
     * const { IGSFeatureLayer } = Zondy.Layer
     * // ES6引入方式
     * import {  IGSFeatureLayer} from "@mapgis/webclient-common"
     * // 添加图层
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
     *   // 指定图层id
     *   sublayerId: 2
     * })
     * map.add(igsFeatureLayer)
     *
     * @example <caption><h7 id='IGSFeatureLayer-url'>添加IGS要素图层-在基地址中指定图层id</h7></caption
     * // ES5引入方式
     * const { IGSFeatureLayer } = Zondy.Layer
     * // ES6引入方式
     * import {  IGSFeatureLayer} from "@mapgis/webclient-common"
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址，再基地址上指定图层id
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer/1'
     * })
     * map.add(igsFeatureLayer)
     *
     * @example <caption><h7 id='IGSFeatureLayer-IGS1.0'>添加IGS要素图层-IGS1.0</h7></caption>
     * // ES5引入方式
     * const { IGSFeatureLayer } = Zondy.Layer
     * // ES6引入方式
     * import {  IGSFeatureLayer} from "@mapgis/webclient-common"
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址，再基地址上指定图层id
     *   url: 'http://{ip}:{port}/igs/rest/mrfs/docs/{ServiceName}',
     *   // 图层id
        sublayerId: '1'
     * })
     * map.add(igsFeatureLayer)
     *
     * @example <caption><h7 id='remove-layer'>删除图层</h7></caption>
     * map.remove(igsFeatureLayer)
     *
     * @example <caption><h7 id='opacity'>设置图层透明度</h7></caption>
     * // ES5引入方式
     * const { IGSFeatureLayer } = Zondy.Layer
     * // ES6引入方式
     * import {  IGSFeatureLayer} from "@mapgis/webclient-common"
     * // 在初始化时设置
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址，再基地址上指定图层id
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer/1',
     *   // 设置透明度
     *   opacity: 1
     * })
     * map.add(igsFeatureLayer)
     *
     * // 在图层加载完毕后设置
     * igsFeatureLayer.opacity = 0.5
     *
     * @example <caption><h7 id='visible'>设置图层可见性</h7></caption>
     * // ES5引入方式
     * const { IGSFeatureLayer } = Zondy.Layer
     * // ES6引入方式
     * import {  IGSFeatureLayer} from "@mapgis/webclient-common"
     * // 在初始化时设置
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址，再基地址上指定图层id
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer/1',
     *   // 设置图层可见性
     *   visible: true
     * })
     * map.add(igsFeatureLayer)
     *
     * // 在图层加载完毕后设置
     * igsFeatureLayer.visible = !igsFeatureLayer.visible
     *
     * @example <caption><h7 id='index'>图层顺序</h7></caption>
     * // 加载完毕后，更改图层顺序
     * map.reorder(igsFeatureLayer, '要移动到的index');
     *
     * @example <caption><h7 id='UniqueValueRenderer'>单值专题图</h7></caption>
     * // ES5引入方式
     * const { IGSFeatureLayer } = Zondy.Layer
     * const { UniqueValueRenderer } = Zondy.Renderer
     * const { SimpleFillSymbol,SimpleLineSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import {  IGSFeatureLayer,UniqueValueRenderer,SimpleFillSymbol,SimpleLineSymbol,Color } from "@mapgis/webclient-common"
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址，当不指定图层名称时，默认查询第一个子图层
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
     *   // 设置渲染样式-单值专题图
     *   renderer: renderer: new UniqueValueRenderer({
     *     // 专题图过滤字段名
     *     field: '字段名',
     *     // 默认样式，当没有匹配到指定值时，会使用默认样式
     *     // 因为该数据的几何类型为区，因此设置区样式
     *     defaultSymbol: new SimpleFillSymbol({
     *       // 填充颜色
     *       color: new Color(255, 0, 0),
     *       // 外边线样式
     *       outline: new SimpleLineSymbol({
     *         // 线颜色
     *         color: new Color(0, 0, 0),
     *         // 线宽
     *         width: 1
     *       })
     *     }),
     *     // 单值专题图过滤条件数组
     *     uniqueValueInfos: [
     *       {
     *         //指定字段值
     *         value: '过滤字段值1',
     *         //匹配到该值后的样式
     *         // 因为该数据的几何类型为区，因此设置区样式
     *         symbol: new SimpleFillSymbol({
     *           // 填充颜色
     *           color: new Color(255, 0, 0)
     *         })
     *       },
     *       {
     *         //指定字段值
     *         // 因为该数据的几何类型为区，因此设置区样式
     *         value: '过滤字段值2',
     *         //匹配到该值后的样式
     *         // 因为该数据的几何类型为区，因此设置区样式
     *         symbol: new SimpleFillSymbol({
     *           // 填充颜色
     *           color: 'rgb(255, 123, 220)'
     *         })
     *       }
     *     ]
     *   })
     * })
     * map.add(igsFeatureLayer3)
     *
     * @example <caption><h7 id='ClassBreakRenderer'>分段专题图</h7></caption>
     * // ES5引入方式
     * const { IGSFeatureLayer } = Zondy.Layer
     * const { ClassBreakRenderer } = Zondy.Renderer
     * const { SimpleLineSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import {  IGSFeatureLayer,ClassBreakRenderer,SimpleLineSymbol,Color } from "@mapgis/webclient-common"
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址，当不指定图层名称时，默认查询第一个子图层
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
     *   // 设置渲染样式-分段专题图
     *   renderer: new ClassBreakRenderer({
     *     // 专题图过滤字段名
     *     field: '字段名',
     *     // 默认样式，当没有匹配到指定值时，会使用默认样式
     *     // 因为该数据的几何类型为线，因此设置线样式
     *     defaultSymbol: new SimpleLineSymbol({
     *       // 线符号颜色
     *       color: new Color(1, 244, 0),
     *       // 线宽
     *       width: 3
     *     }),
     *     // 分段专题图过滤条件数组
     *     classBreakInfos: [
     *       {
     *         // 最小过滤范围，field对应的值大于等于minValue
     *         minValue: 0,
     *         // 最大过滤范围，field对应的值小于maxValue
     *         maxValue: 2,
     *         // 匹配到该值后的样式
     *         // 因为该数据的几何类型为线，因此设置线样式
     *         symbol: new SimpleLineSymbol({
     *           // 线符号颜色
     *           color: new Color(1, 244, 0),
     *           // 线宽
     *           width: 3
     *         })
     *       },
     *       {
     *         // 最小过滤范围，field对应的值大于等于minValue
     *         minValue: 3,
     *         // 最大过滤范围，field对应的值小于maxValue
     *         maxValue: 5,
     *         // 匹配到该值后的样式
     *         // 因为该数据的几何类型为线，因此设置线样式
     *         symbol: new SimpleLineSymbol({
     *           // 线符号颜色
     *           color: new Color(111, 144, 10),
     *           // 线宽
     *           width: 3
     *         })
     *       },
     *       {
     *         // 最小过滤范围，field对应的值大于等于minValue
     *         minValue: 5,
     *         // 最大过滤范围，field对应的值小于maxValue
     *         maxValue: 7,
     *         // 匹配到该值后的样式
     *         // 因为该数据的几何类型为线，因此设置线样式
     *         symbol: new SimpleLineSymbol({
     *           // 线符号颜色
     *           color: new Color(22, 244, 10),
     *           // 线宽
     *           width: 3
     *         })
     *       },
     *       {
     *         // 最小过滤范围，field对应的值大于等于minValue
     *         minValue: 7,
     *         // 最大过滤范围，field对应的值小于maxValue
     *         maxValue: 9,
     *         // 匹配到该值后的样式
     *         // 因为该数据的几何类型为线，因此设置线样式
     *         symbol: new SimpleLineSymbol({
     *           // 线符号颜色
     *           color: new Color(33, 44, 10),
     *           // 线宽
     *           width: 3
     *         })
     *       },
     *       {
     *         // 最小过滤范围，field对应的值大于等于minValue
     *         minValue: 9,
     *         // 最大过滤范围，field对应的值小于maxValue
     *         maxValue: 20,
     *         // 匹配到该值后的样式
     *         // 因为该数据的几何类型为线，因此设置线样式
     *         symbol: new SimpleLineSymbol({
     *           // 线符号颜色
     *           color:  new ZColor(123, 124, 110),
     *           // 线宽
     *           width: 3
     *         })
     *       }
     *     ]
     *   })
     * })
     * map.add(igsFeatureLayer)
     *
     * @example <caption><h7 id='SimpleRenderer'>统一专题图</h7></caption>
     * // ES5引入方式
     * const { IGSFeatureLayer } = Zondy.Layer
     * const { SimpleRenderer } = Zondy.Renderer
     * const { SimpleFillSymbol,SimpleLineSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import {  IGSFeatureLayer,SimpleRenderer,SimpleFillSymbol,SimpleLineSymbol,Color } from "@mapgis/webclient-common"
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址，当不指定图层名称时，默认查询第一个子图层
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
     *   // 设置渲染样式-统一专题图
     *   renderer: new SimpleRenderer({
     *     // 因为该数据的几何类型为区，因此设置区样式
     *     symbol: new SimpleFillSymbol({
     *       // 填充颜色
     *       color: new Color(255, 0, 0),
     *       // 外边线样式
     *       outline: new SimpleLineSymbol({
     *         // 线颜色
     *         color: new Color(0, 0, 0),
     *         // 线宽度
     *         width: 1
     *       })
     *     })
     *   })
     * })
     * map.add(igsFeatureLayer)
     *
     * @example <caption><h7 id='IGSFeatureLayer-gdbp'>指定一个gdbp地址来渲染要素</h7></caption>
     * // ES5引入方式
     * const { IGSFeatureLayer } = Zondy.Layer
     * // ES6引入方式
     * import {  IGSFeatureLayer } from "@mapgis/webclient-common"
     * const igsFeatureLayer = new IGSFeatureLayer({
     *   // 服务基地址，该地址为要素服务1.0地址
     *   url: "http://{ip}:{port}/igs/rest/mrfs/layer",
     *   // gdbp地址，在桌面的数据库中右键简单要素类，来获取该地址
     *   gdbp: "gdbp://MapGisLocal/武汉市/ds/4326矢量/sfcls/武汉市区划4326"
     * })
     * map.add(igsFeatureLayer)
     *
     * @example <caption><h7 id='add-labelingInfo'>启用注记</h7></caption>
     * // ES5引入方式
     * const { igsFeatureLayer } = Zondy.Layer
     * const { LabelClass ,Font} = Zondy
     * const { TextSymbol } = Zondy.Symbol
     * // ES6引入方式
     * import {  igsFeatureLayer,LabelClass,Font,TextSymbol } from "@mapgis/webclient-common"
     * // 初始化LabelClass
     * const labelClass = new LabelClass({
     *   // 指定文本符号样式
     *   symbol: new TextSymbol({
     *     // 文字颜色
     *     color: new Color(252, 100, 22, 1),
     *     // 文字样式
     *     font: new Font({
     *       // 字体
     *       family: "微软雅黑",
     *       // 文字大小，单位像素
     *       size: 30,
     *       // 文字是否为斜体，正常模式
     *       style: "normal",
     *       // 文字粗细
     *       weight: "normal"
     *     })
     *   })
     * })
     * // 初始化IGS要素图层
     * const igsFeatureLayer = new igsFeatureLayer({
     *   // 服务基地址，当不指定图层名称时，默认查询第一个子图层
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/FeatureServer',
     *   // 可在此处设置渲染样式
     *   renderer: {},
     *   // 启用注记
     *   labelsVisible: true,
     *   // 设置注记样式
     *   labelingInfo: [labelClass]
     * })
     * // 添加到容器中
     * map.add(igsFeatureLayer)
     * */

    /**
     * 图层样式更新完毕事件，请注意该事件是图层更新事件(layerview-update)的子事件
     * @event IGSFeatureLayer#图层样式更新完毕事件
     * @property {Object} event 事件对象
     * @property {String} [event.type = 'layerview-update'] 图层更新完毕事件
     * @property {String} [event.message = null] 更新描述
     * @property {Array<UpdateContent>} [event.updateContent = null] 更新详情对象
     * @property {Layer} [event.layer = null] 地图图层对象
     * @property {MapView} [event.layerView = null] 图层的视图对象
     * @property {Layer} [event.sourceTarget = null] 事件发起对象
     * @property {Map} [event.target = null] 事件接收对象
     * @example <caption><h5>图层样式更新完毕事件</h5></caption>
     * Layer.on('layerview-update', function (event) {
     *   // 获取更新事件对象
     *   console.log("更新完毕:", event)
     *   // 获取更新详情数组
     *   const updateContent = event.updateContent
     *   // 循环数组，根据事件名进行后续操作
     *   for (let i = 0; i < updateContent.length; i++) {
     *     // 图层样式更新完毕事件
     *     if(updateContent[i].name === 'renderer'){
     *       console.log("图层样式更新完毕事件:", event);
     *     }
     *   }
     * });
     */
    class IGSFeatureLayer extends FeatureLayer {
      constructor(options) {
        super(options)
        options = defaultValue(options, {})
        this.url = defaultValue(options.url, undefined)
        this.type = LayerType.igsFeature
        /**
         * gdbp数据源
         * @member {String} IGSFeatureLayer.prototype.gdbp
         */
        this.gdbp = defaultValue(options.gdbp, '')
        /**
         * 服务返回的要素字段名数组
         * @member {Array<String>} IGSFeatureLayer.prototype.outFields
         */
        this.outFields = []
        /**
         * 服务支持的能力
         * @member {Array<String>} IGSFeatureLayer.prototype.capabilities
         */
        this.capabilities = []
        /**
         * 要素图层index
         * @member {Number|String} IGSFeatureLayer.prototype.sublayerId
         */
        this.sublayerId = defaultValue(options.sublayerId, 0)
        /**
         * 是否开启动态注记,仅支持三维动态注记渲染
         * @member {Boolean} IGSFeatureLayer.prototype.labelsVisible
         */
        this.labelsVisible = defaultValue(options.labelsVisible, false)
        /**
         * 是否返回三点弧段数据，为true则返回三个点代表三点弧段，否则返回离散的点
         * @member {Boolean} IGSFeatureLayer.prototype.supportArc3
         */
        this.supportArc3 = defaultValue(options.supportArc3, true)
        /**
         * 注记样式数组，默认取数组的第一个样式，仅支持三维动态注记渲染
         * @member {Array<LabelClass>} IGSFeatureLayer.prototype.labelingInfo
         */
        const _labelingInfo = []
        const _optLabelingInfo = defaultValue(options.labelingInfo, [])
        for (let i = 0; i < _optLabelingInfo.length; i++) {
          _labelingInfo.push(new LabelClass(_optLabelingInfo[i]))
        }
        this.labelingInfo = _labelingInfo
        /**
         * 渲染模式，分为客户端渲染'client'和服务器端渲染'server'
         * @member {String} IGSFeatureLayer.prototype.renderMode
         */
        this.renderMode = defaultValue(options.renderMode, 'client')
        this._definitionExpression = defaultValue(options.definitionExpression)
        // 处理外部图层id
        const processSublayerId = () => {
          const reg = /^.*FeatureServer/
          const reg1 = /^.*\/igs\/rest\/mrfs\/docs\//
          const matchResult = this.url.match(reg)
          const matchResult1 = this.url.match(reg1)
          if (matchResult) {
            const url = matchResult[0]
            // 解析图层id
            if (this.url.length !== url.length) {
              const len = this.url.length - url.length
              const substr = this.url.substr(url.length + 1, len - 1)
              this.sublayerId = substr
              this.url = url
            }
          } else if (matchResult1) {
            const url = matchResult1[0]
            const str = this.url.replace(url, '')
            if (str) {
              const splitArr = str.split('/')
              if (splitArr.length > 1) {
                this.url = url + splitArr[0]
                this.sublayerId = splitArr[1]
              }
            }
          }
        }
        // igs服务版本
        this._igsVersion = '2.0'
        // 渲染模式区分
        if (this.renderMode === 'client') {
          const baseUrl = getBaseUrl(this.url)
          if (this.url.indexOf('/igs/rest/mrfs/layer') > -1) {
            this._igsVersion = '1.0'
            this._resourceServer = new ResourceServer({
              url: `${baseUrl}/igs/rest/mrcs`
            })
            this._featureServer = new FeatureServer({
              url: this.url
            })
          } else {
            if (this.url.indexOf('/igs/rest/mrfs/docs') > -1) {
              this._igsVersion = '1.0'
            }
            // 分离url
            processSublayerId()
            // 构造服务server
            this._featureServer = new FeatureServer({
              url: this.url
            })
          }
        } else {
          const baseUrl = getBaseUrl(this.url)
          // 1.0
          if (this.url.indexOf('/igs/rest/mrfs/layer') > -1) {
            this._igsVersion = '1.0'
            this._resourceServer = new ResourceServer({
              url: `${baseUrl}/igs/rest/mrcs`
            })
          } else {
            // 分离url
            processSublayerId()
            // 构造服务server
            this._featureServer = new FeatureServer({
              url: this.url
            })
            // 2.0
            this._igsVersion = '2.0'
            this._resourceServer = new ResourceServer({
              url: `${baseUrl}/igs/rest/services/system/ResourceServer`
            })
          }
        }
      }

      /**
       * 加载图层资源
       * @example <caption><h7 id='load'>不加载图层，仅获取图层信息</h7></caption>
       * // 初始化图层
       * const igsFeatureLayer = new Zondy.Layer.IGSFeatureLayer({
       *   // 服务基地址
       *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/FeatureServer',
       * });
       * igsFeatureLayer.load().then((result) => {
       *   // 获取完图层信息
       *   console.log(result)
       * })
       * @return {Promise<IGSFeatureLayer>}
       */
      load() {
        return super.load()
      }

      /**
       * 子类加载服务端元信息的方法
       * @private
       * */
      _load() {
        const self = this
        // 客户端渲染
        if (self.renderMode === 'client') {
          if (self.url.indexOf('/igs/rest/mrfs/layer') > -1) {
            // 1.0 gdbp
            return this._resourceServer
              .queryGDBPInfo({
                gdbpUrl: this.gdbp
              })
              .then((res) => {
                // 解析信息无效
                return new Promise((resolve) => {
                  self.loadStatus = LoadStatus.loaded
                  self.loaded = true
                  resolve(self)
                })
              })
          } else {
            return self._featureServer
              .queryLayerInfo({
                layerId: `${self.sublayerId}`
              })
              .then((result) => {
                const data = result.data
                // 解析元数据
                self._processDataInfo(self, data)
                return new Promise((resolve) => {
                  self.loadStatus = LoadStatus.loaded
                  self.loaded = true
                  resolve(self)
                })
              })
              .catch((result) => {
                Log.error('要素服务图层信息获取失败:', result)
              })
          }
        }
        // 服务器端渲染
        else if (self.renderMode === 'server') {
          if (this._igsVersion === '1.0') {
            // 1.0 gdbp
            return this._resourceServer
              .queryGDBPInfo({
                gdbpUrl: this.gdbp
              })
              .then((res) => {
                // 解析信息无效
                return new Promise((resolve) => {
                  self.loadStatus = LoadStatus.loaded
                  self.loaded = true
                  resolve(self)
                })
              })
          } else {
            // 2.0 gdbp
            // 目前igs2.0上取图时，无法从要素服务查询到gdbp地址
            return this._resourceServer
              .queryTempDataInfo({
                method: Zondy.Enum.FetchMethod.get,
                url: self.gdbp
              })
              .then((result) => {
                const data = result.data
                // 解析元数据
                self._processDataInfo(self, data)
                return new Promise((resolve) => {
                  self.loadStatus = LoadStatus.loaded
                  self.loaded = true
                  resolve(self)
                })
              })
              .catch((result) => {
                Log.error('要素服务图层信息获取失败:', result)
              })
          }
        } else {
          Log.error('无法解析渲染模式')
        }
      }

      /**
       * 指定图层的要素查询
       * @param {Object} queryOptions 参考此接口的入参{@link FeatureServer#queryFeatures}
       * @return {Promise<FeatureSet>}
       * @example <caption><h7 id='queryFeatures'>指定图层的要素查询</h7></caption>
       * igsFeatureLayer.queryFeatures({
       *   // 图层id
       *   sublayerId: '0',
       *   // where语句
       *   where: "NAME='天门市'"
       * }).then((result) => {
       *   console.log('查询结果:', result)
       * })
       */
      queryFeatures(queryOptions) {
        const query = this._createQueryOption(queryOptions)
        let promise
        if (this.url.indexOf('/igs/rest/mrfs/layer') > -1) {
          query.gdbp = this.gdbp
          promise = this._featureServer.queryFeaturesInLayers(query)
        } else {
          promise = this._featureServer.queryFeatures(query)
        }

        return promise.then((res) => {
          const data = res.data
          if (!data) Log.error('添加图层视图失败，未获取到请求数据')
          const featureSet = data.featureSet
          // 设置要素
          this._setFeatureSetSpatialReference(featureSet)
          if (!featureSet) Log.error('添加图层视图失败，未获取到几何要素信息')
          return featureSet
        })
      }

      /**
       * 查询要素数量,仅支持igs2.0
       * @param {Object} queryOptions 参考此接口的入参{@link FeatureServer#queryFeatures}
       * @return {Promise<Number>}
       * @example <caption><h7 id='queryFeaturesCount'>查询要素数量</h7></caption>
       * igsFeatureLayer.queryFeaturesCount({
       *   // 图层id
       *   sublayerId: '0',
       *   // where语句
       *   where: "NAME='天门市'"
       * }).then((result) => {
       *   console.log('查询结果:', result)
       * })
       */
      queryFeaturesCount(queryOptions) {
        if (this.gdbp) {
          Log.error('gdbp模式不支持查询要素条数,igs1.0不支持此操作')
          return
        }
        const query = this._createQueryOption(queryOptions)
        query.returnCountOnly = true
        return this._featureServer.queryFeatures(query).then((res) => {
          const data = res.data
          if (!data) Log.error('添加图层视图失败，未获取到请求数据')
          return data.count
        })
      }

      /**
       * 通过传入的json构造并返回一个新的几何对象<a id='fromJSON'></a>
       * @param {Object} [json] JSON对象
       * @example <caption><h7>通过传入的json构造并返回一个新的几何对象</h7></caption>
       * const json = {
       *   // 服务基地址
       *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/FeatureServer',
       * }
       * const igsFeatureLayer = new Zondy.Layer.IGSFeatureLayer.fromJSON(json)
       */
      static fromJSON(json) {
        json = jsonClone(json)
        const _layer = new IGSFeatureLayer(json)

        const _labelingInfo = []
        for (let i = 0; i < json.labelingInfo.length; i++) {
          _labelingInfo.push(new LabelClass(json.labelingInfo[i]))
        }
        _layer.labelingInfo = _labelingInfo

        return _layer
      }

      /**
       * @description 转换为json对象
       * @return {Object} json对象
       */
      toJSON() {
        const json = super.toJSON()
        json.url = this.url
        json.gdbp = this.gdbp
        json.outFields = this.outFields
        json.capabilities = this.capabilities
        json.sublayerId = this.sublayerId
        json.labelsVisible = this.labelsVisible
        json.renderMode = this.renderMode
        json.definitionExpression = this.definitionExpression

        const _labelingInfo = []
        for (let i = 0; i < this.labelingInfo.length; i++) {
          _labelingInfo.push(toJSON(this.labelingInfo[i], LabelClass))
        }
        json.labelingInfo = _labelingInfo

        return json
      }

      _createQueryOption(queryOptions) {
        let query = defaultValue(queryOptions, {})
        // eslint-disable-next-line prefer-object-spread
        query = Object.assign(
          {
            layerId: `${this.sublayerId}`,
            where: this.definitionExpression || '',
            supportArc3: this.supportArc3
          },
          query
        )
        return query
      }

      _processDataInfo(self, data) {
        // 解析要素字段
        if (!data) throw new Error('要素服务源数据请求失败')
        // 解析要素坐标系
        if (!self._spatialReference) {
          const srsName = data.srsName || data.SRSName
          // 2.0 数据坐标系
          if (data.spatialReference) {
            self._spatialReference = SpatialReference.fromJSON(
              data.spatialReference
            )
            // 1.0 数据坐标系
          } else if (srsName && epsg.find((v) => v.name === srsName)) {
            const epsgObject = epsg.find((v) => v.name === srsName)
            self._spatialReference = new SpatialReference({
              wkid: epsgObject.id,
              wkt: epsgObject.strProject
            })
          } else {
            self._spatialReference = new SpatialReference('EPSG:4326')
          }
        }

        if (isNull(self.extent)) {
          const extent = self.extent || data.extent || data.Range
          if (extent) {
            // 2.0 extent
            self.extent = new Extent({
              xmin: extent.xmin,
              ymin: extent.ymin,
              xmax: extent.xmax,
              ymax: extent.ymax,
              spatialReference: self._spatialReference
            })
          }
        }
        // 解析服务器提供的能力
        if (data.capabilities) {
          self.capabilities = Array.isArray(data.capabilities)
            ? data.capabilities
            : [data.capabilities]
        }
        // 解析要素字段
        if (data.fields && Array.isArray(data.fields)) {
          data.fields.forEach((field) => {
            self.outFields.push(field.name)
          })
        }
        // 解析要素集类型
        if (data.geometryType) {
          self.geometryType = data.geometryType
        } else if (data.GeomType) {
          self.geometryType = data.GeomType
        }

        // 解析渲染器
        // if (data.drawingInfo) {
        //   data.drawingInfo.renderer.field = data.drawingInfo.renderer.field1
        //   self.renderer = formatIGSRenderer(data.drawingInfo.renderer)
        // }
      }

      /**
       * @private
       * @description: 解决要素集不存在坐标系或服务未返回坐标系问题
       * @return {*}
       */
      _setFeatureSetSpatialReference(featureSet) {
        if (!featureSet) {
          Log.error('服务器请求错误,未返回FeatureSet数据，请检查服务状态')
        }
        const self = this
        if (
          !featureSet.spatialReference ||
          (featureSet.spatialReference && featureSet.spatialReference.wkid === 0)
        ) {
          featureSet.spatialReference = self._spatialReference
          featureSet.features.forEach((feature) => {
            if (feature && feature.geometry) {
              feature.geometry.spatialReference = self._spatialReference
            }
          })
        }
      }
    }

    Object.defineProperties(IGSFeatureLayer.prototype, {
      /**
       * 要素过滤条件，类似sql语句
       * @member {String} IGSFeatureLayer.prototype.definitionExpression
       */
      definitionExpression: {
        get() {
          return this._definitionExpression
        },
        set(value) {
          this._definitionExpression = value
          if (this.loaded) {
            this.refresh()
          }
        }
      }
    })

    Zondy.Layer.IGSFeatureLayer = IGSFeatureLayer
    export default IGSFeatureLayer