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

/**
 * 定义 MapGIS Common API WMTS图层类
 *
 * @alias WMTSLayer
 *
 * @summary <用于加载和管理WMTS服务图层,基于 MapGIS Client for JavaScript Common 模块>
 * @description 该类负责具体的图层操作逻辑,包括图层的加载、显示/隐藏、移除等。
 *              底层通过 zondy.layer.WMTSLayer 与地图进行交互。
 */
export default class WMTSLayer {
    /**
     * 构造函数
     * @param {Object} options - 图层配置选项
     * @param {Object} options.map - 地图对象(mapboxgl.Map 实例)
     * @param {String} options.url - 服务基地址
     * @param {String} [options.id] - 图层ID(可选,不传则自动生成)
     * @param {Object} [options.activeLayer] - 当前处于活动状态的子图层
     * @param {Number} [options.opacity=1] - 图层透明度 (0-1)
     * @param {Boolean} [options.visible=true] - 图层可见性
     * @param {Number} [options.minScale=0] - 最小显示比例尺
     * @param {Number} [options.maxScale=0] - 最大显示比例尺
     * @param {String} [options.tokenKey='token'] - Token键名
     * @param {String} [options.tokenValue=''] - Token值
     * @param {Boolean|null} [options.isReverseXY=null] - 是否翻转TopLeftCorner、BoundingBox的x、y坐标
     * @param {Boolean|null} [options.isReverseOriginXY=null] - 是否翻转TopLeftCorner的x、y坐标
     * @param {Object} [options.tileDisplayStrategy] - 瓦片显示策略
     * @param {Object} [options.clippingArea] - 图层空间裁剪范围
     */
    constructor(options) {
        /**
         * 地图对象
         * @type {Object}
         */
        this._map = options.map;

        this._layer = null

        /**
         * 服务基地址
         * 支持的服务如下:
         * 1. MapGIS的WMTS服务:
         *    - IGS1.0: http://{ip}:{port}/igs/rest/ogc/{folder}:{serviceName}/WMTSServer
         *    - IGS2.0: http://{ip}:{port}/igs/rest/services/{folder}/{serviceName}/WMTSServer
         * 2. ArcGIS的WMTS服务:
         *    - http://{ip}:{port}/arcgis/rest/services/{ServiceName}/MapServer/WMTS
         * 3. 天地图的WMTS服务:
         *    - http://t{0~6}.tianditu.gov.cn/{图层类型}_{坐标系}/wmts
         *    - 图层类型:vec(矢量底图)、img(卫星影像)、cva(矢量注记-中文)、eva(矢量注记-英文)
         *      cia(注记-中文)、eia(注记-英文)、ter(地形晕渲)、cta(注记-中文)、ibo(全球国界)
         *    - 坐标系:w(墨卡托3857)、c(经纬度4326)
         * @type {String}
         */
        this._url = options.url;

        /**
         * 当前处于活动状态的子图层
         * 默认使用第0个图层的第0个TileMatrixSet来构建图层
         * 用户可指定要加载的子图层
         * @type {Object|null}
         */
        this._activeLayer = DataUtils.default(options.activeLayer, null);

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

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

        /**
         * 图层透明度 (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 {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, '');

        /**
         * 是否翻转TopLeftCorner、BoundingBox的x、y坐标
         * 默认为null,程序会根据已知服务发布厂商的规则计算该值
         * @type {Boolean|null}
         */
        this._isReverseXY = DataUtils.default(options.isReverseXY, null);

        /**
         * 是否翻转TopLeftCorner的x、y坐标
         * 默认为null,程序会根据已知服务发布厂商的规则计算该值
         * @type {Boolean|null}
         */
        this._isReverseOriginXY = DataUtils.default(options.isReverseOriginXY, null);

        /**
         * 瓦片显示策略
         * 当瓦片图层的显示比例尺范围超出瓦片数据自身的级别后的显示策略
         * @type {Object}
         */
        this._tileDisplayStrategy = DataUtils.default(options.tileDisplayStrategy, null);

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

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

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

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

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

    _buildOptions() {
        const options = {
            url: this._url,
            type: this._type,
            id: this._layerId,
            opacity: this._opacity,
            visible: this._visible,
            minScale: this._minScale,
            maxScale: this._maxScale,
            tokenKey: this._tokenKey,
            tokenValue: this._tokenValue,
            isReverseXY: this._isReverseXY,
            isReverseOriginXY: this._isReverseOriginXY,
            clippingArea: this._clippingArea
        };

        // 如果指定了活动子图层,添加到选项中
        if (this._activeLayer) {
            options.activeLayer = this._activeLayer;
        }

        // 如果指定了瓦片显示策略,添加到选项中
        if (this._tileDisplayStrategy) {
            options.tileDisplayStrategy = this._tileDisplayStrategy;
        }

        return options;
    }

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

    /**
     * 加载图层资源
     * @description 不加载图层到地图,仅获取图层信息
     * @returns {Promise<WMTSLayer>} 返回图层实例的 Promise
     *
     * @example
     * const layer = new WMTSLayer({
     *     url: 'http://{ip}:{port}/igs/rest/services/{ServiceName}/WMTSServer'
     * });
     * 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.WMTSLayer(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.WMTSLayer 加载图层数据,并添加到 Mapbox GL 地图中
     * @returns {Promise<void>}
     *
     * @example
     * const layer = createLayer({
     *     type: 'wmts',
     *     map: mapboxMap,
     *     url: 'http://xxx/igs/rest/services/Map/WMTSServer'
     * });
     * await layer.loadLayer();
     */
    loadLayer() {
        if (this.hasLayer()) return;

        const layer = new zondy.layer.WMTSLayer(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.WMTSLayer 的加载状态
        if (this._layer && this._layer.isLoaded) {
            return true;
        }
    }

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

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

    /**
     * 根据子图层id查询图层
     * @param {String|Number} id - 子图层ID
     * @returns {Object|null} 子图层对象或null
     */
    findSublayerById(id) {
        if (!this._layer) {
            console.warn('WMTS图层未加载');
            return null;
        }

        return this._layer.findSublayerById(id);
    }

    /**
     * 获取当前图层瓦片裁图信息
     * @returns {Object|null} 瓦片信息对象或null
     */
    getCurrentTileInfo() {
        if (!this._layer) {
            console.warn('WMTS图层未加载');
            return null;
        }

        return this._layer.getCurrentTileInfo();
    }

    /**
     * 通过传入的json构造并返回一个新的WMTSLayer对象
     * @param {Object} json - JSON对象
     * @returns {WMTSLayer} WMTSLayer实例
     */
    static fromJSON(json) {
        const { WMTSLayer } = zondy.layer;
        const instance = WMTSLayer.fromJSON(json);
        return instance;
    }

    /**
     * 通过url创建图层的对象
     * @param {String} url - 服务基地址
     * @returns {WMTSLayer} 新的图层对象
     */
    static fromServerUrl(url) {
        const { WMTSLayer } = zondy.layer;
        const instance = WMTSLayer.fromServerUrl(url);
        return instance;
    }

    /**
     * 克隆WMTSLayer对象
     * @returns {WMTSLayer} 克隆后的WMTSLayer实例
     */
    clone() {
        if (!this._layer) {
            console.warn('WMTS图层未加载,无法克隆');
            return null;
        }

        return this._layer.clone();
    }

    /**
     * 导出为json对象
     * @returns {Object} JSON对象
     */
    toJSON() {
        if (!this._layer) {
            console.warn('WMTS图层未加载');
            return {};
        }

        return this._layer.toJSON();
    }



    /** ==================== Getter/Setter ==================== */

    /**
     * 获取图层ID
     * @returns {String}
     */
    get layerId() {
        return this._layerId;
    }

    /**
     * 获取服务URL
     * @returns {String}
     */
    get url() {
        return this._url;
    }

    /**
     * 获取或设置活动子图层
     * @returns {Object|null}
     */
    get activeLayer() {
        return this._activeLayer;
    }

    set activeLayer(value) {
        this._activeLayer = value;
        if (this._layer) {
            this._layer.activeLayer = value;
        }
    }

    /**
     * 获取图层实例
     * @returns {Object}
     */
    get instance() {
        return this._layer;
    }

}
