import { Utils } from '../common/Utils'
import { ImageWrapType, ImageMappingType, ImageFilterType, ImageColorFormat, ImageEncodingType } from '../const';
import { BaseResource } from './BaseResource';

const __ = {
	private: Symbol('private'),
}

/**
 * @class BaseTexture
 * 基础纹理资源。
 * @memberof THING
 * @extends THING.BaseResource
 * @public
 */
class BaseTexture extends BaseResource {

	/**
	 * 基础纹理资源构造函数,用于初始化纹理的各种参数。
	 * @param {object} param - 初始参数对象,包含纹理的配置选项。
	 * @param {string} [param.colorFormat=THING.ImageColorFormat.RGBA] - 纹理的颜色格式,默认为THING.ImageColorFormat.RGBA。
	 * @param {number} [param.anisotropy=THING.App.current.renderCapabilities.maxAnisotropy] - 纹理的各向异性过滤级别,默认为应用程序的最大各向异性。
	 * @param {string} [param.wrapTypeS=THING.ImageWrapType.Repeat] - 纹理在S轴的包裹方式,默认为THING.ImageWrapType.Repeat。
	 * @param {string} [param.wrapTypeT=THING.ImageWrapType.Repeat] - 纹理在T轴的包裹方式,默认为THING.ImageWrapType.Repeat。
	 * @param {string} [param.mappingType=THING.ImageMappingType.UV] - 纹理的映射类型,默认为THING.ImageMappingType.UV。
	 * @param {boolean} [param.flipY=true] - 是否在Y轴翻转纹理,默认为true。
	 * @param {boolean} [param.premultiplyAlpha=false] - 是否预乘Alpha通道,默认为false。
	 * @param {boolean} [param.generateMipmaps=true] - 是否生成Mipmaps,默认为true。
	 * @param {string} [param.minFilterType] - 纹理的最小过滤类型,默认为根据是否生成Mipmaps选择的过滤类型。
	 * @param {string} [param.magFilterType=THING.ImageFilterType.LinearFilter] - 纹理的放大过滤类型,默认为THING.ImageFilterType.LinearFilter。
	 * @param {string} [param.encoding=null] - 纹理的编码类型,默认为null。
	 * @param {Function} [param.onUpdateSampler] - 纹理更新采样器时的回调函数。
	 */
	constructor(param = {}) {
		super(param);

		this[__.private] = {};
		let _private = this[__.private];

		_private.colorFormat = Utils.parseValue(param['colorFormat'], ImageColorFormat.RGBA);
		_private.anisotropy = Utils.parseValue(param['anisotropy'], 16);
		_private.wrapTypeS = Utils.parseValue(param['wrapTypeS'] || param['wrapType'], ImageWrapType.Repeat);
		_private.wrapTypeT = Utils.parseValue(param['wrapTypeT'] || param['wrapType'], ImageWrapType.Repeat);
		_private.mappingType = Utils.parseValue(param['mappingType'], ImageMappingType.UV);
		_private.flipY = Utils.parseValue(param['flipY'], true);
		_private.premultiplyAlpha = Utils.parseValue(param['premultiplyAlpha'], false);
		_private.generateMipmaps = Utils.parseValue(param['generateMipmaps'], true);
		_private.minFilterType = Utils.parseValue(param['minFilterType'], _private.generateMipmaps ? ImageFilterType.LinearMipmapLinearFilter : ImageFilterType.LinearFilter);
		_private.magFilterType = Utils.parseValue(param['magFilterType'], ImageFilterType.LinearFilter);
		_private.encoding = Utils.parseValue(param['encoding'], null);

		_private.onUpdateSampler = param['onUpdateSampler'];
	}

	// #region Private

	_updateSampler() {
		let _private = this[__.private];

		let onUpdateSampler = _private.onUpdateSampler;
		if (onUpdateSampler) {
			onUpdateSampler(this, {
				minFilter: _private.minFilterType,
				magFilter: _private.magFilterType,
				wrapS: _private.wrapTypeS,
				wrapT: _private.wrapTypeT,
				mappingType: _private.mappingType
			});
		}
	}

