import DataUtils from '../../../../mapboxgl/js/utils/DataUtils';

/**
 * 定义 MapGIS Common API Cesium3DTiles缓存图层类
 *
 * @alias Cesium3DTilesCacheLayer
 *
 * @summary <用于加载和管理Cesium 3D Tiles缓存图层，基于 MapGIS Client for JavaScript Common 模块>
 */
export default class Cesium3DTilesCacheLayer {
    /**
     * 构造函数
     * @param {Object} options - 图层选项
     */
    constructor(options) {
        /**
         * 地图对象
         * @type {Object}
         */
        this._map = options.map;

        /**
         * 视图对象
         * @type {Object}
         */
        this._view = options.view;

        /**
         * 服务链接
         * igs服务的3dTiles服务地址或tileset静态服务地址
         * 例如：
         * - IGS服务: http://webclient.smaryun.com:8089/igs/rest/services/Scene/大雁塔3DTilesServer/3DTilesServer
         * - 静态服务: http://webclient.smaryun.com:8200/3DData/ModelCache/3DTileset/1.0/OSGB-大雁塔_3dtiles_meshopt_ktx2/tileset.json
         * @type {String}
         */
        this._url = options.url || '';

        /**
         * 图层ID
         * @type {String}
         */
        this._id = options.id || 'cesium_3dtiles_cache_layer_' + new Date().getTime();

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

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

        /**
         * 版权所有
         * @type {String}
         */
        this._copyright = DataUtils.default(options.copyright, '');

        /**
         * 坐标系
         * @type {Object|null}
         */
        this._spatialReference = options.spatialReference || null;

        /**
         * 图层的范围
         * 从元信息或数据中获取，默认为null表示取不到范围
         * @type {Object|null}
         */
        this._extent = options.extent || null;

        /**
         * 模型外包盒
         * @type {Object|null}
         */
        this._boundingVolume = options.boundingVolume || null;

        /**
         * 服务名
         * @type {String}
         */
        this._sceneName = options.sceneName || '';

        /**
         * 服务包含的表字段数组
         * @type {Array}
         */
        this._fieldInfo = options.fieldInfo || [];

        /**
         * 是否开启模型缓存剖切封边
         * @type {Boolean}
         */
        this._fillClip = DataUtils.default(options.fillClip, false);

        /**
         * 是否支持生成剖面
         * @type {Boolean}
         */
        this._enableSection = DataUtils.default(options.enableSection, false);

        /**
         * 图层透明度 (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值
         * @type {String}
         */
        this._tokenValue = DataUtils.default(options.tokenValue, '');

        /**
         * Token附加类型
         * @type {String}
         */
        this._tokenAttachType = options.tokenAttachType || '';

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

        /**
         * HTTP请求方式
         * @type {String}
         */
        this._httpMethod = options.httpMethod || 'GET';

        /**
         * 图层支持能力
         * 图层支持能力分为客户端能力和服务端能力
         * 其中客户端能力包含cesium、leaflet、mapboxgl引擎能力
         * 默认图层客户端能力：所有引擎支持图层加载
         * 默认图层服务端能力为空
         * @type {Object}
         */
        this._capabilities = options.capabilities || {};

        /**
         * 额外属性
         * 当前图层对象上不支持的属性，二次开发用户希望挂在图层对像上的属性可以存储到该属性中
         * @type {Object}
         */
        this._extendProps = options.extendProps || {};

        /**
         * 初始化图层的额外参数
         * 可以通过该参数传入引擎原生的构造参数
         * 例如：{ autoReset: true } 开启自动跳转
         * @type {Object}
         */
        this._extensionOptions = options.extensionOptions || {};

        /**
         * 图层类型
         * @type {String}
         */
        this._type = options.type || 'cesium-3dtiles-cache-layer';

        /**
         * 是否加载完毕
         * @type {Boolean}
         */
        this._loaded = false;

        /**
         * 请求失败后的错误信息
         * toJSON方法不会导出该属性
         * @type {Object|null}
         */
        this._loadError = null;

        /**
         * 图层加载状态
         * @type {String}
         */
        this._loadStatus = 'not-loaded';

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

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

    /** 公有方法 **/

    /**
     * 加载图层资源
     * @returns {Promise} 返回Promise对象
     */
    load() {
        return new Promise((resolve, reject) => {
            if (this._loadStatus === 'loaded') {
                resolve({ layer: this });
                return;
            }

            this._loadStatus = 'loading';

            try {
                // 引入 MapGIS Common API Cesium3DTilesCacheLayer 类
                const { Cesium3DTilesCacheLayer } = zondy.layer;
                const { initializeOptions, initializeCRS } = zondy.mapboxgl.util;

                // 初始化选项和坐标系
                const options = this._buildOptions();
                initializeOptions(options);
                initializeCRS(options);

                // 创建Cesium3DTiles缓存图层实例
                this._instance = new Cesium3DTilesCacheLayer(options);

                // 监听图层加载完毕事件
                this._instance.on('layerview-created', (result) => {
                    this._loaded = true;
                    this._loadStatus = 'loaded';
                    this._loadError = null;

                    // 触发加载完成事件
                    this._emitEvent('layerview-created', result);

                    resolve({ layer: this });
                });

                // 监听图层加载失败事件
                this._instance.on('layerview-error', (error) => {
                    this._loaded = false;
                    this._loadStatus = 'error';
                    this._loadError = error;

                    this._emitEvent('layerview-error', error);
                    reject(error);
                });

                // 添加到地图
                if (this._map) {
                    this._map.add(this._instance);
                }

            } catch (error) {
                this._loaded = false;
                this._loadStatus = 'error';
                this._loadError = error;
                console.error('Cesium3DTiles缓存图层加载失败:', error);
                reject(error);
            }
        });
    }

    /**
     * 通过json构造Cesium3DTilesCacheLayer对象
     * @param {Object} json - JSON对象
     * @returns {Cesium3DTilesCacheLayer} Cesium3DTilesCacheLayer实例
     */
    static fromJSON(json) {
        const { Cesium3DTilesCacheLayer } = zondy.layer;
        const instance = Cesium3DTilesCacheLayer.fromJSON(json);
        return instance;
    }

    /**
     * 克隆并返回一个新图层
     * @returns {Cesium3DTilesCacheLayer} 新的图层对象
     */
    clone() {
        if (!this._instance) {
            console.warn('Cesium3DTiles缓存图层未加载，无法克隆');
            return null;
        }

        return this._instance.clone();
    }

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

        return this._instance.toJSON();
    }

