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

/**
 * 定义 MapGIS Common API 影像服务图层类
 *
 * @alias ImageryLayer
 *
 * @summary <用于加载和管理影像服务图层，支持栅格数据处理和渲染>
 */
export default class ImageryLayer {
    /**
     * 构造函数
     * @param {Object} options - 图层选项
     * @param {Object} options.map - 地图对象(mapboxgl.Map 实例)
     * @param {String} options.url - 服务地址
     * @param {String} [options.id] - 图层ID(可选,不传则自动生成)
     * @param {String} [options.title=''] - 图层标题
     * @param {String} [options.description=''] - 图层描述
     * @param {String} [options.copyright=''] - 版权所有
     * @param {Array|null} [options.bandIds=null] - 波段号
     * @param {String} [options.format='PNG'] - 返回图片格式 (PNG/JPG/MIXED)
     * @param {Number|null} [options.imageMaxHeight=null] - 图像最大高度
     * @param {Number|null} [options.imageMaxWidth=null] - 图像最大宽度
     * @param {String|null} [options.interpolation=null] - 重采样方式
     * @param {Object|null} [options.rasterFunction=null] - 栅格数据处理渲染规则
     * @param {Object|null} [options.serviceRasterInfo=null] - 栅格信息
     * @param {Object|null} [options.clippingArea=null] - 图层空间裁剪范围
     * @param {String} [options.renderMode='image'] - 影像展现形式 ('tile'/'image')
     * @param {Number} [options.imageWidth=512] - 影像宽度（renderMode为'tile'时生效）
     * @param {Number} [options.imageHeight=512] - 影像高度（renderMode为'tile'时生效）
     * @param {Object|null} [options.spatialReference=null] - 图层坐标系对象
     * @param {Object|null} [options.extent=null] - 图层的范围
     * @param {Number} [options.minScale=0] - 最小显示比例尺
     * @param {Number} [options.maxScale=0] - 最大显示比例尺
     * @param {Number} [options.opacity=1] - 图层透明度 (0-1)
     * @param {Boolean} [options.visible=true] - 图层可见性
     * @param {String} [options.tokenKey='token'] - Token键名
     * @param {String} [options.tokenValue=''] - Token值
     * @param {String} [options.tokenAttachType=''] - Token附加类型
     * @param {Object} [options.headers={}] - 设置服务请求头
     * @param {String} [options.httpMethod='GET'] - HTTP请求方式
     * @param {Object} [options.capabilities={}] - 图层支持能力
     * @param {Object} [options.extendProps={}] - 额外属性
     * @param {Object} [options.extensionOptions={}] - 初始化图层的额外参数
     */
    constructor(options) {
        /**
         * 地图对象
         * @type {Object}
         */
        this._map = options.map;

        this._layer = null

        /**
         * 服务地址
         * @type {String}
         */
        this._url = DataUtils.default(options.url, '');

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

        /**
         * 返回图片格式
         * @type {String}
         */
        this._format = DataUtils.default(options.format, 'PNG');

        /**
         * 表示服务导出的图像的最大高度
         * @type {Number|null}
         */
        this._imageMaxHeight = DataUtils.default(options.imageMaxHeight, null);

        /**
         * 表示服务导出的图像的最大宽度
         * @type {Number|null}
         */
        this._imageMaxWidth = DataUtils.default(options.imageMaxWidth, null);

        /**
         * 重采样方式
         * @type {String|null}
         */
        this._interpolation = DataUtils.default(options.interpolation, null);

        /**
         * 栅格数据处理渲染规则
         * @type {Object|null}
         */
        this._rasterFunction = DataUtils.default(options.rasterFunction, null);

        /**
         * 栅格信息
         * @type {Object|null}
         */
        this._serviceRasterInfo = DataUtils.default(options.serviceRasterInfo, null);

        /**
         * 图层空间裁剪范围
         * @type {Object|null}
         */
        this._clippingArea = DataUtils.default(options.clippingArea, null);

        /**
         * 影像的展现形式
         * @type {String}
         */
        this._renderMode = DataUtils.default(options.renderMode, 'image');

        /**
         * 影像的宽度
         * @type {Number}
         */
        this._imageWidth = DataUtils.default(options.imageWidth, 512);

        /**
         * 影像的高度
         * @type {Number}
         */
        this._imageHeight = DataUtils.default(options.imageHeight, 512);

        /**
         * 图层坐标系对象
         * @type {Object|null}
         */
        this._spatialReference = DataUtils.default(options.spatialReference, null);

        /**
         * 图层的范围
         * @type {Object|null}
         */
        this._extent = DataUtils.default(options.extent, null);

        /**
         * 最小显示比例尺
         * @type {Number}
         */
        this._minScale = DataUtils.default(options.minScale, 0);

        /**
         * 最大显示比例尺
         * @type {Number}
         */
        this._maxScale = DataUtils.default(options.maxScale, 0);

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

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

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

        /**
         * Token值
         * @type {String}
         */
        this._tokenValue = DataUtils.default(options.tokenValue, '');

        /**
         * Token附加类型
         * @type {String}
         */
        this._tokenAttachType = DataUtils.default(options.tokenAttachType, '');

        /**
         * 设置服务请求头
         * @type {Object}
         */
        this._headers = DataUtils.default(options.headers, {});

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

        /**
         * 图层支持能力
         * @type {Object}
         */
        this._capabilities = DataUtils.default(options.capabilities, {});

        /**
         * 额外属性
         * @type {Object}
         */
        this._extendProps = DataUtils.default(options.extendProps, {});

        /**
         * 初始化图层的额外参数
         * @type {Object}
         */
        this._extensionOptions = DataUtils.default(options.extensionOptions, {});

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

        /**
         * 图层加载状态: '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,
            bandIds: this._bandIds,
            format: this._format,
            imageMaxHeight: this._imageMaxHeight,
            imageMaxWidth: this._imageMaxWidth,
            interpolation: this._interpolation,
            rasterFunction: this._rasterFunction,
            serviceRasterInfo: this._serviceRasterInfo,
            clippingArea: this._clippingArea,
            renderMode: this._renderMode,
            imageWidth: this._imageWidth,
            imageHeight: this._imageHeight,
            title: this._title,
            description: this._description,
            copyright: this._copyright,
            minScale: this._minScale,
            maxScale: this._maxScale,
            opacity: this._opacity,
            visible: this._visible,
            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;
    }

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

    /**
     * 加载图层资源
     * @description 不加载图层到地图,仅获取图层信息
     * @returns {Promise<ImageryLayer>} 返回图层实例的 Promise
     */
    load() {
        return new Promise((resolve, reject) => {
            try {
                if (!this._layer) {
                    const opts = this._buildOptions();
                    // 引入 MapGIS Common API ImageryLayer 类
                    const { ImageryLayer } = zondy.layer;
                    const { initializeOptions, initializeCRS } = zondy.mapboxgl.util;

                    initializeOptions(opts);
                    initializeCRS(opts);

                    this._layer = new ImageryLayer(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.ImageryLayer 加载图层数据,并添加到 Mapbox GL 地图中
     * @returns {void}
     */
    loadLayer() {
        if (this.hasLayer()) return;

        const { ImageryLayer } = zondy.layer;
        const { initializeOptions, initializeCRS } = zondy.mapboxgl.util;

        const opts = this._buildOptions();
        initializeOptions(opts);
        initializeCRS(opts);

        const layer = new ImageryLayer(opts);
        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) {
        if (this._layer) {
            this._layer.visible = isShow;
        }
    }

    /**
     * 判断图层是否已加载
     * @returns {Boolean}
     */
    hasLayer() {
        if (this._layer && this._layer.isLoaded) {
            return true;
        }
        return false;
    }

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

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

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

    /**
     * 导出为json对象
     * @returns {Object} JSON对象
     */
    toJSON() {
        if (!this._layer) {
            console.warn('影像图层未加载');
            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 instance() {
        return this._layer;
    }
}
