import { Object3D } from "./Object3D";
import { Utils } from "../common/Utils"

const __ = {
	private: Symbol('private'),
}

const _defaultSize = {
	length: 60,
	width: 60,
	density: 1
};

/**
 * Grid - 网格对象
 *
 * 用于创建场景中的辅助网格,支持自定义平面、长度、宽度和密度。
 * @class Grid
 * @memberof THING
 * @extends THING.Object3D
 * @public
 * @example
 * const grid = new THING.Grid({
 *   workPlane: 'XZ',
 *   size: { length: 60, width: 60, density: 1 },
 * });
 */
class Grid extends Object3D {

	/**
	 * @typedef {object} GridWorkPlane 网格的平面参数
	 * @property {Array.<number>} position - 网格的位置,默认[0, 0, 0]
	 * @property {Array.<number>} quaternion - 网格的四元数,默认[0, 0, 0, 1]
	 * @property {number} precision - 网格的缩放值,默认0
	 */

	/**
	 * @typedef {object} GridSize 网格的大小参数
	 * @property {number} length - 网格的长度,默认60
	 * @property {number} width - 网格的宽度,默认60
	 * @property {number} density - 网格的密度,默认1
	 */

	/**
	 * @public
	 * 网格对象构造函数
	 * @param {object} param 参数
	 * @param {GridWorkPlane} param.workPlane - 网格的平面
	 * @param {GridSize} param.size - 网格的大小
	 */
	constructor(param) {
		super(param);

		this[__.private] = {};
		let _private = this[__.private];

		param = param || {};
		_private.gridData = param.workPlane || { position: [0, 0, 0], quaternion: [0, 0, 0, 1], precision: 0 };
		_private.size = param.size || _defaultSize;

		let lines = Utils.createObject('LineSegments', { app: this.app });
		lines.setAttribute('Pickable', false);
		lines.getUserData()['isDebugNode'] = true;

		_private.lines = lines;

		this.node.add(lines);

		_private.points = [];
		_private.colors = [];

		const compatibleRender = this.app.view._compatibleRender;
		const centerColor = compatibleRender ? 73 / 255 : 73 / 255 / 1.5;
		const outColor = compatibleRender ? 60 / 255 : 60 / 255 / 1.5;

		_private.centerColor = [centerColor, centerColor, centerColor];
		_private.outColor = [outColor, outColor, outColor];

		_private.length = _private.size.length || _defaultSize.length;
		_private.width = _private.size.width || _defaultSize.width;
		_private.density = _private.size.density || _defaultSize.density;

		_private.position = _private.gridData.position;
		_private.quaternion = _private.gridData.quaternion;

		this._updateLine();
	}

	onRemove() {
		let _private = this[__.private];
		_private.line.destroy();
		_private.line = null;

		super.onRemove();
	}

	_insertLine(p0, p1, c) {
		let _private = this[__.private];

		_private.points.push(p0);
		_private.colors.push(c);

		_private.points.push(p1);
		_private.colors.push(c);
	}

	_updateLine() {
		let _private = this[__.private];
		_private.points = [];
		_private.colors = [];

		let _lengthValue = _private.length / 2;
		let _widthValue = _private.width / 2;

		this._insertLine([_lengthValue, 0, 0], [-_lengthValue, 0, 0], _private.centerColor);
		for (let i = _private.density; i <= _private.width / 2; i += _private.density) {
			this._insertLine([_lengthValue, 0, i], [-_lengthValue, 0, i], _private.outColor); // z+
			this._insertLine([_lengthValue, 0, -i], [-_lengthValue, 0, -i], _private.outColor); // z-
		}

		this._insertLine([0, 0, _widthValue], [0, 0, -_widthValue], _private.centerColor);
		for (let i = _private.density; i <= _private.length / 2; i += _private.density) {
			this._insertLine([i, 0, _widthValue], [i, 0, -_widthValue], _private.outColor); // x+
			this._insertLine([-i, 0, _widthValue], [-i, 0, -_widthValue], _private.outColor); // x-
		}

		_private.lines.setSize(_private.points.length);
		_private.lines.setPoints(_private.points);
		_private.lines.setColors(_private.colors);
	}

	/**
	 * 网格的长度
	 * @type {number}
	 * @public
	 */
	set length(number) {
		let _private = this[__.private];

		if (_private.length !== number) {
			_private.length = number;
			this._updateLine();
		}
	}
	get length() {
		let _private = this[__.private];

		return _private.length;
	}

	/**
	 * 网格的宽度
	 * @type {number}
	 * @public
	 */
	set width(number) {
		let _private = this[__.private];

		if (_private.width !== number) {
			_private.width = number;
			this._updateLine();
		}
	}
	get width() {
		let _private = this[__.private];

		return _private.width;
	}

	/**
	 * 网格的密度,每个网格的长度(数字必须大于0)
	 * @type {number}
	 * @public
	 */
	set density(number) {
		let _private = this[__.private];

		if (_private.density !== number) {
			_private.density = number;
			this._updateLine();
		}
	}
	get density() {
		let _private = this[__.private];

		return _private.density;
	}

}

export { Grid }