    /**
     * 判断图层是否加载成功
     * @returns {Boolean} 图层是否加载成功
     */
    isLoaded() {
        return this._loaded;
    }

    /**
     * 刷新图层
     */
    refresh() {
        if (!this._instance) {
            console.warn('Cesium3DTiles缓存图层未加载');
            return;
        }

        this._instance.refresh();
    }

    /**
     * 销毁图层
     */
    destroy() {
        if (!this._instance) {
            return;
        }

        try {
            // 移除事件监听
            this._removeAllEventListeners();

            // 从地图中移除
            if (this._map) {
                this._map.remove(this._instance);
            }

            // 销毁图层实例
            this._instance.destroy();
            this._instance = null;
            this._loaded = false;
            this._loadStatus = 'not-loaded';
            this._loadError = null;

            this._emitEvent('layerview-remove', { layer: this });
        } catch (error) {
            console.error('Cesium3DTiles缓存图层销毁失败:', error);
        }
    }

    /**
     * 设置属性值
     * @param {String} path - 属性路径
     * @param {*} value - 属性值
     * @returns {Boolean} 是否设置成功
     */
    setProperty(path, value) {
        if (!this._instance) {
            console.warn('Cesium3DTiles缓存图层未加载');
            return false;
        }

        return this._instance.setProperty(path, value);
    }

    /**
     * 获取属性值
     * @param {String} path - 属性路径
     * @returns {*} 属性值
     */
    getProperty(path) {
        if (!this._instance) {
            console.warn('Cesium3DTiles缓存图层未加载');
            return undefined;
        }

        return this._instance.getProperty(path);
    }

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

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

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

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

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

