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

/**
 * 定义 MapGIS Common API ArcGIS矢量瓦片图层类
 *
 * @alias ArcGISVectorTileLayer
 *
 * @summary <用于加载和管理ArcGIS矢量瓦片服务图层，基于 MapGIS Client for JavaScript Common 模块>
 * @description 该类负责具体的图层操作逻辑，包括图层的加载、显示/隐藏、移除等。
 *              底层通过 LayerProvider 与 Mapbox GL JS 进行交互。
 */
export default class ArcGISVectorTileLayer {
    /**
     * 构造函数
     * @param {Object} options - 图层配置选项
     * @param {Object} options.map - 地图对象
     * @param {String} [options.url] - 服务基地址或样式文件地址，和style参数二者选其一
     *        支持的服务如下：
     *        1. IGS发布的ArcGIS服务: http://{ip}:{port}/igs/rest/services/{folder}/{serviceName}/arcgis/VectorTileServer
     *        2. ArcGIS: https://{ip}:{port}/arcgis/rest/services/{serviceName}/VectorTileServer
     *        3. 矢量瓦片样式文件地址: 'https://jsapi.maps.arcgis.com/sharing/rest/content/items/xxx/resources/styles/root.json'
     * @param {Object} [options.style] - 矢量瓦片样式对象，和url参数二者选其一
     * @param {String} [options.id] - 图层ID（可选，不传则自动生成）
     * @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 {String} [options.labelsRenderMode='off-screen'] - 矢量瓦片注记渲染模式，仅在三维上有效
     *        on-screen: 使用Cesium接口实时渲染注记；off-screen: 使用矢量瓦片来绘制注记
     * @param {Object} [options.clippingArea] - 图层空间裁剪范围
     * @param {Object} [options.spatialReference] - 坐标系
     * @param {Boolean} [options.isFlyTo=true] - 是否自动跳转到图层范围
     */
    constructor(options) {
        /**
         * 地图对象
         * @type {Object}
         */
        this._map = options.map;

        /**
         * 底层图层实例
         * @type {Object|null}
         */
        this._layer = null;

        /**
         * 服务基地址或样式文件地址
         * @type {String|null}
         */
        this._url = options.url || null;

        /**
         * 矢量瓦片样式对象，和url参数二者选其一
         * @type {Object|null}
         */
        this._style = options.style || null;

        /**
         * 图层ID
         * @type {String}
         */
        this._layerId = DataUtils.default(options.id, 'arcgis_vector_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 {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, '');

        /**
         * 指定矢量瓦片注记的渲染模式，仅在三维上有效
         * on-screen: 使用Cesium接口实时渲染注记
         * off-screen: 使用矢量瓦片来绘制注记
         * @type {String}
         */
        this._labelsRenderMode = DataUtils.default(options.labelsRenderMode, 'off-screen');

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

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

        /**
         * 坐标系
         * 二维支持4326(包括4490、4214、4610)、3857以及EPSG支持的自定义坐标系
         * 三维仅支持4326(包括4490、4214、4610)以及3857坐标系
         * 会自动读取元信息上的坐标系，不需要用户指定
         * @type {Object|null}
         */
        this._spatialReference = DataUtils.default(options.spatialReference, new zondy.SpatialReference({
            wkid: mapConfig.map_srid_code
        }));

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

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

        /**
         * 是否自动跳转到图层范围
         * @type {Boolean}
         */
        this._isFlyTo = DataUtils.default(options.isFlyTo, true);

        /**
         * 额外属性，当前图层对象上不支持的属性
         * @type {Object}
         */
        this._extendProps = {};

        /**
         * 初始化图层的额外参数，可以通过该参数传入引擎原生的构造参数
         * @type {Object}
         */
        this._extensionOptions = {};

        /**
         * 设置服务请求头
         * @type {Object}
         */
        this._headers = {};

        /**
         * mvt矢量瓦片相对坐标范围，默认为4096
         * @type {Number}
         */
        this._mvtExtent = 4096;
    }

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

    /**
     * 加载图层资源
     * @description 不加载图层到地图，仅获取图层信息
     * @returns {Promise<ArcGISVectorTileLayer>} 返回图层实例的 Promise
     *
     * @example
     * const layer = new ArcGISVectorTileLayer({
     *     url: 'https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer'
     * });
     * 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.ArcGISVectorTileLayer(opts);
                }

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

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

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

    /**
     * 加载图层到地图
     * @description 创建 zondy.layer.ArcGISVectorTileLayer 实例并添加到 MapGIS 地图中
     * @returns {void}
     *
     * @example
     * const layer = new ArcGISVectorTileLayer({
     *     type: 'arcgis-vector-tile',
     *     map: mapboxMap,
     *     url: 'https://xxx/arcgis/rest/services/xxx/VectorTileServer'
     * });
     * layer.loadLayer();
     */
    loadLayer() {
        if (this.hasLayer()) return;

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

    /**
     * 添加图层到 MapGIS 地图
     */
    addToMapGisMap() {
        this._map.add(this._layer)
    }

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

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

    /**
     * 移除图层
     */
    removeLayer() {
        // 移除事件监听
        this._removeAllEventListeners();

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

        this._loadStatus = 'unloaded';
        this._emitEvent('layerview-remove', { layer: this });

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

    /** ==================== Style Layer Methods ==================== */

    /**
     * 通过矢量瓦片样式图层的id，找到对应的矢量瓦片样式图层对象
     * @param {String} styleLayerId - 样式图层ID
     * @returns {Object|null} 样式图层对象或null
     */
    getStyleLayer(styleLayerId) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return null;
        }

        return this._layer.getStyleLayer(styleLayerId);
    }

    /**
     * 通过矢量瓦片样式图层的id，找到对应的矢量瓦片样式图层的序号
     * @param {String} styleLayerId - 样式图层ID
     * @returns {Number} 样式图层序号
     */
    getStyleLayerIndex(styleLayerId) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return -1;
        }