	_updateTextureResource() {
		let _private = this[__.private];

		let textureResource = this.context;
		if (!textureResource) {
			return;
		}

		textureResource.setWrapS(_private.wrapTypeS);
		textureResource.setWrapT(_private.wrapTypeT);
		textureResource.setMapping(_private.mappingType);
		textureResource.setColorFormat(_private.colorFormat);
		textureResource.setAnisotropy(_private.anisotropy);
		textureResource.setMinFilter(_private.minFilterType);
		textureResource.setMagFilter(_private.magFilterType);
		textureResource.enable('FlipY', _private.flipY);
		textureResource.enable('PremultiplyAlpha', _private.premultiplyAlpha);
		textureResource.enable('GenerateMipmaps', _private.generateMipmaps);

		if (_private.encoding) {
			textureResource.setEncoding(_private.encoding);
		}
	}

	// #endregion

	// #region Overrides

	onCreateTextureResource() {

	}

	// #endregion

	/**
	 * Get texture resource.
	 * @returns {object} 返回纹理资源。
	 * @private
	 */
	getTextureResource() {
		if (!this.context) {
			this.setContext(this.onCreateTextureResource());

			this._updateTextureResource();
		}

		return this.context;
	}

	/**
	 * 复制纹理。
	 * @param {THING.BaseTexture} source 源纹理。
	 * @returns {THING.BaseTexture} 返回当前纹理。
	 * @public
	 */
	copy(source) {
		let _private = this[__.private];

		_private.colorFormat = source.colorFormat;
		_private.anisotropy = source.anisotropy;
		_private.wrapTypeS = source.wrapTypeS;
		_private.wrapTypeT = source.wrapTypeT;
		_private.mappingType = source.mappingType;
		_private.minFilterType = source.minFilterType;
		_private.magFilterType = source.magFilterType;
		_private.flipY = source.flipY;
		_private.premultiplyAlpha = source.premultiplyAlpha;
		_private.generateMipmaps = source.generateMipmaps;
		_private.encoding = source.encoding;

		this._updateSampler();

		return this;
	}

	// #region Accessors

	/**
	 * Get texture resource.
	 * @type {object}
	 * @private
	 */
	get textureResource() {
		return this.context;
	}

	/**
	 * Get/Set the update sampler callback function.
	 * @type {Function}
	 * @private
	 */
	get onUpdateSampler() {
		let _private = this[__.private];

		return _private.onUpdateSampler;
	}
	set onUpdateSampler(value) {
		let _private = this[__.private];

		_private.onUpdateSampler = value;
	}

	/**
	 * 获取/设置颜色格式。
	 * @type {number}
	 * @public
	 */
	get colorFormat() {
		let _private = this[__.private];

		return _private.colorFormat;
	}
	set colorFormat(value) {
		let _private = this[__.private];
		if (_private.colorFormat != value) {
			_private.colorFormat = value;
			this._updateTextureResource();
		}
	}

	/**
	 * 获取/设置各向异性。
	 * @type {number}
	 * @public
	 */
	get anisotropy() {
		let _private = this[__.private];

		return _private.anisotropy;
	}
	set anisotropy(value) {
		let _private = this[__.private];
		if (_private.anisotropy != value) {
			_private.anisotropy = value;
			this._updateTextureResource();
		}
	}

	/**
	 * 获取/设置S轴的包裹方式。
	 * @type {ImageWrapType}
	 * @public
	 */
	get wrapTypeS() {
		let _private = this[__.private];

		return _private.wrapTypeS;
	}
	set wrapTypeS(value) {
		let _private = this[__.private];
		if (_private.wrapTypeS != value) {
			_private.wrapTypeS = value;
			this._updateTextureResource();
			this._updateSampler();
		}
	}

