import DataUtils from '../../../../mapboxgl/js/utils/DataUtils';
import mapConfig from '../../../../baseSetting/config/mapConfig'
import {removeLayerFromManager} from "../";

/**
 * 定义 MapGIS Common API IGS地图图片图层类
 *
 * @alias IGSMapImageLayer
 *
 * @summary <用于加载和管理IGS地图图片图层，支持IGS1.0和2.0两个服务版本>
 * @description 该类负责具体的图层操作逻辑，包括图层的加载、显示/隐藏、移除等。
 *              底层通过 LayerProvider 与 Mapbox GL JS 进行交互。
 */
export default class IGSMapImageLayer {
    /**
     * 构造函数
     * @param {Object} options - 图层配置选项
     * @param {Object} options.map - 地图对象（mapboxgl.Map 实例）
     * @param {String} options.url - 服务基地址
     * @param {String} [options.id] - 图层ID（可选，不传则自动生成）
     * @param {String} [options.httpMethod='GET'] - HTTP请求方式
     * @param {String} [options.title=''] - 图层标题
     * @param {String} [options.description=''] - 图层描述
     * @param {Number} [options.opacity=1] - 图层透明度 (0-1)
     * @param {Boolean} [options.visible=true] - 图层可见性
     * @param {Array<Object>} [options.sublayers] - 子图层参数配置
     * @param {Object} [options.spatialReference] - 坐标系
     * @param {Number} [options.imageWidth=256] - 图片宽度
     * @param {Number} [options.imageHeight=256] - 图片高度
     * @param {Number} [options.minzoom=0] - 最小显示层级
     * @param {Number} [options.maxzoom=22] - 最大显示层级
     * @param {String} [options.tokenKey='token'] - Token键名
     * @param {String} [options.tokenValue=''] - Token值
     * @param {Boolean} [options.imageTransparency=true] - 图片透明区域是否透明
     * @param {String} [options.clientId] - 客户端ID
     * @param {Boolean} [options.isAntialiasing=false] - 是否开启服务端抗锯齿
     * @param {Boolean} [options.disableHiRender=false] - 是否禁用快显服务
     * @param {Object} [options.clippingArea=null] - 图层空间裁剪范围
     */
    constructor(options) {
        /**
         * 地图对象
         * @type {Object}
         */
        this._map = options.map;

        this._layer = null

        /**
         * 服务基地址
         * 可以在末尾指定子图层id,若指定,则仅显示该子图层
         * 例如:http://{服务基地址}/子图层id
         * IGS1.0的服务为:http://{ip}:6163/igs/rest/mrms/docs/{folder}:{serviceName}
         * IGS2.0的服务为:http://{ip}:{port}/igs/rest/services/{folder}/{serviceName}/MapServer
         * @type {String}
         */
        this._url = options.url;

        /**
         * HTTP请求方式
         * 默认为GET请求
         * @type {String}
         */
        this._httpMethod = DataUtils.default(options.httpMethod, 'GET');

        /**
         * 图层ID
         * @type {String}
         */
        this._layerId = DataUtils.default(options.id + '_source', 'igs_map_image_layer_' + new Date().getTime());

        /**
         * 数据源ID
         * @type {String}
         */
        this._sourceId = this._layerId;

        /**
         * 图层标题
         * @type {String}
         */
        this._title = DataUtils.default(options.title, '');

        /**
         * 图层描述
         * @type {String}
         */
        this._description = DataUtils.default(options.description, '');

        /**
         * 图层透明度 (0-1),0为完全透明,1为不透明
         * @type {Number}
         */
        this._opacity = DataUtils.default(options.opacity, 1);

        /**
         * 图层可见性,true则显示,false则隐藏
         * @type {Boolean}
         */
        this._visible = DataUtils.default(options.visible, true);

        /**
         * 裁剪区域
         * @type {Polygon | Extent | Circle | MultiPolygon | null}
         */
        this._clippingArea = DataUtils.default(options.clippingArea, null);

        /**
         * 子图层参数配置
         * 会通过该参数中指定的子图层列表对地图服务中的子图层进行过滤
         * 不在列表中的子图层将不会显示
         * 如果没有指定该参数,则会按照地图服务中的子图层的属性显示所有子图层
         * 如果该参数为空数组,则地图服务所有的子图层都不显示
         * 子图层顺序以及专题图参数仅支持IGS2.0服务
         * @type {Array<Object>|undefined}
         */
        this._sublayers = DataUtils.default(options.sublayers, undefined);

        /**
         * 坐标系
         * 支持4326(包含4490,4214以及4610)、3857以及EPSG上的自定义坐标系
         * 坐标系默认从元信息中获取,也可指定坐标系
         * @type {Object|null}
         */
        this._spatialReference = DataUtils.default(options.spatialReference, new zondy.SpatialReference({
            wkid: mapConfig.map_srid_code
        }));

        /**
         * 图片宽度,单位px
         * @type {Number}
         */
        this._imageWidth = DataUtils.default(options.imageWidth, 256);

        /**
         * 图片高度,单位px
         * @type {Number}
         */
        this._imageHeight = DataUtils.default(options.imageHeight, 256);

        /**
         * 最小显示层级,图层在视图中可见的最小缩放级别(最缩小)
         * 如果地图被缩小到超过这个层级,图层将不可见
         * @type {Number}
         */
        this._minzoom = DataUtils.default(options.minzoom, mapConfig.minZoom);

        /**
         * 最大显示层级,图层在视图中可见的最大缩放级别(最放大)
         * 如果地图被放大到超过这个层级,图层将不可见
         * @type {Number}
         */
        this._maxzoom = DataUtils.default(options.maxzoom, mapConfig.isOnline ? mapConfig.maxOnlineZoom : mapConfig.maxZoom);

        /**
         * Token键名
         * @type {String}
         */
        this._tokenKey = DataUtils.default(options.tokenKey, 'token');

        /**
         * Token值,只有当tokenValue存在时,才会绑定token
         * @type {String}
         */
        this._tokenValue = DataUtils.default(options.tokenValue, '');

        /**
         * 图片中没有数据的地方是否透明,默认为true,即透明
         * @type {Boolean}
         */
        this._imageTransparency = DataUtils.default(options.imageTransparency, true);

        /**
         * 客户端ID
         * 用户的唯一标识,默认为未定义
         * 在地图服务中,调用接口时如果修改了地图的状态,包括设置动态投影、设置图层显示隐藏等
         * 为了提升并发性能,服务端会根据clientId来生成临时地图
         * 最佳做法是一个浏览器生成一个固定的唯一值
         * 建议普通用户不要传该参数,webclient会根据当前浏览器生成一个固定的唯一值
         * 在IGServer 10.7.6.10及以后版本中,出图服务不再使用该参数
         * @type {String}
         */
        this._clientId = options.clientId;

        /**
         * 是否开启服务端抗锯齿
         * 启用抗锯齿功能后,显示效果会更清晰,但会导致出图速度变慢
         * true表示开启抗锯齿,false表示关闭抗锯齿
         * 如果没有设置,则默认应用地图文档(MapX)上的设置参数
         * @type {Boolean|null}
         */
        this._isAntialiasing = DataUtils.default(options.isAntialiasing, false);

        /**
         * 是否禁用快显服务
         * 仅当图层的isSupportHiRender属性为true时生效
         * @type {Boolean}
         */
        this._disableHiRender = DataUtils.default(options.disableHiRender, false);

        /**
         * 图片格式
         * @type {String}
         */
        this._imageFormat = '';

        /**
         * 图片格式数组,表示服务支持的所有图片格式
         * @type {Array}
         */
        this._imageFormats = [];

        /**
         * 所有子图层对象信息
         * @type {Array}
         */
        this._allSublayers = [];

        /**
         * 地图文档信息
         * @type {Object}
         */
        this._documentInfo = {};

        /**
         * 是否开启动态投影
         * @type {Boolean}
         */
        this._dynamicProjectionEnabled = false;

        /**
         * 图层空间裁剪范围
         * 仅支持多多边形裁剪、多边形裁剪、矩形裁剪、圆形裁剪
         * @type {Object|null}
         */
        this._clippingArea = DataUtils.default(options.clippingArea, null);

        /**
         * 图层类型
         * @type {String}
         */
        this._type = DataUtils.default(options.type, 'igs-map-image');

        /**
         * 图层加载状态: 'unloaded' | 'loading' | 'loaded' | 'error'
         * @type {String}
         */
        this._loadStatus = 'unloaded';

        /**
         * 样式属性数组
         * @type {Array}
         */
        this._styleProperties = [];

        /**
         * 事件监听器集合
         * @type {Object}
         */
        this._eventListeners = {};


        this._isFlyTo = DataUtils.default(options.isFlyTo, true);
    }

