    import { MapImageLayer } from '../baseLayer'
    import { Zondy, Collection, Projection } from '../../../base'
    import { LayerEventType, LayerType, LoadStatus } from '../../../base/enum'
    import { defaultValue, isNull, Log } from '../../../util'
    import { MapServer } from '../../../service'
    import { Extent, SpatialReference } from '../../../base/geometry'
    import IGSMapImageSubLayer from './IGSMapImageSubLayer'
    import { fireEvent, setSublayer } from '../Utils'

    /**
     * IGS地图图片图层，<br/>
     * 支持IGS1.0和2.0两个服务版本，支持自定义坐标系，当IGS版本是1.0时，需要手动设置图层坐标系，当IGS版本是2.0时，会自动读取元信息上的坐标系，不需要用户指定<br/>
     * <br><br>[ES5引入方式]：<br/>
     * Zondy.Layer.IGSMapImageLayer() <br/>
     * [ES6引入方式]：<br/>
     * import { IGSMapImageLayer } 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 IGSMapImageLayer
     * @moduleEX LayerModule
     * @classdesc IGS地图图层
     * @extends MapImageLayer
     * @fires Layer#图层加载完毕事件
     * @fires Layer#图层销毁完毕事件
     * @fires Layer#图层更新完毕事件
     * @fires Layer#图层显隐更新完毕事件
     * @fires Layer#图层透明度更新完毕事件
     * @fires Layer#图层顺序更新完毕事件
     * @fires Layer#图层刷新完毕事件
     * @fires IGSMapImageLayer#子图层显隐更新完毕事件
     * @param {Object} options 构造参数
     * @param {String} [options.url] 服务基地址，可以在末尾指定子图层id，若指定，则仅显示该子图层，例如：http://{服务基地址}/子图层id，<a href='#show-sublayer'>[仅显示指定子图层]<br/>
     * @param {String} [options.httpMethod="GET"] HTTP请求方式，默认为GET请求
     * IGS1.0的服务为：http://{ip}:6163/igs/rest/mrms/docs/{serviceName}，暂时无法从元信息中获取坐标系，请自行指定图层坐标系，参考示例：<a href='#igs-1'>[IGS1.0的地图图片图层示例]</a><br/>
     * IGS2.0的服务为：http://{ip}:{port}/igs/rest/services/{folder}/{serviceName}/MapServer，参考示例：<a href='#igs-2'>[IGS2.0的地图图片图层示例]</a><br/>
     * 删除图层方法：<a href='#remove-layer'>[删除图层]</a>
     * @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 {Array<Collection>} [options.sublayers = []]  指定子图层参数，可设置子图层的可见性，顺序以及子图层渲染参数，其中图层可见性支持IGS1.0以及2.0服务，
     * 子图层顺序以及专题图参数仅支持IGS2.0服务，目前子图层支持的专题图如下：<br/>
     * [1、单值专题图]{@link UniqueValueRenderer}<br/>
     * [2、分段专题图]{@link ClassBreakRenderer}<br/>
     * 参考示例：<br/>
     * <a href='#showAllSubLayers'>[1、显示所有子图层]</a><br/>
     * <a href='#showSubLayersById'>[2、根据id显示子图层]</a><br/>
     * <a href='#showSubLayers-method'>[3、通过方法设置子图层显隐]</a><br/>
     * <a href='#showSubLayers-property'>[4、通过修改子图参数，设置子图层显隐]</a><br/>
     * <a href='#setLayerIndex'>[5、设置子图层顺序]</a><br/>
     * <a href='#setLayerIndex-method'>[6、通过方法设设置子图层顺序]</a><br/>
     * <a href='#setLayerIndex-property'>[7、通过修改子图参数，设置子图层顺序]</a><br/>
     * <a href='#setLayerRenderer-unique'>[8、设置子图层专题图-单值专题图]</a><br/>
     * <a href='#setLayerRenderer-break'>[9、设置子图层专题图-分段专题图]</a><br/>
     * <a href='#setLayerRenderer-method'>[10、通过方法设置子图层专题图]</a><br/>
     * <a href='#setLayerRenderer-property'>[11、通过修改子图参数，设置子图层专题图]</a><br/>
     * @param {SpatialReference} [options.spatialReference] 图层坐标系，支持4326(包含4490，4214以及4610)、3857以及EPSG上的自定义坐标系，坐标系默认从元信息中获取，也可指定坐标系，
     * 参考示例：<a href='#spatialReference'>[设置图层坐标系]</a>
     * @param {Number} [options.imageWidth = 256] 图片宽度，单位px，参考示例：<a href='#tileSize'>[设置图片大小]</a>
     * @param {Number} [options.imageHeight = 256] 图片高度，单位px，参考示例：<a href='#tileSize'>[设置图片大小]</a>
     * @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.imageTransparency = true] 图片中没有数据的地方是否透明，默认为true，即透明
     * @param {Polygon|Extent|Circle|null} [options.clippingArea = null] 图层空间裁剪范围，仅支持多边形裁剪、矩形裁剪、圆形裁剪
     *
     * @summary <h5>支持如下方法：</h5>
     * <a href='#load'>[1、加载图层资源]</a><br/>
     * <a href='#findSublayerById'>[2、根据子图层id查询子图层]</a><br/>
     * [3、刷新图层]{@link Layer#refresh}<br/>
     * <a href='#fetchImage'>[4、根据范围和大小获取image标签]</a><br/>
     * <a href='#createServiceSublayers'>[5、创建一个该服务的子图层克隆对象]</a><br/>
     * <a href='#getImageUrl'>[6、根据参数获取图片的url]</a><br/>
     * <a href='#setSubLayer'>[7、更新子图层]</a><br/>
     * <a href='#toJSON'>[8、将图层转为json对象]</a><br/>
     * <a href='#clone'>[9、克隆图层对象]</a><br/>
     *
     * @example <caption><h7 id='igs-1'>IGS1.0的地图图片图层示例</h7></caption>
     * // ES5引入方式
     * const { Map,MapView,SpatialReference } = Zondy
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { Map,MapView,SpatialReference,IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 初始化图层管理容器
     * const map = new Map();
     * // 初始化地图视图对象
     * const mapView = new MapView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 添加图层
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:6163/igs/rest/mrms/docs/{serviceName}',
     *   // IGS1.0服务，暂时无法从元信息中获取坐标系，请自行指定图层坐标系
     *   spatialReference: new SpatialReference({
     *     wkid: 4326
     *   })
     * });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7 id='igs-2'>IGS2.0的地图图片图层示例</h7></caption>
     * // ES5引入方式
     * const { Map,MapView } = Zondy
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { Map,MapView,IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 初始化图层管理容器
     * const map = new Map();
     * // 初始化地图视图对象
     * const mapView = new MapView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 添加图层
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer'
     * });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7 id='spatialReference'>指定地图图片图层的坐标系示例</h7></caption>
     * // ES5引入方式
     * const { SpatialReference} = Zondy
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { SpatialReference,IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 添加图层
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *   // 自定义坐标新
     *   spatialReference: new SpatialReference({
     *     // 指定的wkid号，可在https://epsg.io/网站查询
     *     wkid: '指定的wkid号'
     *   })
     * });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7 id='tileSize'>IGS2.0的地图图层示例 - 设置图片大小</h7></caption>
     *  // ES5引入方式
     * const { Map,MapView} = Zondy
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { Map,MapView,IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 初始化图层管理容器
     * const map = new Map();
     * // 初始化地图视图对象
     * const mapView = new MapView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 添加图层
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *   // 瓦片宽度
     *   imageWidth: 512,
     *   // 瓦片高度
     *   imageHeight: 512
     * });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7 id='showAllSubLayers'>显示所有子图层</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 添加图层
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *   // 当sublayers为空时显示所有子图层
     *   sublayers: []
     * });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7 id='showSubLayersById'>根据id显示子图层</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 添加图层
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *   // 根据id显示子图层
     *   sublayers: [
     *      {
     *        // 子图层id
     *        id: 1,
     *        // 显示子图层
     *        visible: true
     *      }
     *    ]
     * });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7 id='showSubLayers-method'>通过方法设置子图层显隐</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 添加图层
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer'
     * });
     * map.add(igsMapImageLayer);
     * // 通过方法设置子图层显隐
     * igsMapImageLayer.setSubLayer({
     *   id: 0,
     *   visible: false
     * })
     *
     * @example <caption><h7 id='showSubLayers-property'>通过修改子图参数，设置子图层显隐</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 添加图层
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer'
     * });
     * map.add(igsMapImageLayer);
     * // 根据id获取子图层
     * const subLayer = igsMapImageLayer.findSublayerById(0)
     * // 设置子图层显隐
     * subLayer.visible = false
     *
     * @example <caption><h7 id='setLayerIndex'>设置子图层顺序</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * const igsMapImageLayer = new IGSMapImageLayer({
     *    // 服务基地址
     *    url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *    // 设置子图层顺序
     *    sublayers: [{
     *      id: '0',
     *      index: 2
     *    },{
     *      id: '1',
     *      index: 1
     *    }]
     *  });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7 id='setLayerIndex-method'>通过方法设置子图层顺序</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * const igsMapImageLayer = new IGSMapImageLayer({
     *    // 服务基地址
     *    url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer'
     *  });
     * map.add(igsMapImageLayer);
     * // 设置子图层顺序
     * igsMapImageLayer.setSubLayer({
     *   // 子图层id
     *   id: '子图层id',
     *   // 子图层顺序
     *   index: 2
     * })
     *
     * @example <caption><h7 id='setLayerIndex-property'>通过修改子图参数，设置子图层顺序</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * const igsMapImageLayer = new IGSMapImageLayer({
     *    // 服务基地址
     *    url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer'
     *  });
     * map.add(igsMapImageLayer);
     * // 根据id获取子图层
     * const subLayer = igsMapImageLayer.findSublayerById(0)
     * // 设置子图层顺序
     * subLayer.index = 2
     *
     * @example <caption><h7 id='setLayerRenderer-unique'>设置子图层专题图-单值专题图</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * const { UniqueValueRenderer } = Zondy.Renderer
     * const { SimpleFillSymbol,SimpleLineSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import { IGSMapImageLayer,UniqueValueRenderer,SimpleFillSymbol,SimpleLineSymbol,Color  } from "@mapgis/webclient-common"
     * igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *   // 设置子图层专题图
     *   sublayers: [
     *      {
     *        // 子图层id
     *        id: '子图层id',
     *        // 专题图参数
     *        renderer: new UniqueValueRenderer({
     *          //字段名
     *          field: '你的字段名',
     *          // 默认符号，不在专题图指定范围内的会采用该样式，可不设置
     *          defaultSymbol: new SimpleFillSymbol({
     *            // 填充颜色
     *            color: 'rgba(1,1,252,0)',
     *            // 外边线样式
     *            outline: new SimpleLineSymbol({
     *              //线颜色
     *              color: new Color(255, 1, 0, 1),
     *              //线宽
     *              width: 1
     *            })
     *          }),
     *          //单值专题图字段样式
     *          uniqueValueInfos: [{
     *            //指定字段值
     *            value: "指定的值",
     *            //匹配到该值后的样式
     *            symbol: new SimpleFillSymbol({
     *              // 填充颜色
     *              color: 'rgba(1,1,252,1)',
     *              // 外边线样式
     *              outline: new SimpleLineSymbol({
     *                //线符号颜色
     *                color: new Color(255, 1, 0, 11),
     *                //线宽
     *                width: 1
     *                })
     *              })
     *            },{
     *              //指定字段值
     *              value: "指定的值",
     *              //匹配到该值后的样式
     *              symbol: new SimpleFillSymbol({
     *                // 填充颜色
     *                color: new Color(211, 111, 11, 1)
     *              })
     *            }]
     *        })
     *      }
     *   ]
     * });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7 id='setLayerRenderer-break'>设置子图层专题图-分段专题图</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * const { ClassBreakRenderer } = Zondy.Renderer
     * const { SimpleFillSymbol,SimpleLineSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import { IGSMapImageLayer,ClassBreakRenderer,SimpleFillSymbol,SimpleLineSymbol,Color  } from "@mapgis/webclient-common"
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *   // 设置子图层专题图
     *   sublayers: [
     *     {
     *      // 子图层id
     *      id: '子图层id',
     *      // 专题图参数
     *      renderer: new ClassBreakRenderer({
     *        //字段名
     *        field: '你的字段名',
     *        // 指定默认样式，不在专题图指定范围内的会采用该样式，可不设置
     *        defaultSymbol:  new SimpleFillSymbol({
     *          // 填充颜色
     *          color: 'rgba(222,1,252,1)',
     *          // 线符号样式
     *          outline: new SimpleLineSymbol({
     *            //线符号颜色
     *            color: new Color(255, 1, 0, 1),
     *            //线宽
     *            width: 1
     *          })
     *        }),
     *        //单值专题图字段样式
     *        classBreakInfos: [{
     *          // 最大范围
     *          maxValue: "最大范围",
     *          // 最小范围
     *          minValue: "最小范围",
     *          //匹配到该值后的样式
     *          symbol:  new SimpleFillSymbol({
     *            // 填充颜色
     *            color: 'rgba(1,1,252,1)',
     *            // 线符号样式
     *            outline: new SimpleLineSymbol({
     *              //线符号颜色
     *              color: new Color(255, 1, 0, 1),
     *              //线宽
     *              width: 1
     *            })
     *          })
     *        }]
     *      })
     *    }
     *  ]
     * });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7 id='setLayerRenderer-method'>通过方法设置子图层专题图</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * const { ClassBreakRenderer } = Zondy.Renderer
     * const { SimpleFillSymbol,SimpleLineSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import { IGSMapImageLayer,ClassBreakRenderer,SimpleFillSymbol,SimpleLineSymbol,Color  } from "@mapgis/webclient-common"
     * const igsMapImageLayer = new Zondy.Layer.IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer'
     * });
     * map.add(igsMapImageLayer);
     * // 设置子图层专题图
     * igsMapImageLayer.setSubLayer({
     *   // 子图层id
     *   id: '子图层id',
     *   // 专题图参数
     *   renderer: new Zondy.Renderer.ClassBreakRenderer({
     *     //字段名
     *     field: '你的字段名',
     *     // 指定默认样式，不在专题图指定范围内的会采用该样式，可不设置
     *     defaultSymbol:  new Zondy.Symbol.SimpleFillSymbol({
     *       // 填充颜色
     *       color: 'rgba(222,1,252,1)',
     *       // 线符号样式
     *       outline: new Zondy.Symbol.SimpleLineSymbol({
     *         //线符号颜色
     *         color: new Zondy.Color(255, 1, 0, 1),
     *         //线宽
     *         width: 1
     *       })
     *     }),
     *     //单值专题图字段样式
     *     classBreakInfos: [{
     *       // 最大范围
     *       maxValue: "最大范围",
     *       // 最小范围
     *       minValue: "最小范围",
     *       //匹配到该值后的样式
     *       symbol:  new Zondy.Symbol.SimpleFillSymbol({
     *         // 填充颜色
     *         color: 'rgba(1,1,252,1)',
     *         // 线符号样式
     *         outline: new Zondy.Symbol.SimpleLineSymbol({
     *           //线符号颜色
     *           color: new Zondy.Color(255, 1, 0, 1),
     *           //线宽
     *           width: 1
     *         })
     *       })
     *     }]
     *   })
     * })
     *
     * @example <caption><h7 id='setLayerRenderer-property'>通过修改子图参数，设置子图层专题图</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * const { ClassBreakRenderer } = Zondy.Renderer
     * const { SimpleFillSymbol,SimpleLineSymbol } = Zondy.Symbol
     * const { Color } = Zondy
     * // ES6引入方式
     * import { IGSMapImageLayer,ClassBreakRenderer,SimpleFillSymbol,SimpleLineSymbol,Color  } from "@mapgis/webclient-common"
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer'
     * });
     * map.add(igsMapImageLayer);
     * // 根据id获取子图层
     * const subLayer = igsMapImageLayer.findSublayerById(0)
     * // 设置子图专题图
     * subLayer.renderer = new ClassBreakRenderer({
     *     //字段名
     *     field: '你的字段名',
     *     // 指定默认样式，不在专题图指定范围内的会采用该样式，可不设置
     *     defaultSymbol:  new SimpleFillSymbol({
     *       // 填充颜色
     *       color: 'rgba(222,1,252,1)',
     *       // 线符号样式
     *       outline: new SimpleLineSymbol({
     *         //线符号颜色
     *         color: new Color(255, 1, 0, 1),
     *         //线宽
     *         width: 1
     *       })
     *     }),
     *     //单值专题图字段样式
     *     classBreakInfos: [{
     *       // 最大范围
     *       maxValue: "最大范围",
     *       // 最小范围
     *       minValue: "最小范围",
     *       //匹配到该值后的样式
     *       symbol:  new SimpleFillSymbol({
     *         // 填充颜色
     *         color: 'rgba(1,1,252,1)',
     *         // 线符号样式
     *         outline: new SimpleLineSymbol({
     *           //线符号颜色
     *           color: new Color(255, 1, 0, 1),
     *           //线宽
     *           width: 1
     *         })
     *       })
     *     }]
     *   })
     *
     * @example <caption><h7 id='opacity'>设置图层透明度</h7></caption>
     * // ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 初始化时设置
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *   // 设置透明度
     *   opacity: 1.0
     * });
     * map.add(igsMapImageLayer);
     * // 加载完成后设置
     * igsMapImageLayer.on('layerview-created', function (result) {
     *   console.log("加载完毕:", result.layer)
     *   // 视点跳转
     *   igsMapImageLayer.opacity = 0.5
     * })
     *
     * @example <caption><h7 id='visible'>显示或隐藏图层</h7></caption>
     * / ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 初始化时设置
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer',
     *   // 显示或隐藏图层
     *   visible: true
     * });
     * map.add(igsMapImageLayer);
     * // 加载完成后设置
     * igsMapImageLayer.on('layerview-created', function (result) {
     *   console.log("加载完毕:", result.layer)
     *   // 显示或隐藏图层
     *   igsMapImageLayer.visible = !igsMapImageLayer.visible
     * })
     *
     * @example <caption><h7 id='remove-layer'>删除图层</h7></caption>
     * map.remove(igsMapImageLayer)
     *
     * @example <caption><h7 id='show-sublayer'>显示指定子图层</h7></caption>
     * / ES5引入方式
     * const { IGSMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { IGSMapImageLayer  } from "@mapgis/webclient-common"
     * // 初始化时设置
     * const igsMapImageLayer = new IGSMapImageLayer({
     *   // 服务基地址，可指定子图层id
     *   url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer/{子图层id}',
     *   // 显示或隐藏图层
     *   visible: true
     * });
     * map.add(igsMapImageLayer);
     *
     * @example <caption><h7>添加arcgis的MapImage图层</h7></caption>
     * // 初始化图层管理容器
     * / ES5引入方式
     * const { Map ,SceneView,SpatialReference} = Zondy
     * const { IGSMapImageLayer} = Zondy.Layer
     * // ES6引入方式
     * import {Map ,SceneView,SpatialReference, IGSMapImageLayer  } from "@mapgis/webclient-common"
     * const map = new Map();
     * // 初始化地图视图对象
     * const sceneView = new SceneView({
     *   // 视图id
     *   viewId: "mapgis-3d-viewer",
     *   // 图层管理容器
     *   map: map
     * });
     * const arcgisMapImageLayer = new IGSMapImageLayer({
     *   url: 'https://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetWarm/MapServer',
     *   // 注意一个MapImage图层可能支持多个坐标系，这里指定4326坐标系
     *   spatialReference: new SpatialReference({
     *     wkid: 4326
     *   })
     * });
     * map.add(arcgisMapImageLayer);
     * // 图层加载完毕
     * igsMapImageLayer.on('layerview-created', function (result) {
     *   console.log("加载完毕:", result.layer)
     *   // 视点跳转
     *   sceneView.flyTo({
     *     extent: result.layer.extent
     *   })
     * })
     *
     * @example <caption><h7 id='index'>图层顺序</h7></caption>
     * // 加载完毕后，更改图层顺序
     * map.reorder(igsMapImageLayer, '要移动到的index');
     */

    /**
     * 子图层显隐更新完毕事件，请注意该事件是图层更新事件(layerview-update)的子事件
     * @event IGSMapImageLayer#子图层显隐更新完毕事件
     * @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 === 'sublayerVisible'){
     *       console.log("子图层显隐更新完毕事件:", event);
     *     }
     *   }
     * });
     */
    class IGSMapImageLayer extends MapImageLayer {
      constructor(options) {
        super(options)
        options = defaultValue(options, {})

        /**
         * 图层类型
         * @readonly
         * @member {String} IGSMapImageLayer.prototype.type
         */
        this.type = LayerType.igsMapImage
        // 空间裁剪范围
        this._clippingArea = defaultValue(options.clippingArea, null)
        this.description = 'IGS地图服务图层'

        // igs服务版本号，默认2.0
        this._igsVersion = '2.0'

        // 是否使用url后面的id，作为显示子图层的id
        this._urlLayerId = false

        // IGSMapImageLayer的真实URL
        const _urlArr = this.url.split('MapServer/')
        if (_urlArr.length === 1) {
          this._url = _urlArr[0]
        } else {
          this._url = `${_urlArr[0]}MapServer`
          this.layers = `show:${_urlArr[1]}`
          this._urlLayerId = true
        }

        // 地图服务对象
        this._mapServer = new MapServer({
          url: this._url
        })
      }

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

      /**
       * 子类请求服务资源的方法
       * @private
       * */
      _load() {
        const self = this
        return this._mapServer.queryServerInfo().then((result) => {
          Log.info('MapServer信息查询成功:', result)
          const data = result.data
          // 查询图层列表参数
          const queryLayerListOpts = {}

          // IGS2.0服务
          if (self.url.indexOf('/igs/rest/services/') > -1) {
            self._igsVersion = '2.0'
            self.documentInfo = defaultValue(self.documentInfo, data.documentInfo)
            self.mapName = defaultValue(self.mapName, data.mapName)
            if (self.capabilities.length === 0) {
              self.capabilities = data.childResources.split(',')
            }
            self.dynamicProjectionEnabled = defaultValue(
              self.dynamicProjectionEnabled,
              data.dynamicProjectionEnabled
            )

            if (!self._spatialReferenceSrc) {
              if (!isNull(data.spatialReference.wkt)) {
                self._spatialReferenceSrc = new SpatialReference({
                  wkt: data.spatialReference.wkt
                })
              }
              if (!isNull(data.spatialReference.wkid)) {
                self._spatialReferenceSrc = new SpatialReference({
                  wkid: data.spatialReference.wkid
                })
              }
            }

            if (!self._extentSrc && !isNull(data.extent)) {
              // 获取图层坐标系
              const _serverSP = new SpatialReference(data.spatialReference)
              // 设置可现实范围
              self._extentSrc = new Extent({
                xmin: data.extent.xmin,
                ymin: data.extent.ymin,
                xmax: data.extent.xmax,
                ymax: data.extent.ymax,
                spatialReference: _serverSP
              })
              // 如果用户输入的坐标系和图层的坐标系不一致，则将范围动态投影
              if (!_serverSP.equals(self._spatialReferenceSrc)) {
                self._extentSrc = Projection.project(
                  self._extentSrc,
                  self._spatialReferenceSrc
                )
              }
            }
          } // IGS1.0服务
          else {
            self._igsVersion = '1.0'
            queryLayerListOpts.mapIndex = '0'
            if (!self._spatialReferenceSrc) {
              Log.error('IGS1.0服务必须设置参考系')
            }
            if (
              !self._extentSrc &&
              !isNull(data.xMin) &&
              !isNull(data.yMin) &&
              !isNull(data.xMax) &&
              !isNull(data.yMax)
            ) {
              self._extentSrc = new Extent({
                xmin: data.xMin,
                ymin: data.yMin,
                xmax: data.xMax,
                ymax: data.yMax,
                spatialReference: self._spatialReferenceSrc
              })
            }
            self.mapName = data.name
          }

          return self._mapServer
            .queryLayerList(queryLayerListOpts)
            .then((layerList) => {
              Log.info('子图层信息查询成功:', layerList)
              // 清空子图层
              self.allSublayers.items = []

              let sublayers = []
              // IGS2.0服务
              if (self._igsVersion === '2.0') {
                sublayers = layerList.data.layers
              } else {
                sublayers = layerList.data
                for (let i = 0; i < sublayers.length; i++) {
                  sublayers[i].visible = sublayers[i].State === 'Visible'
                  sublayers[i].index = sublayers[i].LayerIndex
                  sublayers[i].type =
                    sublayers[i].GeomType === 'Unknown'
                      ? 'Group'
                      : sublayers[i].GeomType
                }
              }

              // 更新所有图层信息
              for (let i = 0; i < self.sublayers.length; i++) {
                self._updateLayerInfo(sublayers, self.sublayers[i])
              }
              // 初始化所有子图层集合
              self._sublayers = new Collection()
              for (let i = 0; i < sublayers.length; i++) {
                const _subLayer = new IGSMapImageSubLayer(sublayers[i])
                _subLayer.layer = self
                self._sublayers.add(_subLayer)
                self.allSublayers.add(_subLayer)
                if (
                  sublayers[i].children &&
                  sublayers[i].children instanceof Array
                ) {
                  self._initAllSubLayers(sublayers[i].children)
                }
              }
              // 设置子图层显隐
              self._setLayers()
              // 图层信息加载完毕
              self.loadStatus = LoadStatus.loaded
              self.loaded = true
              return new Promise((resolve) => {
                resolve(self)
              })
            })
        })
      }

      /**
       * @description 转换为json对象
       * @return {Object} json对象
       */
      toJSON() {
        const _json = super.toJSON()
        _json.description = this.description
        _json.documentInfo = this.documentInfo

        return _json
      }

      /**
       * 用本地的子图层信息，更细服务端子图层信息
       * @private
       * @param {Array} serverSubLayers 服务端图层信息数组，有子图层
       * @param {Object} clientSubLayer 客户端单个图层信息
       * */
      _updateLayerInfo(serverSubLayers, clientSubLayer) {
        for (let i = 0; i < serverSubLayers.length; i++) {
          if (String(serverSubLayers[i].index) === String(clientSubLayer.id)) {
            serverSubLayers[i] = Object.assign(serverSubLayers[i], clientSubLayer)
          }
          if (serverSubLayers[i].children) {
            this._updateLayerInfo(serverSubLayers[i].children, clientSubLayer)
          }
        }
      }

      /**
       * 通过服务端图层信息，初始化所有子图层集合
       * @private
       * @param {Array} sublayers 服务端图层信息数组
       * */
      _initAllSubLayers(sublayers) {
        for (let i = 0; i < sublayers.length; i++) {
          sublayers[i].layer = this
          this.allSublayers.add(new IGSMapImageSubLayer(sublayers[i]))
          if (sublayers[i].children && sublayers[i].children instanceof Array) {
            this._initAllSubLayers(sublayers[i].children)
          }
        }
      }

      /**
       * 根据子图层id查询子图层<a id='findSublayerById'></a>
       * @param {String} id 子图层id
       * @return Object 子图层信息
       * */
      findSublayerById(id) {
        if (this.loadStatus === LoadStatus.loaded && this.allSublayers) {
          for (let i = 0; i < this.allSublayers.items.length; i++) {
            if (String(this.allSublayers.items[i].id) === String(id)) {
              return this.allSublayers.items[i]
            }
          }
        }
      }

      /**
       * 根据范围和大小获取image标签
       * @param {Extent} extent
       * @param {Number} [width = 256] 图片宽度，单位px
       * @param {Number} [height = 256] 图片高度，单位px
       * @example <caption><h7 id='fetchImage'>根据范围和大小获取image标签</h7></caption>
       * igsMapImageLayer.fetchImage({
       *   // 你的范围
       *   extent: new Zondy.Geometry.Extent(),
       *   // 图片宽度
       *   width: 256,
       *   // 图片高度
       *   height: 256
       * }).then((image) => {
       *   // 这里返回一个html的image标签
       * })
       * */
      fetchImage(extent, width, height) {
        width = defaultValue(width, 256)
        height = defaultValue(height, 256)
        const url = this.getImageUrl({
          extent,
          width,
          height
        })

        return new Promise((resolve) => {
          const image = new Image()
          image.src = url
          image.width = width
          image.height = height
          resolve(image)
        })
      }

      /**
       * 创建一个该服务的子图层克隆对象，注意不是本地的子图层对象<a id='createServiceSublayers'></a>
       * @return {Array} 服务上的子图层对象
       * */
      createServiceSublayers() {
        return this.serviceSublayers
      }

      /**
       * 根据参数获取图片的url
       * @param options
       * @param {Extent} [options.extent] 图片范围
       * @param {Number} [options.width] 图片宽度
       * @param {Number} [options.height] 图片高度
       * @return String 图片的url
       * @example <caption><h7 id='getImageUrl'>根据参数获取图片的url</h7></caption>
       * const url = igsMapImageLayer.getImageUrl({
       *   // 你的范围
       *   extent: new Zondy.Geometry.Extent(),
       *   // 图片宽度
       *   width: 256,
       *   // 图片高度
       *   height: 256
       * })
       * */
      getImageUrl(options) {
        return this._mapServer.getImage(options)
      }

      /**
       * 更新子图层<a id='setSubLayer'></a>
       * @param {IGSMapImageSubLayer} igsMapImageSubLayer 要更新的子图层
       * */
      setSubLayer(igsMapImageSubLayer) {
        // 更新子图层
        setSublayer(this, igsMapImageSubLayer, IGSMapImageSubLayer)
        // 设置子图层显隐
        this._setLayers()
        // 发送更新事件
        fireEvent(
          this,
          LayerEventType.layerUpdate,
          LayerEventType.layerSublayerVisible
        )
      }

      _setLayers() {
        // 如果url后面没有id，则计算layers
        if (!this._urlLayerId) {
          // 设置子图层显隐
          let layers = 'show:'
          this.allSublayers.forEach(function (sublayer) {
            if (sublayer.visible && sublayer.type !== 'Group') {
              layers += `${sublayer.id},`
            }
          })
          layers = layers.substring(0, layers.length - 1)

          this.layers = layers
        }
      }

      /**
       * 克隆图层对象
       * @param {IGSMapImageLayer} igsMapImageLayer 被克隆的对象
       * @return {IGSMapImageLayer} 克隆后的图层对象
       * @example <caption><h7 id='getImageUrl'>根据参数获取图片的url</h7></caption>
       * // 添加图层
       * const igsMapImageLayer = new Zondy.Layer.IGSMapImageLayer({
       *   // 服务基地址
       *   url: 'http://{ip}:6163/igs/rest/mrms/docs/{serviceName}'
       * });
       * const newLayer = Zondy.Layer.IGSMapImageLayer.clone(igsMapImageLayer)
       */
      static clone(igsMapImageLayer) {
        return new IGSMapImageLayer(igsMapImageLayer.toJSON())
      }

      /**
       * 获取服务端要素过滤参数字符串
       * @return {Object} 服务端要素过滤参数，格式为{"子图层id":{"where":"sql语句"}}
       * */
      getFilters() {
        const _layerFilters = {}
        this.allSublayers.forEach(function (sublayer) {
          const definitionExpression = sublayer.definitionExpression
          if (definitionExpression) {
            _layerFilters[sublayer.id] = {
              where: definitionExpression
            }
          }
        })
        return JSON.stringify(_layerFilters) === '{}' ? '' : _layerFilters
      }

      static fromJSON(json) {
        json = defaultValue(json, {})
        const _layer = new IGSMapImageLayer(json)
        _layer._isFromJSON = true

        const _sublayers = json.sublayers
        if (_sublayers && _sublayers instanceof Array) {
          _layer._sublayers = new Collection()
          for (let i = 0; i < _sublayers.length; i++) {
            _layer._sublayers.add(new IGSMapImageSubLayer(_sublayers[i]))
          }
        }

        const _allSublayers = json.allSublayers
        if (_allSublayers && _allSublayers instanceof Array) {
          _layer.allSublayers = new Collection()
          for (let i = 0; i < _allSublayers.length; i++) {
            _layer.allSublayers.add(new IGSMapImageSubLayer(_allSublayers[i]))
          }
        }

        return _layer
      }
    }

    Object.defineProperties(IGSMapImageLayer.prototype, {
      /**
       * 子图层对象集合
       * @member IGSMapImageLayer.prototype.sublayers
       * @type {Collection}
       */
      sublayers: {
        get() {
          return this._sublayers
        },
        set(value) {
          this._sublayers = value
        }
      },
      /**
       * 空间裁剪范围
       * @member IGSMapImageLayer.prototype.clippingArea
       * @type {Polygon|Extent|Circle|null}
       */
      clippingArea: {
        get() {
          return this._clippingArea
        },
        set(value) {
          this._clippingArea = value
          this._fireUpdateEvent('空间裁剪区域', [
            {
              name: 'clippingArea',
              params: [this._clippingArea],
              dataChanged: true,
              operationType: 'property'
            }
          ])
        }
      }
    })

    Zondy.Layer.IGSMapImageLayer = IGSMapImageLayer
    export default IGSMapImageLayer