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

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

import { MathUtils } from '../math/MathUtils';

import { BaseTickableObject3D } from './BaseTickableObject3D';



const GROUND_FLOW_TYPE = {

	"Center": 0,

	"Linear": 1

}



const GROUND_FLOW_TYPE_REVERSE = {};

for (let key in GROUND_FLOW_TYPE) {

	GROUND_FLOW_TYPE_REVERSE[GROUND_FLOW_TYPE[key]] = key;

}

/**
 * EffectGroundObject - 特效地面对象
 * 
 * 用于创建带有特效效果的地面对象,支持自定义颜色和流动颜色。
 * 
 * @class EffectGroundObject
 * @memberof THING
 * @extends THING.BaseTickableObject3D
 * @public
 */
class EffectGroundObject extends BaseTickableObject3D {



	/**

	 * 特效地面对象的构造函数。

	 * @param {object} param 初始化参数

	 * @param {string} param.url 地面图片的URL

	 * @param {string} param.maskUrl 遮罩图片的URL

	 * @param {string} param.color 地面颜色

	 * @param {string} param.flowColor 流动颜色

	 */

	constructor(param = {}) {

		super(param);



		this._initParam(param);

	}



	/**

	 * Get type.

	 * @returns {string} 类型。

	 */

	getType() {

		return 'EffectGroundObject';

	}



	_initParam(param) {

		param.url = param.url && Utils.resolveURL(param.url);

		param.maskUrl = param.maskUrl && Utils.resolveURL(param.maskUrl);

		param.alphaMap = param.alphaMap && Utils.resolveURL(param.alphaMap);

		param.color = param.color && Utils.parseColor(param.color);

		param.groundFlowType = param['groundFlowType'] === undefined ? 0 : GROUND_FLOW_TYPE[param['groundFlowType']];

		if (param.flowColor) {

			param.flowColor = Utils.parseColor(param.flowColor);

			param.flowColor.length = 3;

		}

	}



	hasResource() {

		return true;

	}



	/**

	 * When load reosurce.

	 * @param {object} options The options to load.

	 * @param {Function} resolve The promise resolve callback function.

	 * @param {Function} reject The promise reject callback function.

	 * @private

	 */

	onLoadRenderableResource(options, resolve, reject) {

		const node = Utils.createObject('EffectGroundObjectNode', { external: { uScene: this.node._uScene, param: options }});

		this.level.config.ignoreStyle = true;			// skip level outline

		this._node = node;

		this.body.setNode(node);

		this.bounding.inheritType = InheritType.Jump;

		this.updateGround(this.parent);

		this.pickable = false;

		resolve();

	}



	onUpdate(deltaTime) {

		if (this._node && !this._node.groundReflect) {

			this._node.update(deltaTime);

		}

	}



	/**

	 * 更新地面父对象并计算位置。

	 * @param {THING.Object3D} target 根据目标的边界框计算和更新特效地面的位置和缩放。

	 * @public

	 * @example

	 * 	const building = app.query('.Building')[0];

	 * 	effectGround.updateGround(building);

	 */

	updateGround(target) {

		if (!this._node) { return; }



		if (target) {

			this.parent = target;

			const bbx = target.getOBB(true, false);

			const radius = bbx.halfSize[1] + 0.2 - this._node.groundClearance;

			const rDis = MathUtils.scaleVector(target.up, radius);

			let pos = MathUtils.subVector(bbx.center, rDis);

			pos[0] += this._node.groundOffsetX;

			pos[2] += this._node.groundOffsetY;

			this.position = [pos[0], pos[1], pos[2]];

			let scaleFactor = MathUtils.scaleVector([bbx.radius * 2, 1, bbx.radius * 2], this._node.sizeFactor);		// use box's diameter

			this.scale = [scaleFactor[0], scaleFactor[1], scaleFactor[2]];

			this.angles = target.angles;

		}

		else if (!target) {

			this.position = [this._node.groundOffsetX, this._node.groundClearance, this._node.groundOffsetY];

			this.scale = [this._node.sizeFactor, 1, this._node.sizeFactor];

		}

	}



	/**

	 * 设置特效地面是否具有反射效果。

	 * @param {boolean} value 是否具有反射效果。

	 * @public

	 */

	set groundReflect(value) {

		this._node.groundReflect = value;

		if (this.groundReflect) {

			this.updateGround(this.parent);

		}

	}



	/**

	 * 获取特效地面是否具有反射效果。

	 * @type {boolean}

	 * @public

	 */

	get groundReflect() {

		return this._node.groundReflect;

	}



	/**

	 * 设置尺寸因子。

	 * @param {number} value 尺寸因子。

	 * @public

	 */

	set sizeFactor(value) {

		this._node.sizeFactor = value;

		this.updateGround(this.parent);

	}



	/**

	 * 获取尺寸因子。

	 * @type {number}

	 * @public

	 */

	get sizeFactor() {

		return this._node.sizeFactor;

	}



	/**

	 * 设置地面图片的URL。

	 * @param {string} value 地面图片的URL。

	 * @public

	 */

	set imageUrl(value) {

		value = Utils.resolveURL(value);

		this._url = this._node.imageUrl = value;

	}



	/**

	 * 获取地面图片的URL。

	 * @type {string}

	 * @public

	 */

	get imageUrl() {

		return this._node.imageUrl;

	}



	/**

	 * 设置遮罩图片的URL。

	 * @param {string} value 遮罩图片的URL。

	 * @public

	 */

	set maskUrl(value) {

		value = Utils.resolveURL(value);

		this._node.maskUrl = value;

	}