    _buildOptions() {
        return {
            url: this._url,
            id: this._layerId,
            httpMethod: this._httpMethod,
            visible: this._visible,
            sublayers: this._sublayers,
            spatialReference: this._spatialReference,
            imageWidth: this._imageWidth,
            imageHeight: this._imageHeight,
            minzoom: this._minzoom,
            maxzoom: this._maxzoom,
            tokenKey: this._tokenKey,
            tokenValue: this._tokenValue,
            imageTransparency: this._imageTransparency,
            clientId: this._clientId,
            isAntialiasing: this._isAntialiasing,
            disableHiRender: this._disableHiRender,
            imageFormat: this._imageFormat,
            clippingArea: this._clippingArea,
            opacity: this._opacity
        }
    }

    /** ==================== Core Methods ==================== */

    /**
     * 加载图层资源
     * @description 不加载图层到地图，仅获取图层信息
     * @returns {Promise<IGSMapImageLayer>} 返回图层实例的 Promise
     *
     * @example
     * const layer = new IGSMapImageLayer({
     *     url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer'
     * });
     * layer.load().then((result) => {
     *     console.log(result); // 获取完图层信息
     * });
     */
    load() {
        return new Promise((resolve, reject) => {
            try {
                if (!this._layer) {
                    const opts = this._buildOptions();
                    this._layer = new zondy.layer.IGSMapImageLayer(opts);
                }

                // 监听图层加载完成事件
                const handler = (result) => {
                    // 移除事件监听器
                    this._layer.off('layerview-created', handler);
                    resolve(this);
                };

                this._layer.on('layerview-created', handler);

                // 如果已经加载完成，直接返回
                if (this._layer.loadStatus === 'loaded') {
                    resolve(this);
                }
            } catch (error) {
                reject(error);
            }
        });
    }

