import { Object3D, MathUtils } from '@uino/thing';
import { Utils } from '../common/Utils';
import { SpaceComponent } from '../components/SpaceComponent';

/**
 * @class Room
 * 房间类。
 * @extends THING.Object3D
 * @public
 */
class Room extends Object3D {

	static defaultTagArray = ['Room'];

	constructor(param = {}) {
		super(param);

		if (param['points']) {
			this._selfPoints = param['points']
		}

		if (param['holes']) {
			this._selfHoles = param['holes']
		}
	}

	/**
	 * Show/hide roof
	 * @param {Boolean} visible true show (default) / false hide
	 */
	showRoof(visible = true) {
		const roof = this.roof;
		if (roof) {
			roof.visible = visible;
		}
	}

	/**
	 * Show/hide ceiling
	 * @param {Boolean} visible true show (default) / false hide
	 */
	showCeiling(visible = true) {
		const ceiling = this.ceiling;
		if (ceiling) {
			ceiling.visible = visible;
		}
	}

	/**
	 * 获取房间点的世界坐标
	 * @type {Array<Number>}
	 * @public
	 */
	get points() {
		if (!this._selfPoints) {
			return []
		}
		const points = this._selfPoints.map((point) => {
			const worldPoint = this.selfToWorld([point[0], 0, point[1]]);
			return worldPoint;
		});

		return points;
	}

	/**
	 * 获取房间点的相对坐标
	 * @type {Array<Number>}
	 * @public
	 */
	get selfPoints() {
		if (!this._selfPoints) {
			return []
		}
		const points = this._selfPoints.map((point) => {
			return [point[0], 0, point[1]];
		});

		return points;
	}

	/**
	 * 获取房间洞的世界坐标
	 * @type {Array<Number>}
	 * @public
	 */
	get holes() {
		if (!this._selfHoles) {
			return []
		}
		const holes = this._selfHoles?.map(holeArr => {
			const hole = holeArr.map((point) => {
				return this.selfToWorld([point[0], 0, point[1]]);
			});
			return hole;
		});
		return holes;
	}

	/**
	 * 获取房间洞的相对坐标
	 * @type {Array<Number>}
	 * @public
	 */
	get selfHoles() {
		if (!this._selfHoles) {
			return []
		}
		const holes = this._selfHoles?.map(holeArr => {
			const hole = holeArr.map((point) => {
				return [point[0], 0, point[1]];
			});
			return hole;
		});
		return holes;
	}



	/**
	 * 获取房间的地板
	 * @type {THING.Object3D}
	 * @example
	 * let slab = room.slab;
	 * console.log(slab);
	 * @public
	 */
	get slab() {
		return this.children.find('tags:or(RoomFloor)');
	}

	/**
	 * 获取房间的天花板
	 * @type {THING.Object3D}
	 * @example
	 * let ceiling = room.ceiling;
	 * console.log(ceiling);
	 * @public
	 */
	get ceiling() {
		return this.children.find('tags:or(RoomCeiling)');
	}

	/**
	 * 获取房间的屋顶
	 * @type {THING.Object3D}
	 * @example
	 * let roof = room.roof;
	 * console.log(roof);
	 * @public
	 */
	get roof() {
		return this.children.find('tags:or(RoomRoof)');
	}

	/**
	 * 获取房间的其他物体
	 * @type {THING.Object3D}
	 * @example
	 * let misc = room.misc;
	 * console.log(misc);
	 * @public
	 */
	get misc() {
		return this.children.find('tags:or(Misc)');
	}

	/**
	 * 获取房间的面积
	 * @type {Number}
	 * @example
	 * let area = room.area;
	 * console.log(area);
	 * @public
	 */
	get area() {
		if (Utils.isNull(this._area)) {
			this._area = Math.abs(MathUtils.getArea(this._selfPoints));
		}
		return this._area;
	}

	/**
	 * 获取房间的周长
	 * @type {Number}
	 * @example
	 * let perimeter = room.perimeter;
	 * console.log(perimeter);
	 * @public
	 */
	get perimeter() {
		const points = this.points;
		let perimeter = 0;
		for (let i = 0; i < points.length; i++) {
			const point = points[i];
			const nextPoint = points[i < points.length - 1 ? i + 1 : 0];
			perimeter += MathUtils.getDistance(point, nextPoint);
		}
		return perimeter;
	}

	/**
	 * 获取房间中的门对象集合
	 * @type {THING.Selector<THING.Door>}
	 * @example
	 * let doors = room.doors;
	 * console.log(doors);
	 * @public
	 */
	get doors() {
		if (!this._internalSpace) {
			this._internalSpace = new SpaceComponent();
			this.addComponent(this._internalSpace, '_internalSpace');
		}

		const points = this.points;
		const doors = this.parent.doors;

		return this._internalSpace.filterObjectsInLineSegments(points, doors);
	}

	onExportExternalData() {
		const result = {
			points: this._selfPoints,
			holes: this._selfHoles
		}
		return result;
	}

}

export { Room };