	/**
	 * 获取/设置T轴的包裹方式。
	 * @type {ImageWrapType}
	 * @public
	 */
	get wrapTypeT() {
		let _private = this[__.private];

		return _private.wrapTypeT;
	}
	set wrapTypeT(value) {
		let _private = this[__.private];
		if (_private.wrapTypeT != value) {
			_private.wrapTypeT = value;
			this._updateTextureResource();
			this._updateSampler();
		}
	}

	/**
	 * 获取/设置S轴和T轴的包裹方式。
	 * @type {ImageWrapType}
	 * @public
	 */
	set wrapType(value) {
		let _private = this[__.private];
		if (_private.wrapTypeS != value || _private.wrapTypeT != value) {
			_private.wrapTypeS = value;
			_private.wrapTypeT = value;

			this._updateTextureResource();
			this._updateSampler();
		}
	}

	/**
	 * 获取/设置映射类型。
	 * @type {ImageMappingType}
	 * @public
	 */
	get mappingType() {
		let _private = this[__.private];

		return _private.mappingType;
	}
	set mappingType(value) {
		let _private = this[__.private];
		if (_private.mappingType != value) {
			_private.mappingType = value;
			this._updateTextureResource();
			this._updateSampler();
		}
	}

	/**
	 * 获取/设置最小过滤类型。
	 * @type {ImageFilterType}
	 * @public
	 */
	get minFilterType() {
		let _private = this[__.private];

		return _private.minFilterType;
	}
	set minFilterType(value) {
		let _private = this[__.private];
		if (_private.minFilterType != value) {
			_private.minFilterType = value;
			this._updateTextureResource();
			this._updateSampler();
		}
	}

	/**
	 * 获取/设置最大过滤类型。
	 * @type {ImageFilterType}
	 * @public
	 */
	get magFilterType() {
		let _private = this[__.private];

		return _private.magFilterType;
	}
	set magFilterType(value) {
		let _private = this[__.private];
		if (_private.magFilterType != value) {
			_private.magFilterType = value;
			this._updateTextureResource();
			this._updateSampler();
		}
	}

	/**
	 * 获取/设置是否在Y轴翻转。
	 * @type {boolean}
	 * @public
	 */
	get flipY() {
		let _private = this[__.private];

		return _private.flipY;
	}
	set flipY(value) {
		let _private = this[__.private];
		if (_private.flipY != value) {
			_private.flipY = value;
			this._updateTextureResource();
		}
	}

	/**
	 * 获取/设置是否预乘Alpha通道。
	 * @type {boolean}
	 * @public
	 */
	get premultiplyAlpha() {
		let _private = this[__.private];

		return _private.premultiplyAlpha;
	}
	set premultiplyAlpha(value) {
		let _private = this[__.private];
		if (_private.premultiplyAlpha != value) {
			_private.premultiplyAlpha = value;
			this._updateTextureResource();
		}
	}

	/**
	 * 获取/设置是否生成Mipmaps。
	 * @type {boolean}
	 * @public
	 */
	get generateMipmaps() {
		let _private = this[__.private];

		return _private.generateMipmaps;
	}
	set generateMipmaps(value) {
		let _private = this[__.private];
		if (_private.generateMipmaps != value) {
			_private.generateMipmaps = value;
			this._updateTextureResource();
		}
	}

	/**
	 * 获取/设置编码类型。
	 * @type {ImageEncodingType}
	 * @public
	 */
	get encoding() {
		let _private = this[__.private];

		return _private.encoding;
	}
	set encoding(value) {
		let _private = this[__.private];
		if (_private.encoding != value) {
			_private.encoding = value;
			this._updateTextureResource();
		}
	}

	// #endregion

	/**
	 * 检查类类型。
	 * @type {boolean}
	 * @public
	 */
	get isBaseTexture() {
		return true;
	}

	// #endregion

}

export { BaseTexture }