    /**
     * 加载图层到地图
     * @description 调用 zondy.layer.IGSMapImageLayer 加载图层数据，并添加到 Mapbox GL 地图中
     * @returns {Promise<void>}
     *
     * @example
     * const layer = createLayer({
     *     type: 'igs-map-image',
     *     map: mapboxMap,
     *     url: 'http://xxx/igs/rest/services/Map/图层/MapServer'
     * });
     * await layer.loadLayer();
     */
    loadLayer() {
        if (this.hasLayer()) return;

        const layer = new zondy.layer.IGSMapImageLayer(this._buildOptions())
        this._layer = layer;
        // 将图层添加到 MapGIS 地图对象
        this.addToMapGisMap()
        // 监听图层加载完成事件
        layer.on('layerview-created',(result) => {
            //视点跳转
            this._isFlyTo && gisView.goTo({
                layer: result.layer
            })
        });
    }

    addToMapGisMap() {
        this._map.add(this._layer)
    }

    /**
     * 显示/隐藏图层
     * @param {Boolean} isShow - 是否显示图层（true: 显示，false: 隐藏）
     */
    showLayer(isShow) {
        this._layer.visible = isShow
    }

    /**
     * 判断图层是否已加载
     *
     * @returns {Boolean}
     */
    hasLayer() {
        // 优先检查底层 zondy.layer.IGSTileLayer 的加载状态
        if (this._layer && this._layer.isLoaded) {
            return true;
        }
    }

    /**
     * 移除图层
     */
    removeLayer() {
        // 移除底层 zondy.layer.IGSTileLayer
        if (this._layer) {
            this._layer.remove();
            this._layer = null;
        }

        // 从管理器中移除
        removeLayerFromManager(this._layer);
    }

    /**
     * 根据子图层id查询子图层
     * @param {String|Number} id - 子图层id
     * @returns {Object|null} 子图层信息，如果未找到则返回 null
     *
     * @example
     * const sublayer = layer.findSublayerById(1);
     * if (sublayer) {
     *     console.log('找到子图层:', sublayer);
     * }
     */
    findSublayerById(id) {
        if (!this._layer) {
            console.warn('图层未加载，请先调用 load() 或 loadLayer()');
            return null;
        }

        try {
            // 调用底层图层的 findSublayerById 方法
            return this._layer.findSublayerById(id);
        } catch (error) {
            console.error('查找子图层失败:', error);
            return null;
        }
    }

    /**
     * 更新子图层
     * @param {Object} igsMapImageSubLayer - 子图层配置对象
     * @param {String|Number} igsMapImageSubLayer.id - 子图层id
     * @param {Boolean} [igsMapImageSubLayer.visible] - 子图层可见性
     * @param {Number} [igsMapImageSubLayer.index] - 子图层顺序
     * @param {Object} [igsMapImageSubLayer.renderer] - 子图层渲染器
     *
     * @example
     * layer.setSubLayer({
     *     id: 1,
     *     visible: true
     * });
     */
    setSubLayer(igsMapImageSubLayer) {
        if (!this._layer) {
            console.warn('图层未加载，请先调用 load() 或 loadLayer()');
            return;
        }

        try {
            // 调用底层图层的 setSubLayer 方法
            this._layer.setSubLayer(igsMapImageSubLayer);
        } catch (error) {
            console.error('更新子图层失败:', error);
        }
    }

