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

/**
 * Water - 水体
 * 
 * 模拟水面效果,支持波浪、扰动、反射和流动等视觉效果。
 * 
 * @class Water
 * @memberof THING
 * @extends THING.BasePlanePoints
 * @public
 * 
 * @example
 * const water = new THING.Water({
 *   points: [[-10, 0, -10], [10, 0, -10], [10, 0, 10], [-10, 0, 10]],
 *   flowSpeed: [0.01, 0.01],
 *   flowWeight: 0.5,
 * });
 */
class Water extends BasePlanePoints {

	static defaultTagArray = ['Region'];

	/**
	 * 构造函数
	 * @param {object} param 初始参数。
	 * @param {number[][]} [param.points] 世界坐标系下(3D)区域外轮廓坐标
	 * @param {number[][][]} [param.holes] 世界坐标系下(3D)区域内空洞的坐标(支持多个空洞)
	 * @param {number[][]} [param.selfPoints] 自身坐标系下(3D)区域外轮廓坐标
	 * @param {number[][][]} [param.selfHoles] 自身坐标系下(3D)区域空洞坐标
	 * @param {number[][]} [param.selfPlanePoints] 自身平面坐标系下(2D)区域外轮廓坐标
	 * @param {number[][][]} [param.selfPlaneHoles] 自身平面坐标系下(2D)区域空洞坐标
	 * @param {number[]} [param.flowSpeed=[0,0]] 流速(数组,分别代表x,y方向的流速)
	 * @param {number} [param.flowWeight=0.5] 波浪强度
	 * @param {number} [param.reflectDistortion=2] 反射变形系数
	 * @param {number} [param.noiseTimeScale=1] 水流动态效果(噪声系数)
	 * @param {object} param.style 物体样式
	 * @constructor
	 * @public
	 */
	constructor(param = {}) {
		super(param);

		// Set default normal map
		let normalMap = this.app.global.cache.images['water_normal_image'];
		this.style.normalMap = normalMap;
	}

	// #region Overrides

	onSetupResource(param) {
		this._flowOffset = param['flowOffset'] || [0, 0];
		this._flowSpeed = param['flowSpeed'] || [0, 0];
		this._flowWeight = param['flowWeight'] || 0.5;
		this._reflectDistortion = param['reflectDistortion'] || 2;
		this._noiseTimeScale = param['noiseTimeScale'] || 1;
		this._radialFlow = param['radialFlow'] || false;

		super.onSetupResource(param);
	}

	onCreateBodyNode() {
		let water = Utils.createObject('Water', { app: this.app });
		return water;
	}

	onSetupBodyNode(node) {
		super.onSetupBodyNode(node);
		node.setFlowWeight(this._flowWeight);
		node.setReflectDistortion(this._reflectDistortion);
		node.setNoiseTimeScale(this._noiseTimeScale);
		node.setRadialFlow(this._radialFlow);
	}

	onRefreshAttributes() {
		let bodyNode = this.bodyNode;
		bodyNode.setFlowWeight(this._flowWeight);
		bodyNode.setReflectDistortion(this._reflectDistortion);
		bodyNode.setNoiseTimeScale(this._noiseTimeScale);
		bodyNode.setRadialFlow(this._radialFlow);
	}

	onUpdate(deltaTime) {
		if (this._flowSpeed[0] || this._flowSpeed[1]) {
			let factor = deltaTime;
			let flowOffset = this._flowOffset;
			let flowSpeed = this._flowSpeed;
			let offset = [flowSpeed[0] * factor, flowSpeed[1] * factor];
			flowOffset[0] += offset[0];
			flowOffset[1] += offset[1];

			this.bodyNode.setFlowOffset(flowOffset);
		}

		this.bodyNode.update(deltaTime);
	}

	onCreate(options) {
		super.onCreate(options);

		this.onAddTickableObject();
	}

	// #endregion

	destroy() {
		if (this.app.objectManager.isKeepAliveObject(this)) {
			return false;
		}

		this.onRemoveTickableObject();

		return super.destroy();
	}

	onExportExternalData() {
		let external = Object.assign({}, super.onExportExternalData());
		Utils.setAttributeIfExist(external, 'flowSpeed', this);
		Utils.setAttributeIfExist(external, 'flowWeight', this);
		Utils.setAttributeIfExist(external, 'noiseTimeScale', this);
		Utils.setAttributeIfExist(external, 'radialFlow', this);
		return external;
	}

	// #region Accessor

	/**
	 * 获取/设置流速 数组分别代表x和y方向流速
	 * @type {Array<number>}
	 * @public
	 */
	get flowSpeed() {
		return this._flowSpeed;
	}
	set flowSpeed(value) {
		this._flowSpeed = value.concat();
	}

	/**
	 * 获取/设置 波浪强度
	 * @type {number}
	 * @public
	 */
	get flowWeight() {
		return this._flowWeight;
	}
	set flowWeight(value) {
		this._flowWeight = value;

		this.bodyNode.setFlowWeight(value);
	}

	/**
	 * 获取/设置水面反射物体的变形系数(扰动)
	 * @type {number}
	 * @public
	 */
	get reflectDistortion() {
		return this._reflectDistortion;
	}
	set reflectDistortion(value) {
		this._reflectDistortion = value;

		this.bodyNode.setReflectDistortion(value);
	}

	/**
	 * 获取/设置 水流动态效果(噪声系数,暂时还没看到效果是什么)
	 * @type {number}
	 * @public
	 */
	get noiseTimeScale() {
		return this._noiseTimeScale;
	}
	set noiseTimeScale(value) {
		this._noiseTimeScale = value;

		this.bodyNode.setNoiseTimeScale(value);
	}

	/**
	 * 获取/设置 是否开启径向流动
	 * @type {boolean}
	 * @public
	 */
	get radialFlow() {
		return this.bodyNode.getRadialFlow();
	}

	set radialFlow(value) {
		this.bodyNode.setRadialFlow(value);
	}

	// #endregion

	get isWater() {
		return true;
	}

}

export { Water }