        return this._layer.getStyleLayerIndex(styleLayerId);
    }

    /**
     * 通过矢量瓦片样式图层的序号，找到对应的矢量瓦片样式图层的id
     * @param {Number} index - 样式图层序号
     * @returns {String} 样式图层ID
     */
    getStyleLayerId(index) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return '';
        }

        return this._layer.getStyleLayerId(index);
    }

    /**
     * 设置样式图层属性对象
     * @param {String} styleLayerId - 样式图层ID
     * @param {Object} properties - 属性对象
     */
    setStyleLayer(styleLayerId, properties) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return;
        }

        this._layer.setStyleLayer(styleLayerId, properties);
    }

    /**
     * 删除样式图层
     * @param {String} styleLayerId - 样式图层ID
     */
    deleteStyleLayer(styleLayerId) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return;
        }

        this._layer.deleteStyleLayer(styleLayerId);
    }

    /**
     * 设置样式图层可见性
     * @param {String} styleLayerId - 样式图层ID
     * @param {Boolean} visible - 是否可见
     */
    setStyleLayerVisibility(styleLayerId, visible) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return;
        }

        this._layer.setStyleLayerVisibility(styleLayerId, visible);
    }

    /**
     * 获取样式图层可见性
     * @param {String} styleLayerId - 样式图层ID
     * @returns {Boolean} 是否可见
     */
    getStyleLayerVisibility(styleLayerId) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return false;
        }

        return this._layer.getStyleLayerVisibility(styleLayerId);
    }

    /**
     * 获取样式图层绘制属性
     * @param {String} styleLayerId - 样式图层ID
     * @returns {Object} 绘制属性
     */
    getPaintProperties(styleLayerId) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return {};
        }

        return this._layer.getPaintProperties(styleLayerId);
    }

    /**
     * 设置样式图层绘制属性
     * @param {String} styleLayerId - 样式图层ID
     * @param {Object} properties - 绘制属性
     */
    setPaintProperties(styleLayerId, properties) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return;
        }

        this._layer.setPaintProperties(styleLayerId, properties);
    }

    /**
     * 获取样式图层布局属性
     * @param {String} styleLayerId - 样式图层ID
     * @returns {Object} 布局属性
     */
    getLayoutProperties(styleLayerId) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return {};
        }

        return this._layer.getLayoutProperties(styleLayerId);
    }

    /**
     * 设置样式图层布局属性
     * @param {String} styleLayerId - 样式图层ID
     * @param {Object} properties - 布局属性
     */
    setLayoutProperties(styleLayerId, properties) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return;
        }

        this._layer.setLayoutProperties(styleLayerId, properties);
    }

    /**
     * 设置样式图层的扩展属性
     * @param {String} styleLayerId - 样式图层ID
     * @param {String} propertyName - 扩展属性名
     * @param {*} propertyValue - 扩展属性值
     */
    setExtendProperties(styleLayerId, propertyName, propertyValue) {
        if (!this._layer) {
            console.warn('ArcGIS矢量瓦片图层未加载');
            return;
        }

        if (this._layer.setExtendProperties) {
            this._layer.setExtendProperties(styleLayerId, propertyName, propertyValue);
        }
    }

    /** ==================== Serialization ==================== */

    /**
     * 转换为 JSON 对象
     * @returns {Object} JSON 对象
     *
     * @example
     * const json = layer.toJSON();
     * console.log(json);
     */
    toJSON() {
        return {
            url: this._url,
            style: this._style,
            id: this._layerId,
            opacity: this._opacity,
            visible: this._visible,
            minScale: this._minScale,
            maxScale: this._maxScale,
            tokenKey: this._tokenKey,
            tokenValue: this._tokenValue,
            labelsRenderMode: this._labelsRenderMode,
            clippingArea: this._clippingArea,
            spatialReference: this._spatialReference ? (this._spatialReference.toJSON ? this._spatialReference.toJSON() : this._spatialReference) : null,
            type: this._type,
            extendProps: this._extendProps,
            extensionOptions: this._extensionOptions,
            headers: this._headers,
            mvtExtent: this._mvtExtent
        };
    }

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

    /**
     * 通过传入的 JSON 构造并返回一个新的 ArcGISVectorTileLayer 实例
     * @static
     * @param {Object} json - JSON 对象
     * @returns {ArcGISVectorTileLayer} 新的 ArcGISVectorTileLayer 实例
     *
     * @example
     * const json = {
     *     url: 'https://xxx/arcgis/rest/services/xxx/VectorTileServer'
     * };
     * const layer = ArcGISVectorTileLayer.fromJSON(json);
     */
    static fromJSON(json) {
        if (!json) {
            throw new Error('JSON 对象不能为空');
        }

        return new ArcGISVectorTileLayer({
            url: json.url,
            style: json.style,
            id: json.id,
            opacity: json.opacity,
            visible: json.visible,
            minScale: json.minScale,
            maxScale: json.maxScale,
            tokenKey: json.tokenKey,
            tokenValue: json.tokenValue,
            labelsRenderMode: json.labelsRenderMode,
            clippingArea: json.clippingArea,
            spatialReference: json.spatialReference,
            type: json.type,
            extendProps: json.extendProps,
            extensionOptions: json.extensionOptions,
            headers: json.headers,
            mvtExtent: json.mvtExtent
        });
    }

    /**
     * 刷新图层
     */
    refresh() {
        if (!this._layer) {
            console.warn('图层未加载，请先调用 load() 或 loadLayer()');
            return;
        }

        this._layer.refresh();
    }

    /** ==================== Setters ==================== */

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

        if (this._layer) {
            this._layer.opacity = opacity;
        }
    }

    /**
     * 设置图层显隐
     * @param {Boolean} visible - 是否可见
     */
    setVisible(visible) {
        this._visible = visible;

        if (this._layer) {
            this._layer.visible = visible;
        }
    }

    /** ==================== Event Handlers ==================== */

    /**
     * 注册事件监听器
     * @param {String} eventName - 事件名称
     * @param {Function} callback - 回调函数
     */
    on(eventName, callback) {
        if (!this._eventListeners[eventName]) {
            this._eventListeners[eventName] = [];
        }
        this._eventListeners[eventName].push(callback);

        // 如果图层实例已存在，也注册到实例上
        if (this._layer) {
            this._layer.on(eventName, callback);
        }
    }

    /**
     * 移除事件监听器
     * @param {String} eventName - 事件名称
     * @param {Function} callback - 回调函数
     */
    off(eventName, callback) {
        if (this._eventListeners[eventName]) {
            this._eventListeners[eventName] = this._eventListeners[eventName].filter(
                cb => cb !== callback
            );
        }

        // 如果图层实例已存在，也从实例上移除
        if (this._layer && callback) {
            this._layer.off(eventName, callback);
        }
    }

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

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

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

    /**
     * 获取加载状态
     * @returns {String}
     */
    get loadStatus() {
        return this._loadStatus;
    }

    /**
     * 获取图层类型
     * @returns {String}
     */
    get type() {
        return this._type;
    }

    /**
     * 获取透明度
     * @returns {Number}
     */
    get opacity() {
        return this._opacity;
    }

    /**
     * 获取可见性
     * @returns {Boolean}
     */
    get visible() {
        return this._visible;
    }

    /**
     * 获取最小比例尺
     * @returns {Number}
     */
    get minScale() {
        return this._minScale;
    }

    /**
     * 获取最大比例尺
     * @returns {Number}
     */
    get maxScale() {
        return this._maxScale;
    }

    /**
     * 获取所有子图层
     * @returns {Array}
     */
    get allSublayers() {
        return this._layer ? this._layer.allSublayers : [];
    }

    /**
     * 获取图层描述
     * @returns {String}
     */
    get description() {
        return this._layer ? this._layer.description : '';
    }

    /**
     * 获取版权信息
     * @returns {String}
     */
    get copyright() {
        return this._layer ? this._layer.copyright : '';
    }

    /**
     * 获取图层范围
     * @returns {Object|null}
     */
    get extent() {
        return this._layer ? this._layer.extent : null;
    }

    /**
     * 获取图层能力
     * @returns {Object|null}
     */
    get capabilities() {
        return this._layer ? this._layer.capabilities : null;
    }

    /**
     * 获取当前的矢量瓦片样式信息
     * @returns {Object|null}
     */
    get currentStyleInfo() {
        return this._layer ? this._layer.currentStyleInfo : null;
    }

    /**
     * 获取瓦片切图信息
     * @returns {Object|null}
     */
    get tileInfo() {
        return this._layer ? this._layer.tileInfo : null;
    }

    /**
     * 获取图层名称
     * @returns {String}
     */
    get title() {
        return this._layer ? this._layer.title : '';
    }

    /**
     * 获取额外属性
     * @returns {Object}
     */
    get extendProps() {
        return this._extendProps;
    }

    /**
     * 设置额外属性
     * @param {Object} value
     */
    set extendProps(value) {
        this._extendProps = value;
        if (this._layer) {
            this._layer.extendProps = value;
        }
    }

    /**
     * 获取扩展选项
     * @returns {Object}
     */
    get extensionOptions() {
        return this._extensionOptions;
    }

    /**
     * 设置扩展选项
     * @param {Object} value
     */
    set extensionOptions(value) {
        this._extensionOptions = value;
        if (this._layer) {
            this._layer.extensionOptions = value;
        }
    }

    /**
     * 获取请求头
     * @returns {Object}
     */
    get headers() {
        return this._headers;
    }

    /**
     * 设置请求头
     * @param {Object} value
     */
    set headers(value) {
        this._headers = value;
        if (this._layer) {
            this._layer.headers = value;
        }
    }

    /**
     * 获取注记渲染模式
     * @returns {String}
     */
    get labelsRenderMode() {
        return this._labelsRenderMode;
    }

    /**
     * 获取裁剪范围
     * @returns {Object|null}
     */
    get clippingArea() {
        return this._clippingArea;
    }

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

    /** ==================== Private Methods ==================== */

    /**
     * 构建图层配置选项
     * @returns {Object} 配置选项对象
     */
    _buildOptions() {
        const options = {
            type: this._type,
            id: this._layerId,
            opacity: this._opacity,
            visible: this._visible,
            minScale: this._minScale,
            maxScale: this._maxScale,
            tokenKey: this._tokenKey,
            tokenValue: this._tokenValue,
            labelsRenderMode: this._labelsRenderMode,
            clippingArea: this._clippingArea,
            spatialReference: this._spatialReference,
            extendProps: this._extendProps,
            extensionOptions: this._extensionOptions,
            headers: this._headers
        };

        // url和style二者选其一
        if (this._url) {
            options.url = this._url;
        } else if (this._style) {
            options.style = this._style;
        }

        return options;
    }

    /**
     * 触发事件
     * @param {String} eventName - 事件名称
     * @param {*} data - 事件数据
     */
    _emitEvent(eventName, data) {
        if (this._eventListeners[eventName]) {
            this._eventListeners[eventName].forEach(callback => {
                try {
                    callback(data);
                } catch (error) {
                    console.error(`事件 ${eventName} 回调执行失败:`, error);
                }
            });
        }
    }

    /**
     * 移除所有事件监听器
     */
    _removeAllEventListeners() {
        if (this._layer) {
            Object.keys(this._eventListeners).forEach(eventName => {
                this._eventListeners[eventName].forEach(callback => {
                    this._layer.off(eventName, callback);
                });
            });
        }
        this._eventListeners = {};
    }
}
