import { Utils } from '../common/Utils'

import { ImageWrapType, ImageMappingType } from '../const';

import { BaseImageTexture } from './BaseImageTexture';



/**
 * CubeTexture - 立方体纹理
 * 
 * 用于创建和加载立方体纹理资源,支持从 URL 数组、对象或文件夹路径加载。
 * 
 * @class CubeTexture
 * @memberof THING
 * @extends THING.BaseImageTexture
 * @public
 * 
 * @example
 const cubeTexture = new THING.CubeTexture({
   url: {
     negx: './images/negx.jpg',
     negy: './images/negy.jpg',
     negz: './images/negz.jpg',
     posx: './images/posx.jpg',
     posy: './images/posy.jpg',
     posz: './images/posz.jpg',
   },
 });
 */
class CubeTexture extends BaseImageTexture {



	/**

	 * 构造立方体纹理

	 * @param {object} param 初始参数

	 * @param {string} param.url 立方体纹理的url

	 * @param {boolean} param.flipY 是否翻转y轴

	 * @param {THING.ImageWrapType} param.wrapType 纹理包裹类型

	 * @param {THING.ImageMappingType} param.mappingType 纹理映射类型

	 * @param {Function} param.onLoad 立方体纹理加载完成后的回调函数

	 * @param {Function} param.onProgress 立方体纹理加载进度的回调函数

	 * @param {Function} param.onError 立方体纹理加载失败后的回调函数
	 * @constructor
	 * @public
	 */

	constructor(param = {}) {

		super(param);

	}



	onLoad(param) {

		// Parse arguments



		let onLoad = Utils.parseValue(param['onLoad'], null);



		this._updateUrl();



		// Some features do not support in compressed texture

		this.flipY = Utils.parseValue(param['flipY'], false);

		this.wrapType = Utils.parseValue(param['wrapType'], ImageWrapType.ClampToEdge);

		this.mappingType = Utils.parseValue(param['mappingType'], ImageMappingType.CubeReflection);



		const data = Utils.parseValue(param['data'], null);



		if (data) {

			this._loadImages(data, onLoad);

		}

		else {

			this._parseUrl(param);

		}

	}



	_parseUrl(param) {

		const onLoad = Utils.parseValue(param['onLoad'], null);



		param = Utils.parseCubeTextureParams(param)



		this._url = param['url'];



		if (!this._url) {

			this.onNotifyComplete();

		}



		// load image url

		if (Utils.isArray(this._url)) {

			let promises = [];

			this._url.forEach(url => {

				promises.push(this._loadImageFileAsync(url, param));

			});



			Promise.all(promises).then(

				(images) => {

					this._loadImages(images, onLoad);

				},

				(ev) => {

					this.onTriggerErrorEvent(ev);

				}

			);

		}

		else if (Utils.isString(this._url)) {

			this._loadImageFile();

		}

	}



	_loadImages(image, onLoad) {

		this._image = image;



		// Check whether set the image format

		if (this._image.length > 0) {

			this._image.forEach((image) => {

				if (image.format) {

					this.colorFormat = image.format;

				}

			})

		}



		if (onLoad) {

			onLoad({ images: this });

		}



		this.onNotifyComplete();

	}



	_loadImageFileAsync(url, options) {

		const defaultOptions = {

			flipY: this.flipY,

			premultiplyAlpha: this.premultiplyAlpha,

			generateMipmaps: this.generateMipmaps,

			extensions: Utils.getCurrentApp().view.getExtensions()

		};



		const param = Object.assign({}, defaultOptions, options);



		return Utils.loadImageFile(

			url,

			null,

			null,

			null,

			param

		);

	}



	_loadImageFile() {

		Utils.loadImageFile(this._url,

			// Load

			(image) => {

				this._image = image;



				this.onFixupFromImage(image);



				if (onLoad) {

					onLoad({ images: this });

				}



				this.onNotifyComplete();

			},

			// Progress

			(ev) => {



			},

			// Error

			(ev) => {

				this.onTriggerErrorEvent(ev);

			},

			{

				flipY: this.flipY,

				premultiplyAlpha: this.premultiplyAlpha,

				generateMipmaps: this.generateMipmaps,

				extensions: Utils.getCurrentApp().view.getExtensions()

			}

		);

	}



	onCreateTextureResource() {

		let images = this._image;

		if (images) {

			// Image had been loaded

			return Utils.createObject('CubeTextureResource', { data: images, scene: this.app.scene.context, view: this.app.view });

		}

		else {

			let textureType = Utils.isString(this._url) ? "CompressedImage" : "ArrayImage";



			// Image is still loading, should replace it when it finished

			let textureResource = Utils.createObject('CubeTextureResource', { textureType, scene: this.app.scene.context, view: this.app.view });



			this.waitForComplete().then((images) => {

				if (images.resource) {

					// Replace texture image

					textureResource.setImages(images.resource);

				}

			});



			return textureResource;

		}

	}



	/**

	 * 获取指定索引的图像。

	 * @param {number} index 图像索引。

	 * @returns {object} 返回图像。

	 * @private

	 */

	getImageByIndex(index) {

		return this.textureResource.getImageByIndex(index);

	}



	// #region Accessors



	/**

	 * 获取/设置资源。

	 * @type {*}

	 * @private

	 */

	get resource() {

		return this._image;

	}

	set resource(value) {

		this._image = value;



		if (this.textureResource) {

			this.textureResource.setImages(value);

		}

	}



	/**

	 * 获取/设置图像。

	 * @type {Array<string>}

	 * @private

	 */

	get urls() {

		return this._url;

	}

	set urls(value) {

		this._setUrl(value);

	}



	// #endregion



	/**

	 * 检查是否是立方体纹理。

	 * @type {boolean}

	 */

	get isCubeTexture() {

		return true;

	}



}



export { CubeTexture }