import { ObjectProxy } from '@uino/base-thing';

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

import { BaseComponent } from './BaseComponent';

import { FogType } from '../const';



const __ = {

	private: Symbol('private'),

}



/**
 * CameraFogComponent - 相机雾效组件
 *
 * 用于管理相机的雾效,可设置雾的颜色、密度和衰减范围。
 * @class CameraFogComponent
 * @memberof THING
 * @extends THING.BaseComponent
 * @public
 * @example
 app.camera.fog.enable = true;
 app.camera.fog.color = '#cccccc';
 app.camera.fog.density = 0.01;
 */
class CameraFogComponent extends BaseComponent {



	/**

	 * 相机雾效组件,用于管理相机的雾效。

	 */

	constructor() {
		super();



		this[__.private] = {};

		let _private = this[__.private];



		_private.needsRefresh = false;



		_private.objectProxy = new ObjectProxy({

			data: {

				enable: false,

				type: FogType.Linear,

				near: 1,

				far: 1000,

				color: [1, 1, 1],

				density: 0.00025,

				sky: {

					enable: false,

					start: 0,

					height: 0.1

				}

			},

			onChange: function (ev) {
				_private.needsRefresh = true;
			}

		});



		// Refresh effect by current config

		this._refresh();



		// Show config always

		Object.defineProperty(this, 'customFormatters', {

			enumerable: false,

			configurable: false,

			get: function () {
				return ['object', { object: _private.objectProxy.dataProxy }];
			}

		});
	}



	// #region Private Functions



	_refresh() {
		let object = this.object;

		if (!object) {
			return;
		}



		let _private = this[__.private];



		if (!_private.needsRefresh) {
			return;
		}



		_private.needsRefresh = false;



		object.node.setFog(_private.objectProxy.data);
	}



	// #endregion



	// #region BaseComponent Overrides



	onAdd(object) {
		super.onAdd(object);



		// Refresh config before render if needed

		this.app.addBeforeRenderCallback(this._onBeforeRenderCallback = () => {
			this._refresh();
		});
	}



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



		_private.objectProxy.dispose();



		this.app.removeBeforeRenderCallback(this._onBeforeRenderCallback);



		super.onRemove();
	}



	// #endregion



	/**

	 是否开启雾效
	 * @type {boolean}
	 * @public
	 */

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



		return _private.objectProxy.dataProxy.enable;
	}

	set enable(value) {
		let _private = this[__.private];



		let config = _private.objectProxy.dataProxy;

		if (config.enable == value) {
			return;
		}



		config.enable = value;



		this._refresh();
	}



	/**

	 设置/获取雾的类型 支持指数雾(THING.FogType.Exp2)和线性雾(THING.FogType.Linear)
	 * @type {FogType}
	 * @public
	 */

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



		return _private.objectProxy.dataProxy.type;
	}

	set type(value) {
		let _private = this[__.private];



		let config = _private.objectProxy.dataProxy;

		if (config.type == value) {
			return;
		}



		config.type = value;



		this._refresh();
	}



	/**

	 指定雾效的起始位置(仅线性雾生效)
	 * @type {number}
	 * @public
	 */

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



		return _private.objectProxy.dataProxy.near;
	}

	set near(value) {
		let _private = this[__.private];



		let config = _private.objectProxy.dataProxy;

		if (config.near == value) {
			return;
		}



		config.near = value;



		this._refresh();
	}



	/**

	 获取/设置远裁剪面。
	 * @type {number}
	 * @public
	 */

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



		return _private.objectProxy.dataProxy.far;
	}

	set far(value) {
		let _private = this[__.private];



		let config = _private.objectProxy.dataProxy;

		if (config.far == value) {
			return;
		}



		config.far = value;



		this._refresh();
	}



	/**

	 雾的浓度(仅指数雾生效)
	 * @type {number}
	 * @public
	 */

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



		return _private.objectProxy.dataProxy.density;
	}

	set density(value) {
		let _private = this[__.private];



		let config = _private.objectProxy.dataProxy;

		if (config.density == value) {
			return;
		}



		config.density = value;



		this._refresh();
	}



	/**

	 雾的颜色
	 * @type {number|string|Array<string>}
	 * @public
	 */

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



		return _private.objectProxy.dataProxy.color;
	}

	set color(value) {
		if (!value) {
			return;
		}



		let _private = this[__.private];

		let config = _private.objectProxy.dataProxy;



		config.color = Utils.parseColor(value);



		this._refresh();
	}



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



		return _private.objectProxy.dataProxy.sky;
	}



	/**
	 
	 雾效配置
	 * @typedef {object} FogInfo
	 * @property {boolean} enable 是否开启
	 * @property {FogType} type 雾的类型
	 * @property {number} near 雾效起始位置(仅线性雾生效)
	 * @property {number} far 雾效结束位置(仅线性雾生效)
	 * @property {number} density 雾的强度(仅指数雾生效)
	 * @property {number|string|Array<string>} color 颜色
	 * @property {SkyFog} SkyFog 天空盒的雾效
	 * @public
	 */



	/**
	 
	 天空盒的雾效
	 * @typedef {object} SkyFog
	 * @property {boolean} enable 是否开启
	 * @property {number} start	开始位置
	 * @property {number} height 高度
	 * @public
	 */



	/**

	 雾效的配置
	 * @type {FogInfo}
	 * @public
	 */

	get config() {
		return this[__.private].objectProxy.dataProxy;
	}

	set config(value) {
		let _private = this[__.private];



		let to = _private.objectProxy.dataProxy;

		to.enable = Utils.parseValue(value['enable'], to.enable);

		to.type = Utils.parseValue(value['type'], to.type);

		to.color = Utils.parseColor(value['color'], to.color);

		to.density = Utils.parseValue(value['density'], to.density);

		to.near = Utils.parseValue(value['near'], to.near);

		to.far = Utils.parseValue(value['far'], to.far);

		Utils.mergeObject(to.sky, value.sky, true);
	}



}



export { CameraFogComponent }