        // 如果图层实例已存在，也注册到实例上
        if (this._instance) {
            this._instance.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._instance && callback) {
            this._instance.off(eventName, callback);
        }
    }

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

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

    /**
     * 设置图层ID
     * @param {String} value
     */
    set id(value) {
        this._id = value;
        if (this._instance) {
            this._instance.id = value;
        }
    }

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

    /**
     * 设置服务URL
     * @param {String} value
     */
    set url(value) {
        this._url = value;
        if (this._instance) {
            this._instance.url = value;
        }
    }

    /**
     * 获取图层标题
     * @returns {String}
     */
    get title() {
        return this._title;
    }

    /**
     * 设置图层标题
     * @param {String} value
     */
    set title(value) {
        this._title = value;
        if (this._instance) {
            this._instance.title = value;
        }
    }

    /**
     * 获取描述信息
     * @returns {String}
     */
    get description() {
        return this._description;
    }

    /**
     * 设置描述信息
     * @param {String} value
     */
    set description(value) {
        this._description = value;
        if (this._instance) {
            this._instance.description = value;
        }
    }

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

    /**
     * 设置版权信息
     * @param {String} value
     */
    set copyright(value) {
        this._copyright = value;
        if (this._instance) {
            this._instance.copyright = value;
        }
    }

    /**
     * 获取坐标系
     * @returns {Object|null}
     */
    get spatialReference() {
        return this._spatialReference;
    }

    /**
     * 设置坐标系
     * @param {Object} value
     */
    set spatialReference(value) {
        this._spatialReference = value;
        if (this._instance) {
            this._instance.spatialReference = value;
        }
    }

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

    /**
     * 设置图层范围
     * @param {Object} value
     */
    set extent(value) {
        this._extent = value;
        if (this._instance) {
            this._instance.extent = value;
        }
    }

    /**
     * 获取模型外包盒
     * @returns {Object|null}
     */
    get boundingVolume() {
        return this._boundingVolume;
    }

    /**
     * 设置模型外包盒
     * @param {Object} value
     */
    set boundingVolume(value) {
        this._boundingVolume = value;
        if (this._instance) {
            this._instance.boundingVolume = value;
        }
    }

    /**
     * 获取服务名
     * @returns {String}
     */
    get sceneName() {
        return this._sceneName;
    }

    /**
     * 设置服务名
     * @param {String} value
     */
    set sceneName(value) {
        this._sceneName = value;
        if (this._instance) {
            this._instance.sceneName = value;
        }
    }

    /**
     * 获取表字段数组
     * @returns {Array}
     */
    get fieldInfo() {
        return this._fieldInfo;
    }

    /**
     * 设置表字段数组
     * @param {Array} value
     */
    set fieldInfo(value) {
        this._fieldInfo = value;
        if (this._instance) {
            this._instance.fieldInfo = value;
        }
    }

    /**
     * 获取是否开启剖切封边
     * @returns {Boolean}
     */
    get fillClip() {
        return this._fillClip;
    }

    /**
     * 设置是否开启剖切封边
     * @param {Boolean} value
     */
    set fillClip(value) {
        this._fillClip = value;
        if (this._instance) {
            this._instance.fillClip = value;
        }
    }

    /**
     * 获取是否支持生成剖面
     * @returns {Boolean}
     */
    get enableSection() {
        return this._enableSection;
    }

    /**
     * 设置是否支持生成剖面
     * @param {Boolean} value
     */
    set enableSection(value) {
        this._enableSection = value;
        if (this._instance) {
            this._instance.enableSection = value;
        }
    }

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

    /**
     * 设置图层透明度
     * @param {Number} value
     */
    set opacity(value) {
        this._opacity = value;
        if (this._instance) {
            this._instance.opacity = value;
        }
    }

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

    /**
     * 设置图层可见性
     * @param {Boolean} value
     */
    set visible(value) {
        this._visible = value;
        if (this._instance) {
            this._instance.visible = value;
        }
    }

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

    /**
     * 设置最小显示比例尺
     * @param {Number} value
     */
    set minScale(value) {
        this._minScale = value;
        if (this._instance) {
            this._instance.minScale = value;
        }
    }

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

    /**
     * 设置最大显示比例尺
     * @param {Number} value
     */
    set maxScale(value) {
        this._maxScale = value;
        if (this._instance) {
            this._instance.maxScale = value;
        }
    }

    /**
     * 获取Token键名
     * @returns {String}
     */
    get tokenKey() {
        return this._tokenKey;
    }

    /**
     * 设置Token键名
     * @param {String} value
     */
    set tokenKey(value) {
        this._tokenKey = value;
        if (this._instance) {
            this._instance.tokenKey = value;
        }
    }

    /**
     * 获取Token值
     * @returns {String}
     */
    get tokenValue() {
        return this._tokenValue;
    }

    /**
     * 设置Token值
     * @param {String} value
     */
    set tokenValue(value) {
        this._tokenValue = value;
        if (this._instance) {
            this._instance.tokenValue = value;
        }
    }

    /**
     * 获取Token附加类型
     * @returns {String}
     */
    get tokenAttachType() {
        return this._tokenAttachType;
    }

    /**
     * 设置Token附加类型
     * @param {String} value
     */
    set tokenAttachType(value) {
        this._tokenAttachType = value;
        if (this._instance) {
            this._instance.tokenAttachType = value;
        }
    }

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

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

    /**
     * 获取HTTP请求方式
     * @returns {String}
     */
    get httpMethod() {
        return this._httpMethod;
    }

    /**
     * 设置HTTP请求方式
     * @param {String} value
     */
    set httpMethod(value) {
        this._httpMethod = value;
        if (this._instance) {
            this._instance.httpMethod = value;
        }
    }

    /**
     * 获取能力配置
     * @returns {Object}
     */
    get capabilities() {
        return this._capabilities;
    }

    /**
     * 设置能力配置
     * @param {Object} value
     */
    set capabilities(value) {
        this._capabilities = value;
        if (this._instance) {
            this._instance.capabilities = value;
        }
    }

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

    /**
     * 设置扩展属性
     * @param {Object} value
     */
    set extendProps(value) {
        this._extendProps = value;
        if (this._instance) {
            this._instance.extendProps = value;
        }
    }

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

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

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

    /**
     * 获取是否加载完毕
     * @returns {Boolean}
     */
    get loaded() {
        return this._loaded;
    }

    /**
     * 获取加载错误信息
     * @returns {Object|null}
     */
    get loadError() {
        return this._loadError;
    }

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

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

    /** ==================== 私有方法 ==================== */

    /**
     * 构建图层配置选项
     * @returns {Object} 配置选项对象
     */
    _buildOptions() {
        const options = {
            url: this._url,
            title: this._title,
            type: this._type,
            description: this._description,
            copyright: this._copyright,
            boundingVolume: this._boundingVolume,
            sceneName: this._sceneName,
            fieldInfo: this._fieldInfo,
            fillClip: this._fillClip,
            enableSection: this._enableSection,
            opacity: this._opacity,
            visible: this._visible,
            minScale: this._minScale,
            maxScale: this._maxScale,
            tokenKey: this._tokenKey,
            tokenValue: this._tokenValue,
            tokenAttachType: this._tokenAttachType,
            headers: this._headers,
            httpMethod: this._httpMethod,
            capabilities: this._capabilities,
            extendProps: this._extendProps,
            extensionOptions: this._extensionOptions
        };

        // 如果指定了坐标系，添加到选项中
        if (this._spatialReference) {
            options.spatialReference = this._spatialReference;
        }

        // 如果指定了范围，添加到选项中
        if (this._extent) {
            options.extent = this._extent;
        }

        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._instance) {
            Object.keys(this._eventListeners).forEach(eventName => {
                this._eventListeners[eventName].forEach(callback => {
                    this._instance.off(eventName, callback);
                });
            });
        }
        this._eventListeners = {};
    }
}
