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

let _scale = MathUtils.createVec3();

/**
 * @class CSS3DNode
 * CSS 3D 渲染节点,处理 DOM 元素在 3D 空间中的变换。
 * @memberof THING
 * @public
 */
class CSS3DNode {

	/**
	 * constructor.
	 * Initializes the CSS3DNode with the specified render type.
	 * @param {string} renderType - The type of rendering to be applied.
	 * @example
	 * const node = new CSS3DNode('css3d');
	 */
	constructor(renderType) {
		/**
		 * The DOM element to be rendered.
		 * @type {HTMLElement}
		 * @private
		 */
		this._domElement = null;

		/**
		 * The position vector of the node.
		 * @type {Array<number>}
		 * @private
		 */
		this._position = MathUtils.createVec3();

		/**
		 * The quaternion representing rotation.
		 * @type {Array<number>}
		 * @private
		 */
		this._quaternion = MathUtils.createQuat();

		/**
		 * The scale vector of the node.
		 * @type {Array<number>}
		 * @private
		 */
		this._scale = MathUtils.createVec3();
		MathUtils.vec3.set(this._scale, 1, 1, 1);

		/**
		 * The parent transformation matrix.
		 * @type {Array<number>}
		 * @private
		 */
		this._parentMatrix = MathUtils.createMat4();

		/**
		 * The world transformation matrix.
		 * @type {Array<number>}
		 * @private
		 */
		this._matrixWorld = MathUtils.createMat4();

		/**
		 * The visibility state of the node.
		 * @type {boolean}
		 * @private
		 */
		this._visible = true;

		/**
		 * The loading state of the node.
		 * @type {boolean}
		 * @private
		 */
		this._loading = false;

		/**
		 * The type of rendering to be applied.
		 * @type {string}
		 * @private
		 */
		this._renderType = renderType;

		this._anchorMatrix = MathUtils.createMat4();
	}

	/**
	 * Removes the DOM element from its parent.
	 * @private
	 * @example
	 * // Example usage of _removeElement method
	 * const node = new CSS3DNode();
	 * node._domElement = document.createElement('div');
	 * document.body.appendChild(node._domElement);
	 * node._removeElement(); // This will remove the DOM element from the document body.
	 */
	_removeElement() {
		if (this._domElement && this._domElement.parentNode !== null) {
			this._domElement.parentNode.removeChild(this._domElement);
		}
	}

	/**
	 * Disposes the node and removes its DOM element.
	 * @private
	 * @example
	 * // Example usage of dispose method
	 * const node = new CSS3DNode();
	 * node.dispose(); // This will remove the DOM element if it exists.
	 */
	dispose() {
		this._removeElement();
	}

	/**
	 * Updates the world transformation matrix.
	 * @returns {Array<number>} The updated world matrix.
	 * @private
	 * @example
	 * // Example usage of updateMatrixWorld method
	 * const node = new CSS3DNode();
	 * node.updateMatrixWorld(); // This will update the node's world transformation matrix.
	 */
	updateMatrixWorld() {
		MathUtils.mat4.fromRotationTranslationScale(this._matrixWorld, this._quaternion, this._position, this._scale);
		MathUtils.mat4.multiply(this._matrixWorld, this._parentMatrix, this._matrixWorld);

		return this._matrixWorld;
	}

	/**
	 * 获取/设置位置向量。
	 * @type {Array<number>}
	 * @public
	 */
	get position() {
		return this._position;
	}
	set position(value) {
		MathUtils.vec3.copy(this._position, value);
	}

	/**
	 * 获取/设置旋转四元数。
	 * @type {Array<number>}
	 * @public
	 */
	get quaternion() {
		return this._quaternion;
	}
	set quaternion(value) {
		MathUtils.quat.copy(this._quaternion, value);
	}

	/**
	 * 获取/设置缩放向量。
	 * @type {Array<number>}
	 * @public
	 */
	get scale() {
		return this._scale;
	}
	set scale(value) {
		MathUtils.vec3.copy(this._scale, value);
	}

	/**
	 * 获取世界缩放向量。
	 * @type {Array<number>}
	 * @public
	 */
	get worldScale() {
		return MathUtils.mat4.getScaling(_scale, this._matrixWorld);
	}

	/**
	 * 获取/设置父变换矩阵。
	 * @type {Array<number>}
	 * @public
	 */
	get parentMatrix() {
		return this._parentMatrix;
	}
	set parentMatrix(value) {
		MathUtils.mat4.copy(this._parentMatrix, value);
	}

	/**
	 * 获取世界变换矩阵。
	 * @type {Array<number>}
	 * @public
	 */
	get matrixWorld() {
		return this._matrixWorld;
	}

	/**
	 * 获取/设置要渲染的DOM元素。
	 * @type {HTMLElement}
	 * @public
	 */
	get domElement() {
		return this._domElement;
	}
	set domElement(value) {
		this._removeElement();

		this._domElement = value;
		this._domElement.style.position = 'absolute';
	}

	/**
	 * 获取/设置可见性状态。
	 * @type {boolean}
	 * @public
	 */
	get visible() {
		return this._visible;
	}
	set visible(value) {
		this._visible = value;
	}

	/**
	 * 获取/设置加载状态。
	 * @type {boolean}
	 * @public
	 */
	get loading() {
		return this._loading;
	}
	set loading(value) {
		this._loading = value;
	}

	/**
	 * 获取/设置渲染类型。
	 * @type {string}
	 * @public
	 */
	get renderType() {
		return this._renderType;
	}
	set renderType(value) {
		this._renderType = value;
	}

	/**
	 * 检查节点是否作为精灵渲染。
	 * @type {boolean}
	 * @public
	 */
	get isSprite() {
		return this.renderType == 'Sprite';
	}

	setAnchorMatrix(x, y) {
		this._anchorMatrix[12] = x;
		this._anchorMatrix[13] = y;
	}

}

export { CSS3DNode };