	/**

	 * 获取遮罩图片的URL。

	 * @type {string}

	 * @public

	 */

	get maskUrl() {

		return this._node.maskUrl;

	}



	/**

	 * 设置不透明度。

	 * @param {number} value 不透明度。

	 * @public

	 */

	set opacityValue(value) {

		this._node.opacityValue = value;

	}



	/**

	 * 获取不透明度。

	 * @type {number}

	 * @public

	 */

	get opacityValue() {

		return this._node.opacityValue;

	}



	/**

	 * 设置发光强度因子。

	 * @param {number} value 发光强度因子。

	 * @public

	 */

	set glowFactorValue(value) {

		this._node.glowFactorValue = value;

	}



	/**

	 * 获取发光强度因子。

	 * @type {number}

	 * @public

	 */

	get glowFactorValue() {

		return this._node.glowFactorValue;

	}



	/**

	 * 设置纹理UV重复因子。

	 * @param {number} value 纹理UV重复因子。

	 * @public

	 */

	set repeatFactorValue(value) {

		this._node.repeatFactorValue = value;

	}



	/**

	 * 获取纹理UV重复因子。

	 * @type {number}

	 * @public

	 */

	get repeatFactorValue() {

		return this._node.repeatFactorValue;

	}



	/**

	 * 设置纹理在U轴上的重复因子。

	 * @param {number} value 纹理在U轴上的重复因子。

	 * @public

	 */

	set repeatFactorValueX(value) {

		this._node.repeatFactorValueX = value;

	}



	/**

	 * 获取纹理在U轴上的重复因子。

	 * @type {number}

	 * @public

	 */

	get repeatFactorValueX() {

		return this._node.repeatFactorValueX;

	}



	/**

	 * 设置纹理在V轴上的重复因子。

	 * @param {number} value 纹理在V轴上的重复因子。

	 * @public

	 */

	set repeatFactorValueY(value) {

		this._node.repeatFactorValueY = value;

	}



	/**

	 * 获取纹理在V轴上的重复因子。

	 * @type {number}

	 * @public

	 */

	get repeatFactorValueY() {

		return this._node.repeatFactorValueY;

	}



	/**

	 * 设置地面颜色。

	 * @param {string} value 地面颜色。

	 * @public

	 */

	set groundColorValue(value) {

		const colorArray = Utils.parseColor(value);

		this._node.groundColorValue = colorArray;

	}



	/**

	 * 获取地面颜色。

	 * @type {string}

	 * @public

	 */

	get groundColorValue() {

		const value = Utils.toColorHexString(this._node.groundColorValue);

		return value;

	}



	/**

	 * 设置流动颜色。

	 * @param {string} value 流动颜色。

	 * @public

	 */

	set flowColorValue(value) {

		const colorArray = Utils.parseColor(value);

		colorArray.length = 3;

		this._node.flowColorValue = colorArray;

	}



	/**

	 * 获取流动颜色。

	 * @type {string}

	 * @public

	 */

	get flowColorValue() {

		const value = Utils.toColorHexString(this._node.flowColorValue);

		return value;

	}



	/**

	 * 设置流动动画速度。

	 * @param {number} value 流动动画速度。

	 * @public

	 */

	set animationSpeed(value) {

		this._node.animationSpeed = value;

	}



	/**

	 * 获取流动动画速度。

	 * @type {number}

	 * @public

	 */

	get animationSpeed() {

		return this._node.animationSpeed;

	}



	/**

	 * 设置地面高度。

	 * @param {number} value 地面高度。

	 * @public

	 */

	set groundClearance(value) {

		this._node.groundClearance = value;

		this.updateGround(this.parent);

	}



	/**

	 * 获取地面高度。

	 * @type {number}

	 * @public

	 */

	get groundClearance() {

		return this._node.groundClearance;

	}



	set groundOffsetX(value) {

		this._node.groundOffsetX = value;

		this.updateGround(this.parent);

	}



	get groundOffsetX() {

		return this._node.groundOffsetX;

	}



	set groundOffsetY(value) {

		this._node.groundOffsetY = value;

		this.updateGround(this.parent);

	}



	get groundOffsetY() {

		return this._node.groundOffsetY;

	}





	/**

	 * 获取地面类型。

	 * @type {string}

	 * @public

	 */

	get groundType() {

		return this._node.groundType;

	}



	/**

	 * 设置透明贴图。

	 * @type {string}

	 * @public

	 */

	set alphaMap(value) {

		value = Utils.resolveURL(value);

		this._node.alphaMapUrl = value;

	}



	/**

	 * 获取透明贴图路径。

	 * @type {string}

	 * @public

	 */

	get alphaMap() {

		return this._node.alphaMapUrl;

	}



	set groundFlowType(value) {

		const flowType = GROUND_FLOW_TYPE[value];

		if (Utils.isValid(flowType)) {

			this._node.groundFlowType = flowType;

		}

	}



	get groundFlowType() {

		return GROUND_FLOW_TYPE_REVERSE[this._node.groundFlowType];

	}



	set groundFlowAngle(value) {

		this._node.groundFlowAngle = value;

	}



	get groundFlowAngle() {

		return this._node.groundFlowAngle;

	}



	set receiveShadow(value) {

		this._node.receiveShadow = value;

	}



	get receiveShadow() {

		return this._node.receiveShadow;

	}



	set unlitSSR(value) {

		this._node.unlitSSR = value;

	}



	get unlitSSR() {

		return this._node.unlitSSR;

	}



	dispose() {

		this._node.dispose();

	}



	copy(source) {

		this._node.copy(source);

	}



}

export { EffectGroundObject }