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

/**
 * 定义 MapGIS Common API IGS瓦片图层类
 *
 * @alias IGSTileLayer
 *
 * @summary <用于加载和管理IGS瓦片图层，支持IGS1.0和2.0两个服务版本>
 * @description 该类负责具体的图层操作逻辑，包括图层的加载、显示/隐藏、移除等。直接与mapgisMap进行交互
 */
export default class IGSTileLayer {
    /**
     * 构造函数
     * @param {Object} options - 图层配置选项
     * @param {Object} options.map - 地图对象（mapboxgl.Map 实例）
     * @param {String} options.url - 服务基地址
     * @param {String} [options.id] - 图层ID（可选，不传则自动生成）
     * @param {Number} [options.opacity=1] - 图层透明度 (0-1)
     * @param {Boolean} [options.visible=true] - 图层可见性
     * @param {Object} [options.spatialReference] - 图层坐标系
     * @param {Number} [options.minScale=0] - 最小显示比例尺
     * @param {Number} [options.maxScale=0] - 最大显示比例尺
     * @param {String} [options.tokenKey='token'] - Token键名
     * @param {String} [options.tokenValue=''] - Token值
     * @param {Object} [options.clippingArea=null] - 图层空间裁剪范围
     */
    constructor(options) {
        /**
         * 地图对象
         * @type {Object}
         */
        this._map = options.map;

        this._layer = null

        /**
         * 服务基地址
         * IGS1.0的服务为：http://{ip}:{port}/igs/rest/mrms/tile/{folder}:{serviceName}
         * IGS2.0的服务为：http://{ip}:{port}/igs/rest/services/{folder}/{serviceName}/TileServer
         * IGS2.0的MapServer服务为：http://{ip}:{port}/igs/rest/services/{folder}/{serviceName}/MapServer
         * @type {String}
         */
        this._url = options.url;

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

        /**
         * 图层透明度 (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 {Object|null}
         */
        this._spatialReference = DataUtils.default(options.spatialReference, new zondy.SpatialReference({
            wkid: mapConfig.map_srid_code
        }));

        /**
         * 最小显示比例尺，图层在视图中可见的最小比例尺
         * @type {Number}
         */
        this._minScale = DataUtils.default(options.minScale, 0);

        /**
         * 最大显示比例尺，图层在视图中可见的最大比例尺
         * @type {Number}
         */
        this._maxScale = DataUtils.default(options.maxScale, 0);

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

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

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

        /**
         * 图层类型
         * @type {String}
         */
        this._type = 'igs-tile';

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

    _buildOptions() {
        return {
            url: this._url,
            id: this._layerId,
            type: this._type,
            opacity: this._opacity,
            visible: this._visible,
            spatialReference: this._spatialReference,
            minScale: this._minScale,
            maxScale: this._maxScale,
            tokenKey: this._tokenKey,
            tokenValue: this._tokenValue,
            clippingArea: this._clippingArea,
            isFLyTo: this._isFlyTo || false
        }
    }

    /**
     * 加载图层资源
     * @description 不加载图层到地图，仅获取图层信息
     * @param {Function} [onLoaded] - 可选的回调函数，在图层加载完成后执行
     * @returns {Promise<IGSTileLayer>} 返回图层实例的 Promise
     *
     * @example
     * const layer = new IGSTileLayer({
     *     url: 'http://{ip}:{port}/igs/rest/services/Tile/{serviceName}/TileServer'
     * });
     * await layer.load();
     */
    load(onLoaded) {
        return new Promise((resolve, reject) => {
            try {
                if (!this._layer) {
                    const opts = this._buildOptions();
                    this._layer = new zondy.layer.IGSTileLayer(opts);
                }

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

                    // 如果提供了回调函数，执行它
                    if (onLoaded && typeof onLoaded === 'function') {
                        onLoaded(result);
                    }

                    resolve(this);
                };

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

                // 如果已经加载完成，直接返回
                if (this._layer.loadStatus === 'loaded') {
                    // 如果提供了回调函数，也需要执行
                    if (onLoaded && typeof onLoaded === 'function') {
                        onLoaded({ layer: this._layer });
                    }
                    resolve(this);
                }
            } catch (error) {
                reject(error);
            }
        });
    }

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

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