    /**
     * 根据范围和大小获取 image 标签
     * @param {Object} extent - 范围参数（Extent 对象）
     * @param {Number} [width=256] - 图片宽度，单位px
     * @param {Number} [height=256] - 图片高度，单位px
     * @returns {Promise<HTMLImageElement>} 返回 image 标签的 Promise
     *
     * @example
     * layer.fetchImage({
     *     extent: new zondy.geometry.Extent(),
     *     width: 256,
     *     height: 256
     * }).then((image) => {
     *     // 这里返回一个html的image标签
     *     document.body.appendChild(image);
     * });
     */
    fetchImage(extent, width = 256, height = 256) {
        return new Promise((resolve, reject) => {
            if (!this._layer) {
                reject(new Error('图层未加载，请先调用 load() 或 loadLayer()'));
                return;
            }

            try {
                // 调用底层图层的 fetchImage 方法
                this._layer.fetchImage(extent, width, height).then((image) => {
                    resolve(image);
                }).catch((error) => {
                    reject(error);
                });
            } catch (error) {
                reject(error);
            }
        });
    }

    /**
     * 根据参数获取图片的 url
     * @param {Object} options - 参数选项
     * @param {Object} [options.extent] - 图片范围（Extent 对象）
     * @param {Number} [options.width=256] - 图片宽度
     * @param {Number} [options.height=256] - 图片高度
     * @returns {String} 图片的 url
     *
     * @example
     * const url = layer.getImageUrl({
     *     extent: new zondy.geometry.Extent(),
     *     width: 256,
     *     height: 256
     * });
     * console.log('图片URL:', url);
     */
    getImageUrl(options = {}) {
        if (!this._layer) {
            console.warn('图层未加载，请先调用 load() 或 loadLayer()');
            return '';
        }

        try {
            // 调用底层图层的 getImageUrl 方法
            return this._layer.getImageUrl(options);
        } catch (error) {
            console.error('获取图片URL失败:', error);
            return '';
        }
    }

    /**
     * 转换为 JSON 对象
     * @returns {Object} JSON 对象
     *
     * @example
     * const json = layer.toJSON();
     * console.log(json);
     */
    toJSON() {
        return {
            url: this._url,
            httpMethod: this._httpMethod,
            id: this._layerId,
            title: this._title,
            description: this._description,
            opacity: this._opacity,
            visible: this._visible,
            sublayers: this._sublayers,
            spatialReference: this._spatialReference ? this._spatialReference.toJSON ? this._spatialReference.toJSON() : this._spatialReference : null,
            imageWidth: this._imageWidth,
            imageHeight: this._imageHeight,
            minzoom: this._minzoom,
            maxzoom: this._maxzoom,
            tokenKey: this._tokenKey,
            tokenValue: this._tokenValue,
            imageTransparency: this._imageTransparency,
            clientId: this._clientId,
            isAntialiasing: this._isAntialiasing,
            disableHiRender: this._disableHiRender,
            clippingArea: this._clippingArea,
            type: this._type
        };
    }

    /**
     * 克隆 IGSMapImageLayer 对象
     * @returns {IGSMapImageLayer} 克隆后的 IGSMapImageLayer 实例
     *
     * @example
     * const clonedLayer = layer.clone();
     */
    clone() {
        const json = this.toJSON();
        return IGSMapImageLayer.fromJSON(json);
    }

    /**
     * 通过传入的 JSON 构造并返回一个新的 IGSMapImageLayer 实例
     * @static
     * @param {Object} json - JSON 对象
     * @returns {IGSMapImageLayer} 新的 IGSMapImageLayer 实例
     *
     * @example
     * const json = {
     *     url: 'http://{ip}:{port}/igs/rest/services/{serviceName}/MapServer'
     * };
     * const layer = IGSMapImageLayer.fromJSON(json);
     */
    static fromJSON(json) {
        if (!json || !json.url) {
            throw new Error('JSON 对象必须包含 url 属性');
        }

        return new IGSMapImageLayer({
            url: json.url,
            httpMethod: json.httpMethod,
            id: json.id,
            title: json.title,
            description: json.description,
            opacity: json.opacity,
            visible: json.visible,
            sublayers: json.sublayers,
            spatialReference: json.spatialReference,
            imageWidth: json.imageWidth,
            imageHeight: json.imageHeight,
            minzoom: json.minzoom,
            maxzoom: json.maxzoom,
            tokenKey: json.tokenKey,
            tokenValue: json.tokenValue,
            imageTransparency: json.imageTransparency,
            clientId: json.clientId,
            isAntialiasing: json.isAntialiasing,
            disableHiRender: json.disableHiRender,
            clippingArea: json.clippingArea
        });
    }
}
