    import { Zondy, ElevationInfo } from '../../../base'
    import {defaultValue, Log, getGUID, toJSON} from '../../../util'
    import { WFSServer } from '../../../service'
    import { LayerType, LoadStatus, GeometryType } from '../../../base/enum'
    import { Extent, SpatialReference } from '../../../base/geometry'
    import OGCLayer from './OGCLayer'
    import { BaseRenderer } from '../../renderer'
    import LabelClass from '../../support/LabelClass'
    import {jsonClone} from '../../../util/Utils';
    import {getEPSGCodeFromOGCSupportedCRSString} from '../support/Utils';

    /**
     * WFS图层，<br>
     * 目前二维和三维上支持4326(包括4490，4214以及4610)，3857以及EPSG支持的自定义坐标系，WFS服务会自动读取元信息上的坐标系，不需要用户指定
     * <br><br>[ES5引入方式]：<br/>
     * Zondy.Layer.WMTSLayer() <br/>
     * [ES6引入方式]：<br/>
     * import { WMTSLayer } 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 WFSLayer
     * @moduleEX LayerModule
     * @extends OGCLayer
     * @fires Layer#图层加载完毕事件
     * @fires Layer#图层销毁完毕事件
     * @fires Layer#图层更新完毕事件
     * @fires Layer#图层显隐更新完毕事件
     * @fires Layer#图层透明度更新完毕事件
     * @fires Layer#图层刷新完毕事件
     * @param {Object} options 构造参数
     * @param {String} [options.url] 服务基地址，目前支持的服务如下：<br/>
     * 1、IGS2.0的WFS服务：http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer，示例如下：<br/>
     * <a href='#add-WFSLayer'>[1、添加IGS要素图层-不指定图层]</a><br/>
     * <a href='#WFSLayer-sublayerId'>[2、添加IGS要素图层-指定图层名称]</a><br/>
     * 删除图层方法：<a href='#remove-layer'>[删除图层]</a>
     * @param {String} [options.sublayerId] WFS服务的子图层名称，不指定则默认区该服务的第一个子图层
     * @param {String} [options.id] 图层id，不给则给一个随机的id
     * @param {Number} [options.index] 图层顺序，参考示例：<a href='#index'>[图层顺序]</a>
     * @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 {Object} [options.renderer] 渲染样式，详细的几何类型样式请参考支持的渲染样式文档，所有支持的渲染样式如下：<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 {Boolean} [options.labelsVisible = false] 是否开启动态注记，仅支持三维场景
     * @param {Array<LabelClass>} [options.labelingInfo = []] 注记样式数组，可以和renderer同时启用，默认取数组的第一个样式，
     * 仅支持三维场景，参考示例：<a href='#add-labelingInfo'>[注记样式]</a><br/>
     * @param {ElevationInfo} [options.elevationInfo] 高程样式，仅支持三维场景
     *
     * @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-WFSLayer'>添加IGS2.0的WFS图层-不指定图层示例</h7></caption>
     * // ES5引入方式
     * const { Map, MapView, SceneView } = Zondy
     * const { WFSLayer } = Zondy.Layer
     * // ES6引入方式
     * import { Map, MapView, SceneView, WFSLayer } from "@mapgis/webclient-common"
     * // 初始化图层管理容器
     * const map = new Map();
     * // 初始化二维地图视图对象
     * const mapView = new MapView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 初始化三维地图视图对象
     * const mapView = new SceneView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 初始化WFS图层
     * const wfsLayer = new WFSLayer({
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer'
     * })
     * // 添加到容器中
     * map.add(wfsLayer)
     *
     * @example <caption><h7 id='WFSLayer'>添加IGS2.0的WFS图层-不指定图层示例</h7></caption>
     * // ES5引入方式
     * const { Map, MapView, SceneView } = Zondy
     * const { WFSLayer } = Zondy.Layer
     * // ES6引入方式
     * import { Map, MapView, SceneView, WFSLayer } from "@mapgis/webclient-common"
     * // 初始化图层管理容器
     * const map = new Map();
     * // 初始化二维地图视图对象
     * const mapView = new MapView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 初始化三维地图视图对象
     * const mapView = new SceneView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 初始化WFS图层
     * const wfsLayer = new WFSLayer({
     *   // 服务基地址，当不指定图层名称时，默认查询第一个子图层
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer'
     * })
     * // 添加到容器中
     * map.add(wfsLayer)
     *
     * @example <caption><h7 id='WFSLayer-sublayerId'>添加IGS2.0的WFS图层-指定图层名称示例</h7></caption>
     * // ES5引入方式
     * const { Map, MapView, SceneView } = Zondy
     * const { WFSLayer } = Zondy.Layer
     * // ES6引入方式
     * import { Map, MapView, SceneView, WFSLayer } from "@mapgis/webclient-common"
     * // 初始化图层管理容器
     * const map = new Map();
     * // 初始化二维地图视图对象
     * const mapView = new MapView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 初始化三维地图视图对象
     * const mapView = new SceneView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 初始化WFS图层
     * const wfsLayer = new WFSLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer',
     *   // 通过图层名称指定要查询的图层
     *   sublayerId: 'Map_Hubei4326:t2'
     * })
     * // 添加到容器中
     * map.add(wfsLayer)
     *
     * @example <caption><h7 id='UniqueValueRenderer'>单值专题图</h7></caption>
     * // ES5引入方式
     * const { WFSLayer } = Zondy.Layer
     * const { UniqueValueRenderer } = Zondy.Renderer
     * const { SimpleFillSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import { WFSLayer, UniqueValueRenderer, SimpleFillSymbol, Color } from "@mapgis/webclient-common"
     * const wfsLayer = new WFSLayer({
     *   // 服务基地址，当不指定图层名称时，默认查询第一个子图层
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer',
     *   // 设置渲染样式-单值专题图
     *   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)'
     *         })
     *       }
     *     ]
     *   })
     * })
     *
     * @example <caption><h7 id='ClassBreakRenderer'>分段专题图</h7></caption>
     * // ES5引入方式
     * const { WFSLayer } = Zondy.Layer
     * const { ClassBreakRenderer } = Zondy.Renderer
     * const { SimpleLineSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import { WFSLayer, UniqueValueRenderer, SimpleLineSymbol, Color } from "@mapgis/webclient-common"
     * const wfsLayer = new WFSLayer({
     *   // 服务基地址，当不指定图层名称时，默认查询第一个子图层
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer',
     *   // 设置渲染样式-分段专题图
     *   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 Color(123, 124, 110),
     *           // 线宽
     *           width: 3
     *         })
     *       }
     *     ]
     *   })
     * })
     *
     * @example <caption><h7 id='SimpleRenderer'>统一专题图</h7></caption>
     * // ES5引入方式
     * const { WFSLayer } = Zondy.Layer
     * const { SimpleRenderer } = Zondy.Renderer
     * const { SimpleLineSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import { WFSLayer, SimpleRenderer, SimpleLineSymbol, Color } from "@mapgis/webclient-common"
     * const wfsLayer = new WFSLayer({
     *   // 服务基地址，当不指定图层名称时，默认查询第一个子图层
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer',
     *   // 设置渲染样式-统一专题图
     *   renderer: new SimpleRenderer({
     *     // 因为该数据的几何类型为区，因此设置区样式
     *     symbol: new SimpleFillSymbol({
     *       // 填充颜色
     *       color: new Color(255, 0, 0),
     *       // 外边线样式
     *       outline: new SimpleLineSymbol({
     *         // 线颜色
     *         color: new Color(0, 0, 0),
     *         // 线宽度
     *         width: 1
     *       })
     *     })
     *   })
     * })
     *
     * @example <caption><h7 id='add-labelingInfo'>启用注记</h7></caption>
     * // ES5引入方式
     * const { LabelClass, Color, Font } = Zondy
     * const { TextSymbol } = Zondy.Symbol
     * const { WFSLayer } = Zondy.Layer
     * // ES6引入方式
     * import { LabelClass, Color, Font, TextSymbol, WFSLayer } 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"
     *     })
     *   })
     * })
     * // 初始化WFS图层
     * const wfsLayer = new WFSLayer({
     *   // 服务
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer',
     *   // 可在此处设置渲染样式
     *   renderer: {},
     *   // 启用注记
     *   labelsVisible: true,
     *   // 设置注记样式
     *   labelingInfo: [labelClass]
     * })
     * // 添加到容器中
     * map.add(wfsLayer)
     *
     * @example <caption><h7 id='index'>图层顺序</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer, WFSLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer, WFSLayer } from "@mapgis/webclient-common"
     * // 加载地图图片图层，设置index为3
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *   // 设置index
     *   index: 3
     * });
     * map.add(igsMapImageLayer)
     *
     * // 加载完毕后，更改图层顺序
     * map.reorder(layer, '要移动到的index');
     *
     * // 初始化WFS图层
     * const wfsLayer = new WFSLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer',
     *   // 设置index
     *   index: 4
     * })
     * // 添加到容器中
     * map.add(wfsLayer)
     *
     * @example <caption><h7 id='opacity'>设置图层透明度</h7></caption>
     * // ES5引入方式
     * const { WFSLayer } = Zondy.Layer
     * // ES6引入方式
     * import { WFSLayer } from "@mapgis/webclient-common"
     * // 初始化时指定透明度
     * const wfsLayer = new WFSLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer',
     *   // 设置opacity
     *   opacity: 1
     * })
     * // 添加到容器中
     * map.add(wfsLayer)
     *
     * // 加载完毕后设置透明度
     * wfsLayer.opacity = 0.5
     *
     * @example <caption><h7 id='visible'>设置图层可见性</h7></caption>
     * // ES5引入方式
     * const { WFSLayer } = Zondy.Layer
     * // ES6引入方式
     * import { WFSLayer } from "@mapgis/webclient-common"
     * // 在初始化时设置
     * const wfsLayer = new WFSLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer',
     *   // 设置图层可见性
     *   visible: true
     * })
     * // 添加到容器中
     * map.add(wfsLayer)
     *
     * // 加载完毕后设置可见性
     * wfsLayer.visible = false
     */
    class WFSLayer extends OGCLayer {
      constructor(options) {
        super(options)
        options = defaultValue(options, {})
        this.type = LayerType.wfs
        this.url = defaultValue(options.url, '')
        this.id = defaultValue(options.id, getGUID())
        this._spatialReference = undefined
        /**
         * renderer渲染器
         * @member {String} WFSLayer.prototype.renderer
         */
        this.renderer = this._decorate(
          'renderer',
          options.renderer,
          BaseRenderer,
          BaseRenderer.fromJSON
        )
        /**
         * 服务数据库的所有字段名数组
         * @readonly
         * @member {Array<String>} WFSLayer.prototype.outFields
         */
        this.outFields = []
        /**
         * 高程信息
         * @member {ElevationInfo} WFSLayer.prototype.elevationInfo
         */
        this.elevationInfo = defaultValue(
          options.elevationInfo,
          new ElevationInfo()
        )
        /**
         * 服务元数据的几何类型
         * @readonly
         * @member {String} WFSLayer.prototype.geometryType
         */
        this.geometryType = GeometryType.geometry
        /**
         * 图层id
         * @member {String} WFSLayer.prototype.sublayerId
         */
        this.sublayerId = defaultValue(options.sublayerId, '')
        /**
         * wfsCapabilities信息
         * @readonly
         * @member {String} WFSLayer.prototype.wfsCapabilities
         */
        this.wfsCapabilities = defaultValue(options.wfsCapabilities, '')
        /**
         * 是否开启动态注记,仅支持三维动态注记渲染
         * @member {Boolean} WFSLayer.prototype.labelsVisible
         */
        this.labelsVisible = defaultValue(options.labelsVisible, false)
        /**
         * 注记样式数组，默认取数组的第一个样式，仅支持三维动态注记渲染
         * @member {Array<LabelClass>} WFSLayer.prototype.labelingInfo
         */
        this.labelingInfo = defaultValue(options.labelingInfo, [])
        // wfs服务
        this._wfsServer = new WFSServer({
          url: this.url
        })
      }

      /**
       * 加载图层资源<a id='load'></a>
       * @example <caption><h7>不加载图层，仅获取图层信息</h7></caption>
       * // ES5引入方式
       * const { WFSLayer } = Zondy.Layer
       * // ES6引入方式
       * import { WFSLayer } from "@mapgis/webclient-common"
       * // 初始化图层
       * const wfsLayer = new WFSLayer({
       *   // 服务基地址
       *   url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WFSServer'
       * });
       * wfsLayer.load().then((result) => {
       *   // 获取完图层信息
       *   console.log(wfsLayer)
       * })
       */
      load() {
        return super.load()
      }

      /**
       * 子类加载服务端元信息的方法
       * @private
       * */
      _load() {
        const self = this
        return this._wfsServer
          .queryServerInfo()
          .then((result) => {
            Log.info('WFS信息查询成功:', result)
            const data = result.data
            if (data) {
              self.wfsCapabilities = data
              const features = data.featureTypeList
              // 初始化图层信息
              if (features.length > 0) {
                const feature = features[0]

                // 获取坐标系
                const _epsgCode = getEPSGCodeFromOGCSupportedCRSString(
                  feature.defaultSRS
                )
                if (_epsgCode) {
                  self._spatialReference = new SpatialReference({
                    wkid: _epsgCode
                  })
                } else {
                  self._spatialReference = new SpatialReference({
                    wkid: 4326
                  })
                }

                if (!self.sublayerId && feature.name) {
                  self.sublayerId = feature.name
                }

                if (!self.extent) {
                  const feature = features.find((v) => v.name === self.sublayerId)
                  if (!feature) {
                    Log.error('未查询到要素图层，请检查图层名称是否正确')
                  }
                  // 解析extent
                  if (feature.WGS84BoundingBox) {
                    const UpperCorner = feature.WGS84BoundingBox.UpperCorner
                    const lowerCorner = feature.WGS84BoundingBox.lowerCorner
                    let minX
                    let minY
                    let maxX
                    let maxY
                    if (UpperCorner) {
                      const arr = UpperCorner.split(' ').map((v) => parseFloat(v))
                      maxX = arr[0]
                      maxY = arr[1]
                    }
                    if (lowerCorner) {
                      const arr = lowerCorner.split(' ').map((v) => parseFloat(v))
                      minX = arr[0]
                      minY = arr[1]
                    }
                    self.extent = new Extent({
                      xmin: minX,
                      ymin: minY,
                      xmax: maxX,
                      ymax: maxY,
                      spatialReference: self._spatialReference
                    })
                  }
                }
              }

              return new Promise((resolve) => {
                self.loadStatus = LoadStatus.loaded
                self.loaded = true
                resolve(self)
              })
            } else {
              Log.error('wfs请求数据为空')
            }
          })
          .catch((result) => {
            self.loadStatus = Log.error('WMS信息查询失败:', result)
          })
      }

      /**
       * 指定图层的要素查询<a id='queryFeatures'></a>
       * @param {Object} queryOptions 参考此接口的入参{@link WFSServer#queryFeatures}
       * @return {Promise<FeatureSet>}
       * @example <caption><h7>指定图层的要素查询</h7></caption>
       * wfsLayer.queryFeatures({
       *   // 图层id
       *   layerId: '0',
       *   // where语句
       *   where: "查询条件"
       * }).then((result) => {
       *   console.log('查询结果:', result)
       * })
       */
      queryFeatures(queryOptions) {
        const query = this._createQueryOption(queryOptions)
        return this._wfsServer.queryFeatures(query).then((res) => {
          const data = res.data
          if (!data) Log.error('添加图层视图失败，未获取到请求数据')
          const featureSet = data.featureSet
          if (!featureSet) Log.error('添加图层视图失败，未获取到几何要素信息')
          return featureSet
        })
      }

      /**
       * 查询要素数量<a id='queryFeaturesCount'></a>
       * @param {Object} queryOptions 参考此接口的入参{@link WFSServer#queryFeatures}
       * @return {Promise<Number>}
       * @example <caption><h7>查询要素数量</h7></caption>
       * igsFeatureLayer.queryFeaturesCount({
       *   // 图层id
       *   layerId: '0',
       *   // where语句
       *   where: "查询条件"
       * }).then((result) => {
       *   console.log('查询结果:', result)
       * })
       */
      queryFeaturesCount(queryOptions) {
        const query = this._createQueryOption(queryOptions)
        query.returnCountOnly = true
        return this._wfsServer.queryFeatures(query).then((res) => {
          const data = res.data
          if (!data) Log.error('添加图层视图失败，未获取到请求数据')
          return data.count
        })
      }

      _createQueryOption(queryOptions) {
        let query = defaultValue(queryOptions, {})
        // eslint-disable-next-line prefer-object-spread
        query = Object.assign(
          {
            typename: this.sublayerId,
            version: this.version
          },
          query
        )
        return query
      }

      /**
       * 通过传入的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}/WFSServer'
       * }
       * const wfsLayer = new Zondy.Layer.WFSLayer.fromJSON(json)
       */
      static fromJSON(json) {
        json = jsonClone(json)
        const _layer = new WFSLayer(json)
        _layer.spatialReference = SpatialReference.fromJSON(json.spatialReference)
        _layer.renderer = BaseRenderer.fromJSON(json.renderer)
        _layer.elevationInfo = new ElevationInfo(json.elevationInfo)
        if (json.labelingInfo && json.labelingInfo instanceof Array) {
          for (let i = 0; i < json.labelingInfo.length; i++) {
            _layer.labelingInfo[i] = new LabelClass(json.labelingInfo[i])
          }
        }

        return _layer
      }

      toJSON() {
        const _json = super.toJSON()

        _json.url = this.url
        _json.sublayerId = this.sublayerId
        _json.geometryType = this.geometryType
        _json.wfsCapabilities = this.wfsCapabilities
        _json.labelsVisible = this.labelsVisible
        _json.spatialReference = toJSON(this._spatialReference, SpatialReference)
        _json.renderer = toJSON(this.renderer, BaseRenderer)
        _json.outFields = this.outFields
        _json.elevationInfo = toJSON(this.elevationInfo, ElevationInfo)
        const _labelingInfo = []
        if (this.labelingInfo && this.labelingInfo instanceof Array) {
          for (let i = 0; i < this.labelingInfo.length; i++) {
            _labelingInfo.push(toJSON(this.labelingInfo[i], LabelClass))
          }
        }
        _json.labelingInfo = _labelingInfo

        return _json
      }
    }

    Zondy.Layer.WFSLayer = WFSLayer
    export default WFSLayer