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

    /**
     * ArcGIS地图图片图层，<br/>
     * 目前二维上支持4326(包括4490，4214以及4610)，3857以及EPSG支持的自定义坐标系，三维上仅支持4326(包括4490，4214以及4610)以及3857坐标系，会自动读取元信息上的坐标系，不需要用户指定
     * <br><br>[ES5引入方式]：<br/>
     * Zondy.Layer.ArcGISMapImageLayer() <br/>
     * [ES6引入方式]：<br/>
     * import { ArcGISMapImageLayer } 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 ArcGISMapImageLayer
     * @moduleEX LayerManagerModule
     * @classdesc ArcGIS地图图片图层
     * @extends MapImageLayer
     * @fires Layer#图层加载完毕事件
     * @fires Layer#图层销毁完毕事件
     * @fires Layer#图层更新完毕事件
     * @param {Object} options 构造参数
     * @param {String} [options.url] 服务基地址，<br/>
     * https://{ip}:{port}/arcgis/rest/services/{serviceName}/MapServer，参考示例：<a href='#arcgis'>[ArcGIS的地图图片图层示例]</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 {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 = 0] 最小缩放级数，仅会请求级数大于等于minScale的图片
     * @param {Number} [options.maxScale = 19] 最大缩放级数，仅会请求级数小于等于maxScale的图片
     * @param {String} [options.tokenKey = 'token'] token名
     * @param {String} [options.tokenValue] token值，只有当tokenValue存在时，才会绑定token
     * @param {Boolean} [options.imageTransparency = true] 图片中没有数据的地方是否透明，默认为true，即透明
     *
     * @summary <h5>支持如下方法：</h5>
     * <a href='#load'>[1、加载图层资源]</a><br/>
     * <a href='#findSublayerById'>[2、根据子图层id查询子图层]</a><br/>
     * <a href='#refresh'>[3、刷新图层]</a><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='#fromJSON'>[8、通过传入的json构造并返回一个新的几何对象]</a><br/>
     * [9、导出为json对象]{@link OGCLayer#toJSON}<br/>
     * [10、克隆几何对象]{@link OGCLayer#clone}
     *
     * @example <caption><h7 id='arcgis'>ArcGIS的地图图片图层示例</h7></caption>
     * // 初始化图层管理容器
     * // ES5引入方式
     * const { Map,MapView } = Zondy
     * const { ArcGISMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { Map,MapView,ArcGISMapImageLayer } from "@mapgis/webclient-common"
     * const map = new Map();
     * // 初始化地图视图对象
     * const mapView = new MapView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 添加图层
     * const arcGISMapImageLayer = new ArcGISMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/arcgis/rest/services/{serviceName}/MapServer'
     * });
     * map.add(arcGISMapImageLayer);
     *
     * @example <caption><h7 id='spatialReference'>指定图层的坐标系示例</h7></caption>
     * // ES5引入方式
     * const { ArcGISMapImageLayer } = Zondy.Layer
     * const { SpatialReference } = Zondy
     * // ES6引入方式
     * import { ArcGISMapImageLayer,SpatialReference } from "@mapgis/webclient-common"
     * // 添加图层
     * const arcGISMapImageLayer = new ArcGISMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/arcgis/rest/services/{serviceName}/MapServer',
     *   // 自定义坐标新
     *   spatialReference: new SpatialReference({
     *     // 指定的wkid号，可在https://epsg.io/网站查询
     *     wkid: '指定的wkid号'
     *   })
     * });
     * map.add(arcGISMapImageLayer);
     *
     * @example <caption><h7 id='tileSize'>地图图层示例 - 设置图片大小</h7></caption>
     * // ES5引入方式
     * const { Map,MapView } = Zondy
     * const { ArcGISMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { Map,MapView,ArcGISMapImageLayer } from "@mapgis/webclient-common"
     * // 初始化图层管理容器
     * const map = new Map();
     * // 初始化地图视图对象
     * const mapView = new MapView({
     *   // 视图id
     *   viewId: "viewer-id",
     *   // 图层管理容器
     *   map: map
     * });
     * // 添加图层
     * const arcGISMapImageLayer = new ArcGISMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/arcgis/rest/services/{serviceName}/MapServer',
     *   // 瓦片宽度
     *   imageWidth: 512,
     *   // 瓦片高度
     *   imageHeight: 512
     * });
     * map.add(arcGISMapImageLayer);
     *
     * @example <caption><h7 id='opacity'>设置图层透明度</h7></caption>
     * // ES5引入方式
     * const { ArcGISMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { ArcGISMapImageLayer } from "@mapgis/webclient-common"
     * // 初始化时设置
     * const arcGISMapImageLayer = new ArcGISMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/arcgis/rest/services/{serviceName}/MapServer',
     *   // 设置透明度
     *   opacity: 1.0
     * });
     * map.add(arcGISMapImageLayer);
     * // 加载完成后设置
     * arcGISMapImageLayer.on('layerview-created', function (result) {
     *   console.log("加载完毕:", result.layer)
     *   // 视点跳转
     *   ArcGISMapImageLayer.opacity = 0.5
     * })
     *
     * @example <caption><h7 id='visible'>显示或隐藏图层</h7></caption>
     *  // ES5引入方式
     * const { ArcGISMapImageLayer } = Zondy.Layer
     * // ES6引入方式
     * import { ArcGISMapImageLayer } from "@mapgis/webclient-common"
     * // 初始化时设置
     * const arcGISMapImageLayer = new ArcGISMapImageLayer({
     *   // 服务基地址
     *   url: 'http://{ip}:{port}/arcgis/rest/services/{serviceName}/MapServer',
     *   // 显示或隐藏图层
     *   visible: true
     * });
     * map.add(arcGISMapImageLayer);
     * // 加载完成后设置
     * arcGISMapImageLayer.on('layerview-created', function (result) {
     *   console.log("加载完毕:", result.layer)
     *   // 显示或隐藏图层
     *   arcGISMapImageLayer.visible = !ArcGISMapImageLayer.visible
     * })
     *
     * @example <caption><h7 id='remove-layer'>删除图层</h7></caption>
     * map.remove(arcGISMapImageLayer)
     *
     * @example <caption><h7 id='index'>图层顺序</h7></caption>
     * // 加载完毕后，更改图层顺序
     * map.reorder(arcGISMapImageLayer, '要移动到的index');
     */
    class ArcGISMapImageLayer extends MapImageLayer {
      constructor(options) {
        super(options)
        options = defaultValue(options, {})
        /**
         * 图层类型
         * @readonly
         * @member {String} ArcGISMapImageLayer.prototype.type
         */
        this.type = LayerType.arcgisMapImage
        this.description = 'ArcGIS地图图片图层'

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

      /**
       * 加载图层资源
       * @example <caption><h7 id='load'>不加载图层，仅获取图层信息</h7></caption>
       * // ES5引入方式
       * const { ArcGISMapImageLayer } = Zondy.Layer
       * // ES6引入方式
       * import { ArcGISMapImageLayer } from "@mapgis/webclient-common"
       * // 初始化图层
       * const arcGISMapImageLayer = new ArcGISMapImageLayer({
       *   // 服务基地址
       *   url: 'http://{ip}:{port}/arcgis/rest/services/{serviceName}/MapServer',
       * });
       * arcGISMapImageLayer.load().then((result) => {
       *   // 获取完图层信息
       *   console.log(result)
       * })
       * */
      load() {
        const self = this
        return this._mapServer.queryServerInfo().then((result) => {
          Log.info('MapServer信息查询成功:', result)
          const data = result.data
          // 查询图层列表参数
          const queryLayerListOpts = {}

          self.documentInfo = data.documentInfo
          self.mapName = data.mapName
          self.capabilities = data.capabilities
          self.tileInfo = defaultValue(data.tileInfo, {})

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

            if (isNull(self.spatialReference)) {
              self._spatialReference = SpatialReference.fromJSON(
                self._spatialReferenceSrc.toJSON()
              )
            }
          }

          if (!isNull(data.fullExtent)) {
            self._extentSrc = new Extent({
              xmin: data.fullExtent.xmin,
              ymin: data.fullExtent.ymin,
              xmax: data.fullExtent.xmax,
              ymax: data.fullExtent.ymax,
              spatialReference: self._spatialReferenceSrc
            })
          }

          return self._mapServer
            .queryLayerList(queryLayerListOpts)
            .then((layerList) => {
              Log.info('子图层信息查询成功:', layerList)

              const sublayers = layerList.data.layers
              self.serviceSublayers = sublayers

              for (let i = 0; i < sublayers.length; i++) {
                sublayers[i].layer = self
                self.allSublayers.push(new ArcGISMapImageSubLayer(sublayers[i]))
              }
              for (let i = 0; i < self._sublayers.length; i++) {
                for (let j = 0; j < self.allSublayers.length; j++) {
                  if (
                    String(self._sublayers[i].id) ===
                      String(self.allSublayers[j].id) ||
                    String(self._sublayers[i].name) ===
                      String(self.allSublayers[j].name)
                  ) {
                    if (!(self._sublayers[i] instanceof ArcGISMapImageSubLayer)) {
                      const options = Object.assign(
                        JSON.parse(JSON.stringify(self.allSublayers[j])),
                        self._sublayers[i]
                      )
                      options.layer = self
                      options.id = String(options.id)
                      self._sublayers[i] = new ArcGISMapImageSubLayer(options)
                      self.allSublayers[j] = new ArcGISMapImageSubLayer(options)
                    }
                    break
                  }
                }
              }
              // 设置子图层显隐
              self._setLayers()
              // 图层信息加载完毕
              self.loadStatus = LoadStatus.loaded
              self.loaded = true
              return new Promise((resolve) => {
                resolve(self)
              })
            })
        })
      }

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

      /**
       * 刷新图层<a id='refresh'></a>
       * */
      refresh() {
        this._fireUpdateEvent('刷新图层', [
          {
            params: arguments,
            dataChanged: true,
            name: 'refresh',
            operationType: 'method'
          }
        ])
      }

      /**
       * 根据范围和大小获取image标签
       * @param {Extent} extent
       * @param {Number} [width = 256] 图片宽度，单位px
       * @param {Number} [height = 256] 图片高度，单位px
       * @example <caption><h7 id='fetchImage'>根据范围和大小获取image标签</h7></caption>
       *  // ES5引入方式
       * const { Extent } = Zondy.Geometry
       * // ES6引入方式
       * import { Extent } from "@mapgis/webclient-common"
       * arcGISMapImageLayer.fetchImage({
       *   // 你的范围
       *   extent: new 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>
       *  // ES5引入方式
       * const { Extent } = Zondy.Geometry
       * // ES6引入方式
       * import { Extent } from "@mapgis/webclient-common"
       * const url = arcGISMapImageLayer.getImageUrl({
       *   // 你的范围
       *   extent: new Extent(),
       *   // 图片宽度
       *   width: 256,
       *   // 图片高度
       *   height: 256
       * })
       * */
      getImageUrl(options) {
        return this._mapServer.getImage(options)
      }

      /**
       * 通过传入的json构造并返回一个新的几何对象<a id='fromJSON'></a>
       * @param {Object} [json] JSON对象
       * @example <caption><h7>通过传入的json构造并返回一个新的几何对象</h7></caption>
       *  // ES5引入方式
       * const { ArcGISMapImageLayer } = Zondy.Layer
       * // ES6引入方式
       * import { ArcGISMapImageLayer } from "@mapgis/webclient-common"
       * const json = {
       *   // 服务基地址
       *   url: 'http://{ip}:{port}/arcgis/rest/services/{serviceName}/MapServer',
       * }
       * const arcGISMapImageLayer = new ArcGISMapImageLayer.fromJSON(json)
       */
      static fromJSON(json) {
        json = defaultValue(json, {})
        return new ArcGISMapImageLayer(json)
      }

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

      _setLayers() {
        // 设置子图层显隐
        let layers = 'show:'
        for (let i = 0; i < this.allSublayers.length; i++) {
          if (this.allSublayers[i].visible) {
            layers += `${this.allSublayers[i].id},`
          }
        }
        // 如果不显示任何子图层，则用exclude
        if (layers === 'show:') {
          layers = 'exclude:'
          for (let i = 0; i < this.allSublayers.length; i++) {
            layers += `${this.allSublayers[i].id},`
          }
        }
        layers = layers.substring(0, layers.length - 1)
        this.layers = layers
      }
    }

    Object.defineProperties(ArcGISMapImageLayer.prototype, {
      /**
       * 子图层对象
       * @member ArcGISMapImageLayer.prototype.sublayers
       * @type {Array}
       */
      sublayers: {
        get() {
          return this._sublayers
        },
        set(value) {
          this._sublayers = value
        }
      }
    })

    Zondy.Layer.ArcGISMapImageLayer = ArcGISMapImageLayer
    export default ArcGISMapImageLayer