import { Object3D, Style } from '@uino/thing';
import { Utils } from '../../common/Utils.js';
/**
 * @class Boundary
 * @summary 围栏类,用于在三维场景中创建多边形围栏/边界墙,支持自定义高度和纹理贴图。
 * 通过指定世界坐标点集或局部坐标点集定义围栏路径,配合高度参数生成三维墙体。
 * 高度支持数组形式为不同顶点分别指定高度,样式支持纹理贴图,
 * 适用于场地围栏、安全区域边界、道路护栏等可视化场景。
 * @memberof THING
 * @public
 * @example
 * // 创建一个半透明纹理围栏
 * const fence = new THING.EXTEND.Boundary({
 *   points: [
 *     [-10, 0, -10],
 *     [-10, 0, 10],
 *     [10, 0, 10],
 *     [10, 0, -10]
 *   ],
 *   height: 3,
 *   style: {
 *     color: [0, 0.6, 1, 0.5],
 *     map: new THING.ImageTexture('./images/fence.png')
 *   }
 * });
 * fence.isAcceptLight = false;
 */
class Boundary extends Object3D {

	/**
	 * 构造函数
	 * @param {object} param 参数对象
	 * @param {Number|Number[]} param.height 围栏高度 支持数组 长度需要和points或者selfPoints一致
	 * @param {Boolean} param.isAcceptLight 是否接受光照
	 * @param {Array<number>} param.points 点集合
	 * @param {Array<number>} param.selfPoints 自身坐标系下的点集合
	 * @param {Style} param.style 围栏样式
	 * @example
	 * // 创建一个围栏
		const boundary = new THING.EXTEND.Boundary({       
			points: [
				[1,0,-1],
				[1,0,1],
				[1,0,2],
			],
			height: 5,
			style: {
				map: new THING.ImageTexture('./images/signboard-top/image1.png'),
			}
	 	});
	 */
	constructor(param = {}) {
		super(param);

		this._syncOptions(param);

		if (this._points) {
			this._convertPointsAndSelfPoints('points');
		}

		if (this._selfPoints) {
			this._convertPointsAndSelfPoints('selfPoints');
		}

		this._updateRenderNode();
	}

	_syncOptions(param) {
		Utils.syncOptions(this, [
			'height',
			'points',
			'selfPoints',
			'isAcceptLight',
		], param, param['extras'] || param['external']);
	}

	/**
	 * 更新渲染节点
	 * @private
	 * @ignore
	 */
	_updateRenderNode() {
		// create render node
		if (this._selfPoints) {
			const geometryResource = Utils._createBoundaryGeometryResource({
				data: this._selfPoints,
				extrudeHeight: this._height //支持数组 长度需要和points一致
			});
			const node = Utils.createObject('BoundaryNode', { uScene: this.node._uScene, geometryResource: geometryResource });
			this.body.setNode(node);
		}
	}

	/**
	 * 在点和自身点之间进行转换
	 * @private
	 * @ignore
	 */
	_convertPointsAndSelfPoints(flag) {
		// convert points to selfPoints
		if (this._points && flag === 'points') {
			let localPoints = [];
			for (let i = 0; i < this._points.length; i++) {
				localPoints[i] = this.worldToSelf(this._points[i]);
			}
			this._selfPoints = localPoints;
		}

		// convert selfPoints to points
		if (this._selfPoints && flag === 'selfPoints') {
			let worldPoints = [];
			for (let i = 0; i < this._selfPoints.length; i++) {
				worldPoints[i] = this.selfToWorld(this._selfPoints[i]);
			}
			this._points = worldPoints;
		}
	}

	onExportExternalData() {
		let external = Object.assign({}, super.onExportExternalData());
		Utils.setAttributeIfExist(external, 'selfPoints', this);
		Utils.setAttributeIfExist(external, 'height', this);
		Utils.setAttributeIfExist(external, 'isAcceptLight', this);
		return external;
	}

	/**
	 * 获取/设置点集合
	 * @type {Number[]}
	 * @public
	 */
	get points() {
		return this._points;
	}
	set points(value) {
		this._points = value;
		this._convertPointsAndSelfPoints('points');
		this._updateRenderNode();
	}

	/**
	 * 获取/设置自身坐标系下的点集合
	 * @type {Number[]}
	 * @public
	 */
	get selfPoints() {
		return this._selfPoints;
	}
	set selfPoints(value) {
		this._selfPoints = value;
		this._convertPointsAndSelfPoints('selfPoints');
		this._updateRenderNode();
	}

	/** 
	 * 获取/设置高度 支持数组
	 * @type {Number|Number[]}
	 * @public
	 */
	get height() {
		return this._height;
	}
	set height(value) {
		this._height = value;
		this._updateRenderNode();
	}

	/**
	 * 获取/设置是否接受光照
	 * @type {Boolean}
	 * @public
	 */
	set isAcceptLight(value) {
		this._isAcceptLight = value
		this.style.setAttribute('Lights', value)
	}
	get isAcceptLight() {
		return this._isAcceptLight
	}

	onDestroy() {
		this._selfPoints = null;
		this._points = null;
		this._height = null;

		super.onDestroy()
	}

	copy(source) {
		super.copy(source);
		this._points = source._points;
		this._selfPoints = source._selfPoints;
		this._height = source._height;
		if (this._points) {
			this._convertPointsAndSelfPoints('points');
		}
		if (this._selfPoints) {
			this._convertPointsAndSelfPoints('selfPoints');
		}
		this._updateRenderNode();
		return this;
	}

	clone() {
		return new this.constructor().copy(this);
	}

}

export { Boundary }