    /**
     * 根据级数以及行列号获取瓦片的url
     * @param {Number} level - 瓦片级数
     * @param {Number} row - 行号
     * @param {Number} col - 列号
     * @returns {String} 瓦片URL
     */
    getTileUrl(level, row, col) {
        if (!this._layer) {
            console.warn('IGS瓦片图层未加载');
            return '';
        }

        // 调用底层 zondy.layer.IGSTileLayer 的 getTileUrl 方法
        return this._layer.getTileUrl(level, row, col);
    }

    /**
     * 显示/隐藏图层
     * @param {Boolean} isShow - 是否显示图层（true: 显示，false: 隐藏）
     */
    showLayer(isShow) {
        // 更新内部可见性状态
        this._visible = isShow;

        // 如果底层图层已加载，调用其 visible 属性
        if (this._layer) {
            this._layer.visible = isShow;
        }
    }

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

    /**
     * 判断图层是否加载成功（继承自 Layer）
     * @returns {Boolean} 图层是否加载成功
     */
    isLoaded() {
        if (!this._layer) {
            return false;
        }

        // 调用底层图层的 isLoaded 方法
        return this._layer.isLoaded();
    }

    /**
     * 移除图层
     */
    removeLayer() {

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

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

    /**
     * 设置图层透明度
     * @param {Number} opacity - 透明度值 (0-1)
     */
    setOpacity(opacity) {
        this._opacity = opacity;

        // 如果底层图层已加载，设置其透明度
        if (this._layer) {
            this._layer.opacity = opacity;
        }
    }

    /**
     * 获取图层透明度
     * @returns {Number} 透明度值
     */
    getOpacity() {
        return this._opacity;
    }

    /**
     * 设置图层可见性
     * @param {Boolean} visible - 是否可见
     */
    setVisible(visible) {
        this.showLayer(visible);
    }

    /**
     * 获取图层可见性
     * @returns {Boolean} 是否可见
     */
    getVisible() {
        return this._visible;
    }

    /**
     * 将图层转为JSON对象
     * @description 导出图层配置为JSON格式，可用于序列化存储或传输
     * @returns {Object} JSON对象，包含图层的所有配置信息
     *
     * @example
     * const json = layer.toJSON();
     * console.log(json); // { url: '...', id: '...', opacity: 1, ... }
     */
    toJSON() {
        return {
            type: this._type,
            url: this._url,
            id: this._layerId,
            opacity: this._opacity,
            visible: this._visible,
            spatialReference: this._spatialReference,
            minScale: this._minScale,
            maxScale: this._maxScale,
            tokenKey: this._tokenKey,
            tokenValue: this._tokenValue,
            clippingArea: this._clippingArea
        };
    }

    /**
     * 通过传入的JSON构造并返回一个新的IGSTileLayer对象
     * @description 静态方法，从JSON对象创建图层实例
     * @param {Object} json - JSON对象，包含图层配置信息
     * @param {Object} json.map - 地图对象（必需）
     * @returns {IGSTileLayer} 新的IGSTileLayer实例
     *
     * @example
     * const json = {
     *   url: 'http://{ip}:{port}/igs/rest/services/Tile/{serviceName}/TileServer',
     *   opacity: 0.8,
     *   visible: true
     * };
     * const layer = IGSTileLayer.fromJSON(json);
     */
    static fromJSON(json) {
        if (!json || typeof json !== 'object') {
            throw new Error('无效的JSON对象');
        }

        return new IGSTileLayer({
            map: json.map,
            url: json.url,
            id: json.id,
            opacity: json.opacity,
            visible: json.visible,
            spatialReference: json.spatialReference,
            minScale: json.minScale,
            maxScale: json.maxScale,
            tokenKey: json.tokenKey,
            tokenValue: json.tokenValue,
            clippingArea: json.clippingArea
        });
    }

    /**
     * 克隆IGSTileLayer对象
     * @description 创建当前图层的一个深拷贝副本
     * @returns {IGSTileLayer} 克隆后的新图层实例
     *
     * @example
     * const clonedLayer = layer.clone();
     */
    clone() {
        const json = this.toJSON();
        // 注意：clone时需要重新提供map对象
        delete json.map;
        return IGSTileLayer.fromJSON(json);
    }
}
