import { Box3 } from '@uino/base-thing';
import { Utils } from '../common/Utils';
import { ObjectExpression } from '../common/ObjectExpression';
import { AsyncSelector } from './AsyncSelector';
import { StyleSelector } from './StyleSelector';
import { InheritSelector } from './InheritSelector';

const _styleSelector = new StyleSelector();
const _inheritSelector = new InheritSelector();

// #region ObjectExpression-Cache

let _expressions = new Map();

function _getExpression(condition, mode) {
	let key = mode ? mode + ':' + condition : condition;

	let expression = _expressions.get(key);
	if (!expression) {
		expression = new ObjectExpression(condition, mode);

		_expressions.set(key, expression);
	}

	return expression;
}

// #endregion

// #region Private

function _selectObjectsByExpression(expression, objects, result) {
	objects.forEach(object => {
		if (expression.evaluate(object)) {
			result.push(object);
		}
	});
}

function _selectObjectsByRegExpName(condition, objects, result) {
	objects.forEach(object => {
		if (!condition.test(object.name)) {
			return;
		}

		result.push(object);
	});
}

function _selectObjectsByFunction(condition, objects, result) {
	objects.forEach(object => {
		if (!condition(object)) {
			return;
		}

		result.push(object);
	});
}

function _findObjectsByExpression(expression, objects) {
	for (let i = 0, l = objects.length; i < l; i++) {
		let object = objects[i];

		if (expression.evaluate(object)) {
			return object;
		}
	}

	return null;
}

function _findObjectsByRegExpName(condition, objects) {
	for (let i = 0, l = objects.length; i < l; i++) {
		let object = objects[i];

		if (condition.test(object.name)) {
			return object;
		}
	}

	return null;
}

function _findObjectsByFunction(condition, objects) {
	for (let i = 0, l = objects.length; i < l; i++) {
		let object = objects[i];

		if (condition(object)) {
			return object;
		}
	}

	return null;
}

// Get objects by condition.
function _getObjectsByCondition(condition, objects) {
	if (condition) {
		if (Utils.isString(condition)) {
			return Selector.select(condition, objects);
		}
		else if (Utils.isArray(condition)) {
			return condition;
		}
		else if (condition.isSelector) {
			return condition.objects;
		}
		else {
			return [condition];
		}
	}

	return null;
}

function _parseObjects(param) {
	if (Utils.isArray(param)) {
		return param;
	}

	if (Utils.isObject(param)) {
		return Utils.parseValue(param['objects'], []);
	}

	return [];
}

function _pushArray(array, arrayLength, target) {
	for (let i = 0; i < target.length; i++) {
		array[arrayLength] = target[i];
		++arrayLength;
	}
	return arrayLength;
}

// #endregion

/**
 * @class Selector
 * 用于根据条件查找对象的选择器。
 * @memberof THING
 * @public
 */
class Selector {

	static asyncSelector = null;


	constructor(param = {}) {
		this._app = param['app'] || Utils.getCurrentApp();
		this._objects = _parseObjects(param);

		// Hook [index] to implement accessor by index
		let handler = {
			get: (target, prop) => {
				let object = this._objects[prop];
				if (object && object.isBaseObject) {
					return object;
				}

				return target[prop];
			},
		};

		let proxy = new Proxy(this, handler);
		Object.defineProperty(proxy, 'customFormatters', {
			enumerable: false,
			configurable: false,
			get: () => {
				return ['object', { object: this._objects }];
			}
		});

		return proxy;
	}

	static update(deltaTime) {
		ObjectExpression.update(deltaTime);
	}

	// #region Private

	_queryInWorker(condition, root, recursive) {
		return new Promise((resolve, reject) => {
			// Query in normal async mode if it's just simple expression
			if (condition == '*') {
				let result;

				if (root) {
					result = root.query(condition, { recursive });
				}
				else {
					result = this.onCreateInstance({ objects: this.objects });
				}

				resolve(result);
			}
			else {
				let promise;

				if (root) {
					promise = Selector.asyncSelector.queryAsync(root, recursive, condition);
				}
				else {
					promise = Selector.asyncSelector.selectAsync(this.objects, condition);
				}

				promise.then(result => {
					let objects = this._app.objectManager.objects;

					let filteredObjects = result.orderIDs.map(id => {
						return objects.get(id);
					});

					let selector = this.onCreateInstance({ objects: filteredObjects });
					resolve(selector);
				});
			}
		});
	}

	// #endregion

	/**
	 * 使用对象初始化。
	 * @param {Array<THING.BaseObject>} objects 对象数组。
	 * @private
	 * @returns {THING.Selector} 当前选择器实例。
	 * @example
	 * let selector = new Selector([object1, object2, object3]);
	 */
	init(objects) {
		// Clear previous objects
		this.clear();

		// Set members as Array
		this._objects = objects.slice(0);

		return this;
	}

	applyObjects(funcName, args) {
		this._objects.forEach(object => {
			object[funcName].apply(object, args);
		});
	}

	onCreateInstance() {
		return new Selector(arguments[0]);
	}

	// #region Objects Query Operations

	/**
	 * 根据条件选择对象。
	 * @param {string} condition 条件。
	 * @param {Array<object>} objects 要查询的对象数组。
	 * @returns {Array<object>} 选择的对象数组。
	 * @example
	 * // 从对象中选择实体
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let entities = selector.select('.Entity', objects);
	 * let entity = entities[0];
	 * let ret = entity.isEntity;
	 * // @expect(ret == true)
	 */
	select(condition, objects) {
		let result = [];

		objects = objects || this.objects;

		if (objects.length) {
			if (Utils.isString(condition)) {
				// All
				if (condition == '*') {
					result = objects.slice(0);
				}
				else {
					let expression = _getExpression(condition);

					_selectObjectsByExpression(expression, objects, result);
				}
			}
			// Reg Expression
			else if (Utils.isRegExp(condition)) {
				_selectObjectsByRegExpName(condition, objects, result);
			}
			// Function
			else if (Utils.isFunction(condition)) {
				_selectObjectsByFunction(condition, objects, result);
			}
		}

		return result;
	}

	_selectByCondition(condition, objects, mode) {
		let result = [];

		objects = objects || this.objects;

		if (objects.length) {
			if (Utils.isString(condition)) {
				let expression = _getExpression(condition, mode);

				_selectObjectsByExpression(expression, objects, result);
			}
		}

		return result;
	}

	_outputLogger(funcName, condition) {
		let msg = { "condition": condition };
		Utils.logger.api("Selector_" + funcName, { msg: JSON.stringify(msg) });
	}

	/**
	 * 测试单个对象是否符合指定条件(不考虑对象的查询状态)。
	 * @param {string} condition 条件。
	 * @param {THING.BaseObject} object 要查询的对象。
	 * @returns {boolean} 是否符合条件。
	 * @example
	 * // 测试对象是否符合指定条件
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let object = new THING.Entity();
	 * let ret = selector.test('.Entity', object);
	 * // @expect(ret == true);
	 * let box = new THING.Box();
	 * ret = selector.test('.Entity', box);
	 * // @expect(ret == false);
	 */
	test(condition, object) {
		if (Utils.isString(condition)) {
			// All
			if (condition == '*') {
				return true;
			}
			else {
				let expression = _getExpression(condition);

				return expression.evaluate(object);
			}
		}
		// Reg Expression
		else if (Utils.isRegExp(condition)) {
			return condition.test(object.name);
		}
		// Function
		else if (Utils.isFunction(condition)) {
			return condition(object);
		}

		return false;
	}

	/**
	 * 通过一些条件查找对象并将其存储在结果中。
	 * @param {string} condition 条件。
	 * @param {THING.BaseObject} objects 要查询的对象。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 目标的引用或新选择器。
	 * @example
	 * // 通过指定条件查询/选择对象
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let entitys = selector.query('.Entity');
	 * let entity = entitys[0];
	 * // @expect(entity.isEntity == true);
	 */
	query(condition, objects, target) {
		let objs = objects || this._objects;
		let result = this.select(condition, objs).filter(object => {
			return object.queryable;
		});

		target = target || this.onCreateInstance();

		if (_NEED_LOGGER) {
			this._outputLogger('query', condition.toString());
		}

		return target.init(result);
	}

	/**
	 * 根据某些条件查找对象,不考虑queryable属性。
	 * @param {string} condition 条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 目标选择器的引用或新选择器。
	 * @example
	 * // 通过指定条件查询/选择对象,忽略queryable
	 * let objects = app.queryAll('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let entitys = selector.queryAll('.Entity');
	 * let entity = entitys[0];
	 * // @expect(entity.isEntity == true);
	 */
	queryAll(condition, objects, target) {
		let objs = objects || this._objects;
		let result = this.select(condition, objs);

		target = target || this.onCreateInstance();

		if (_NEED_LOGGER) {
			this._outputLogger('queryAll', condition.toString());
		}

		return target.init(result);
	}

	_queryByAttribute(objects, cb, target) {
		var objs = (objects || this._objects).filter((c) => {
			return cb(c) && c.queryable;
		});
		target = target || this.onCreateInstance();
		return target.init(objs);
	}

	_queryByCondition(condition, objects, target, mode) {
		let objs = objects || this._objects;

		let result = this._selectByCondition(condition, objs, mode).filter(object => {
			return object.queryable;
		});
		target = target || this.onCreateInstance();

		return target.init(result);
	}

	/**
	 * 使用正则表达式查询子对象。
	 * @param {RegExp} condition 选择对象的条件,作为正则表达式。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let car = selector.queryByRegExp(/car/);
	 * let ret = car.length != 0;
	 * // @expect(ret == true)
	 * @public
	 */
	queryByRegExp(condition, objects, target) {
		if (_NEED_LOGGER) {
			this._outputLogger('queryByRegExp', condition.toString());
		}

		return this.query(condition, objects, target);
	}

	/**
	 * 使用正则表达式查询子对象。
	 * @param {RegExp} condition 选择对象的条件,作为正则表达式。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let car = selector.queryByReg(/car/);
	 * console.log(car);
	 * @deprecated 2.7
	 * @private
	 */
	queryByReg(condition, objects, target) {
		return this.queryByRegExp(condition, objects, target);
	}

	/**
	 * 根据标签查询子对象。
	 * @param {string} condition 选择对象的条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let car = selector.queryByTags('Entity');
	 * let ret = car.length != 0;
	 * // @expect(ret == true)
	 * @public
	 */
	queryByTags(condition, objects, target) {
		if (_NEED_LOGGER) {
			this._outputLogger('queryByTags', condition);
		}

		return this._queryByCondition('tags(' + condition + ')', objects, target, 'tags');
	}

	/**
	 * 根据名称查询子对象。
	 * @param {string} condition 选择对象的条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let car = selector.queryByName('car1');
	 * let ret = car.length != 0 && car[0].name == 'car1';
	 * // @expect(ret == true)
	 * @public
	 */
	queryByName(condition, objects, target) {
		if (_NEED_LOGGER) {
			this._outputLogger('queryByName', condition);
		}
		return this._queryByAttribute(objects, (c) => { return c.name == condition }, target);
	}

	/**
	 * 根据UUID查询子对象。
	 * @param {string} condition 选择对象的条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let car = selector.queryByUUID('1605');
	 * let ret = car.length != 0 && car[0].uuid == '1605';
	 * // @expect(ret == true)
	 * @public
	 */
	queryByUUID(condition, objects, target) {
		if (_NEED_LOGGER) {
			this._outputLogger('queryByUUID', condition);
		}
		return this._queryByAttribute(objects, (c) => { return c.uuid == condition }, target);
	}

	/**
	 * 根据id查询子对象。
	 * @param {string} condition 选择对象的条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let car = selector.queryById('car01');
	 * let ret = car.length != 0 && car[0].id == 'car01';
	 * // @expect(ret == true)
	 * @public
	 */
	queryById(condition, objects, target) {
		if (_NEED_LOGGER) {
			this._outputLogger('queryById', condition);
		}
		return this._queryByAttribute(objects, (c) => { return c.id == condition }, target);
	}

	/**
	 * 根据类型查询子对象。
	 * @param {string} condition 选择对象的条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let entitys = selector.queryByType('Entity');
	 * let ret = entitys.length != 0 && entitys[0].type == 'Entity';
	 * // @expect(ret == true)
	 * @public
	 */
	queryByType(condition, objects, target) {
		if (_NEED_LOGGER) {
			this._outputLogger('queryByType', condition);
		}
		var key = "is" + condition;
		return this._queryByAttribute(objects, (c) => { return c[key] == true }, target);
	}

	/**
	 * 根据孪生体类型查询子对象。
	 * @param {string} condition 选择对象的条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let equipment = selector.queryByDTType('Equipment');
	 * let ret = equipment.length != 0 && equipment[0].dtType == 'Equipment';
	 * // @expect(ret == true)
	 * @public
	 */
	queryByDTType(condition, objects, target) {
		if (_NEED_LOGGER) {
			this._outputLogger('queryByDTType', condition);
		}
		return this._queryByAttribute(objects, (c) => { return c.dtType === condition }, target);
	}

	/**
	 * 根据userData查询子对象。
	 * @param {string} condition 选择对象的条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let car = selector.queryByUserData('id="666"')
	 * let ret = car.length != 0 && car[0].userData.id == '666';
	 * // @expect(ret == true)
	 * @public
	 */
	queryByUserData(condition, objects, target) {
		if (_NEED_LOGGER) {
			this._outputLogger('queryByUserData', condition);
		}
		return this._queryByCondition(condition, objects, target, 'userData');
	}

	/**
	 * 根据userData查询子对象。
	 * @param {string} condition 选择对象的条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象数组。
	 * @param {THING.Selector} target 目标选择器。
	 * @returns {THING.Selector} 返回包含查询结果的选择器实例。
	 * @example
	 * 	let car = selector.queryByData('test=1')
	 * 	console.log(car);
	 * @deprecated 2.7
	 * @private
	 */
	queryByData(condition, objects, target) {
		return this.queryByUserData(condition, objects, target);
	}

	/**
	 * 根据某些条件查找对象,并将其存储在结果中,以异步模式查询。
	 * @param {string} condition 条件。
	 * @param {THING.BaseObject} root 根对象。
	 * @param {boolean} recursive 布尔值,表示是否递归查询。
	 * @returns {Promise<THING.Selector>} 返回包含查询结果的选择器实例。
	 * @example
	 * // 从根对象异步查询/选择对象,指定条件
	 * selector.queryAsync('.Entity', rootObject, true).then((result) => {
	 * 	console.log(result);
	 * });
	 * @private
	 */
	queryAsync(condition, root, recursive) {
		// Try to query in worker by async selector
		if (Selector.asyncSelector) {
			return this._queryInWorker(condition, root, recursive);
		}
		else {
			return new Promise((resolve, reject) => {
				let result;

				if (root) {
					result = root.query(condition, { recursive });
				}
				else {
					result = this.query(condition);
				}

				resolve(result);
			});
		}
	}

	/**
	 * 根据条件查找对象并返回第一个对象。
	 * @param {string} condition 条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象。
	 * @returns {THING.BaseObject} 返回第一个对象。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let entity = selector.find('.Entity')
	 * let ret = entity instanceof THING.Entity;;
	 * // @expect(ret == true)
	 * @public
	 */
	find(condition, objects) {
		let objs = objects || this._objects;
		if (!objs.length) {
			return null;
		}

		if (Utils.isString(condition)) {
			// All
			if (condition == '*') {
				return objs[0];
			}
			else {
				let expression = _getExpression(condition);

				return _findObjectsByExpression(expression, objs);
			}
		}
		// Reg Expression
		else if (Utils.isRegExp(condition)) {
			return _findObjectsByRegExpName(condition, objs);
		}
		// Function
		else if (Utils.isFunction(condition)) {
			return _findObjectsByFunction(condition, objs);
		}

		return null;
	}

	/**
	 * 根据条件查找对象并返回第一个对象的索引。
	 * @param {string|RegExp|Function} condition 条件。
	 * @param {THING.BaseObject[]} objects 要查询的对象。
	 * @returns {number} 返回找到的对象的索引,如果未找到则返回 -1。
	 * @example
	 * let objects = app.query('.BaseObject');
	 * let selector = new THING.Selector(objects);
	 * let index = selector.findIndex('.Entity');
	 * // @expect(index >= 0);
	 * @public
	 */
	findIndex(condition, objects) {
		let objs = objects || this._objects;
		if (!objs.length) {
			return -1;
		}

		if (Utils.isString(condition)) {
			// All
			if (condition == '*') {
				return 0;
			}
			else {
				let expression = _getExpression(condition);
				for (let i = 0; i < objs.length; i++) {
					if (expression.evaluate(objs[i])) {
						return i;
					}
				}
			}
		}
		// Reg Expression
		else if (Utils.isRegExp(condition)) {
			for (let i = 0; i < objs.length; i++) {
				if (condition.test(objs[i].name)) {
					return i;
				}
			}
		}
		// Function
		else if (Utils.isFunction(condition)) {
			for (let i = 0; i < objs.length; i++) {
				if (condition(objs[i])) {
					return i;
				}
			}
		}

		return -1;
	}

	/**
	 * 遍历所有对象并执行回调函数。
	 * @param {Function} callback 回调函数。
	 * @example
	 * selector.every(object => {
	 *     return object.isVisible; // 检查每个对象是否可见
	 * });
	 * @returns {boolean} 如果所有对象都满足条件,则返回true,否则返回false。
	 * @public
	 */
	every(callback) {
		return this._objects.every((object, index) => {
			return callback(object, index, this._objects);
		});
	}

	/**
	 * 使用flat将对象数组扁平化。
	 * @param {number} depth 深度,默认为1。
	 * @returns {THING.Selector} 扁平化后的新选择器。
	 * @example
	 * let flatSelector = selector.flat();
	 * console.log(flatSelector);
	 * @public
	 */
	flat(depth = 1) {
		return this.onCreateInstance({ objects: this._objects.flat(depth) });
	}

	/**
	 * 使用flatMap遍历对象并返回一个新选择器。
	 * @param {Function} callback 回调函数。
	 * @returns {THING.Selector} 新选择器,包含回调函数返回的结果。
	 * @example
	 * let results = selector.flatMap(object => {
	 *     return object.children; // 返回每个对象的子对象
	 * });
	 * @public
	 */
	flatMap(callback) {
		let results = [];
		this._objects.forEach((object, index) => {
			const mapped = callback(object, index, this._objects);
			if (Utils.isArray(mapped)) {
				results.push(...mapped);
			}
			else {
				results.push(mapped);
			}
		});

		return this.onCreateInstance({ objects: results });
	}

	// #endregion

	// #region Objects Array Operations

	/**
	 * 将对象推入数组。
	 * @param {...THING.BaseObject|Array<THING.BaseObject>|THING.Selector} args 要推入的对象。
	 * @returns {number} 推入对象后的数组长度。
	 * @example
	 * let objects = app.query('.Entity');
	 * let selector = new THING.Selector(objects);
	 * let count1 = selector.length;
	 * let object = new THING.BaseObject();
	 * let count2 = selector.push(object);
	 * let ret = count2 - count1 == 1;
	 * // @expect(ret == true)
	 * @public
	 */
	push(...args) {
		let arrayLength = this._objects.length;
		for (let i = 0; i < args.length; i++) {
			const arg = args[i];
			if (!arg) {
				continue;
			}

			if (arg.isSelector) {
				arrayLength = _pushArray(this._objects, arrayLength, arg.objects);
			}
			else if (Utils.isArray(arg)) {
				arrayLength = _pushArray(this._objects, arrayLength, arg);
			}
			else {
				this._objects[arrayLength] = arg;
				++arrayLength;
			}
		}
		return arrayLength;
	}

	/**
	 * 根据选择器添加对象,并返回包含结果的新选择器。
	 * @param {THING.Selector|Array<THING.BaseObject>|THING.BaseObject} selector 要添加的选择器或对象。
	 * @returns {THING.Selector} 返回包含结果的选择器实例。
	 * @example
	 * let objects = app.query('.Entity');
	 * let selector = new THING.Selector(objects);
	 * let count1 = selector.length;
	 * let object1 = new THING.BaseObject();
	 * let object2 = new THING.BaseObject();
	 * let newSelector = selector.add([object1,object2]);
	 * let count2 = newSelector.length;
	 * let ret = count2 - count1 == 2;
	 * // @expect(ret == true)
	 * @public
	 */
	add(selector) {
		// Get source objects
		let srcObjects = [];
		if (selector.isSelector) {
			srcObjects = selector.objects;
		}
		else if (Utils.isArray(selector)) {
			srcObjects = selector;
		}
		else if (selector.isBaseObject) {
			srcObjects = [selector];
		}

		// Add objects
		let objects = this._objects.slice(0);
		for (let i = 0; i < srcObjects.length; i++) {
			let index = objects.indexOf(srcObjects[i]);
			if (index === -1) {
				objects.push(srcObjects[i]);
			}
		}

		return this.onCreateInstance({ objects });
	}

	/**
	 * 根据条件删除对象,并返回包含结果的新选择器。
	 * @param {string} condition 条件。
	 * @returns {THING.Selector} 返回包含结果的选择器实例。
	 * @example
	 * let objects = app.query('.Entity');
	 * let selector = new THING.Selector(objects);
	 * selector.remove('.Entity');
	 * let count = selector.length;
	 * let ret = count == 0;
	 * // @expect(ret == true)
	 * @public
	 */
	remove(condition) {
		let candidates = _getObjectsByCondition(condition, this._objects);
		if (!candidates) {
			return this.onCreateInstance({ objects: this.objects });
		}

		// 删除对象
		let objects = this._objects.slice(0);
		for (let i = 0; i < candidates.length; i++) {
			let index = objects.indexOf(candidates[i]);
			if (index !== -1) {
				objects._removeAt(index);
			}
		}

		return this.onCreateInstance({ objects });
	}

	/**
	 * 根据条件删除对象,并返回包含结果的新选择器。
	 * @param {string} condition 条件。
	 * @returns {THING.Selector} 返回包含结果的选择器实例。
	 * @example
	 * // 通过删除选择器/对象返回新的选择器
	 * let objects = selector.not([obj1, obj2, obj3]);
	 * console.log(objects);
	 * @public
	 */
	not(condition) {
		return this.remove(condition);
	}

	/**
	 * 清空对象。
	 * @example
	 * let objects = app.query('.Entity');
	 * let selector = new THING.Selector(objects);
	 * selector.clear();
	 * let ret = count == 0;
	 * // @expect(ret == true)
	 * @public
	 */
	clear() {
		this._objects.length = 0;
	}

	/**
	 * 通过forEach遍历对象。
	 * @callback OnTraverseObjectsInSelector
	 * @param {THING.BaseObject} object 对象。
	 * @param {number} index 对象的索引。
	 * @param {Array<THING.BaseObject>} objects 对象数组。
	 */

	/**
	 * 遍历对象。
	 * @param {OnTraverseObjectsInSelector} callback 回调函数(返回false表示中断遍历,否则继续处理)。
	 * @example
	 * // 遍历选择器中的所有对象
	 * selector.forEach((object) => {
	 * 	console.log(object);
	 * });
	 * @public
	 */
	forEach(callback) {
		let objects = this._objects;

		for (let i = 0, l = objects.length; i < l; i++) {
			callback(objects[i], i, objects);
		}
	}

	/**
	 * 异步模式下遍历对象。
	 * @param {OnTraverseObjectsInSelector} callback 回调函数(返回false表示中断遍历,否则继续处理)。
	 * @example
	 * // 对象逐个飞行(会等待前一个对象飞行完成后再开始)
	 * selector.forEachAsync(object => {
	 * 	return THING.App.current.camera.flyToAsync({
	 * 		target: object,
	 * 		duration: 1 * 1000,
	 * 		distance: 10,
	 * 		delayTime: THING.Math.randomFloat(0, 1000),
	 * 		complete: function (ev) {
	 * 		}
	 * 	});
	 * });
	 * @public
	 */
	forEachAsync(callback) {
		this._objects.forEachAsync(callback);
	}

	/**
	 * Traverse objects in async mode.
	 * @param {OnTraverseObjectsInSelector} callback The callback function(returns false indicates break it, otherwise continue to process it).
	 * @deprecated 2.7
	 * @private
	 * @example
	 * selector.forEachSync(object => {
	 * 	console.log(object);
	 * });
	 */
	forEachSync(callback) {
		this.forEachAsync(callback);
	}

	/**
	 * Traverse self and all children.
	 * @param {Function} callback The callback function.
	 * @example
	 * selector.traverse(object =>{
	 *  console.log(object)
	 * });
	 * @private
	 */
	traverse(callback) {
		var objects = this._objects;
		for (let i = 0, l = objects.length; i < l; i++) {
			objects[i].traverse(callback);
		}
	}

	/**
	 * Traverse self and all children. (Support for exit at traverse runtime)
	 * @param {Function} callback The callback function. (Return false to exit)
	 * @example
	 * selector.traverseBranch(object =>{
	 *  if(object.children.length){
	 *    return false;
	 *  }
	 *  return true;
	 * })
	 * @private
	 */
	traverseBranch(callback) {
		for (let i = 0, l = this._objects.length; i < l; i++) {
			const isBranch = this._objects[i].traverseBranch(callback);
			if (!isBranch) {
				return;
			}
		}
	}

	/**
	 * unique the selector. process the repeat and inherit object
	 * @private
	 * @example
	 *	selector.uniqueObjects();
	 */
	unique() {
		this._objects = Utils.uniqueObjects(this._objects);
	}

	/**
	 * The function to call when to get objects by map.
	 * @callback OnMapObjectsInSelector
	 * @param {THING.BaseObject} object The object.
	 * @param {number} index The index of objects.
	 * @param {Array<THING.BaseObject>} objects The objects.
	 * @returns {THING.BaseObject}
	 */

	/**
	 * 遍历对象并返回一个新的选择器。
	 * @param {OnMapObjectsInSelector} callback 回调函数。
	 * @returns {THING.Selector} 返回包含结果的选择器实例。
	 * @example
	 * // 返回每个对象的第一个子对象
	 * let objects = selector.map((object) => {
	 * 	return object.children[0];
	 * });
	 * @public
	 */
	map(callback) {
		if (!callback) {
			return null;
		}

		let objects = this._objects.map((object, i) => {
			return callback(object, i, this._objects);
		}).filter(object => {
			return !!object;
		});

		return this.onCreateInstance({ objects });
	}

	/**
	 * some 检查是否至少有一个对象满足提供的条件。
	 * @param {Function} callback 回调函数。
	 * @returns {boolean} 如果至少有一个对象满足条件,则返回true,否则返回false。
	 * @example
	 * selector.some(object => {
	 *     return object.isVisible; // 检查是否至少有一个对象可见
	 * });
	 * @public
	 */
	some(callback) {
		return this._objects.some((object, index) => {
			return callback(object, index, this._objects);
		});
	}

	/**
	 * @callback OnReduceObjectsInSelector
	 * @param {*} accumulator 累加器。
	 * @param {THING.BaseObject} object 对象。
	 * @param {number} index 索引。
	 * @param {Array<THING.BaseObject>} objects 对象数组。
	 * @returns {*} 新的累加值。
	 */

	/**
	 * 在选择器中执行用户提供的"reducer"回调函数,按顺序对数组的每个元素进行计算,并传入前一个元素的计算结果。
	 * 在数组的所有元素上运行reducer的最终结果是一个单一的值。
	 * @param {OnReduceObjectsInSelector} callback 回调函数。
	 * @param {number} initialValue 初始值。
	 * @returns {number} 返回计算结果。
	 * @example
	 * // 获取实体的平均高度
	 * let entities = app.query('.Entity');
	 * let height = entities.reduce((value, entity) => {
	 * 	return value + entity.position[1];
	 * }, 0) / entities.length;
	 * @public
	 */
	reduce(callback, initialValue = 0) {
		if (!callback) {
			return 0;
		}

		return this._objects.reduce((accumulator, object, currentIndex) => {
			return callback(accumulator, object, currentIndex, this._objects);
		}, initialValue);
	}

	/**
	 * 返回指定范围内的元素。
	 * @param {number} start 起始索引。
	 * @param {number} end 结束索引。
	 * @returns {THING.Selector} 返回一个新的选择器,包含指定范围内的元素。
	 * @example
	 * // 返回 [1, 4] 范围内的对象
	 * let objects1 = selector.slice(1, 4);
	 *
	 * // 返回 [1, ...] 范围内的对象
	 * let objects2 = selector.slice(1);
	 * @public
	 */
	slice(start, end) {
		return this.onCreateInstance({ objects: this._objects.slice(start, end) });
	}

	/**
	 * 用于筛选对象的回调函数。
	 * @callback OnFilterObjectsInSelector
	 * @param {THING.BaseObject} object 对象。
	 * @param {number} index 对象的索引。
	 * @param {Array<THING.BaseObject>} objects 对象数组。
	 * @returns {boolean}
	 * @public
	 */

	/**
	 * 筛选对象。
	 * @param {OnFilterObjectsInSelector} callback 回调函数。
	 * @returns {THING.Selector} 返回一个新的选择器,包含通过回调函数筛选后的对象。
	 * @example
	 * // 根据名称筛选对象
	 * let objects = selector.filter((object) => {
	 * 	return !!object.name;
	 * });
	 * @public
	 */
	filter(callback) {
		if (!callback) {
			return null;
		}

		let objects = this._objects.filter((object, i) => {
			return callback(object, i, this._objects);
		});

		return this.onCreateInstance({ objects });
	}

	/**
	 * 用于排序对象的回调函数。
	 * @callback OnSortObjectsInSelector
	 * @param {THING.BaseObject} obj1 第一个对象。
	 * @param {THING.BaseObject} obj2 第二个对象。
	 * @returns {number}
	 * < 0: obj1 < obj2
	 * == 0: obj1 == obj2
	 * > 0: obj1 > obj2
	 * @public
	 */

	/**
	 * 按照回调函数的结果,从低到高对对象进行排序。
	 * @param {OnSortObjectsInSelector} callback 用于排序的回调函数。
	 * @returns {THING.Selector} 返回排序后的选择器实例。
	 * @example
	 * // 按照名称对对象进行排序
	 * selector.sort((obj1, obj2) => {
	 * 	return obj1.name.localeCompare(obj2.name);
	 * })
	 * @public
	 */
	sort(callback) {
		let objects = this._objects;

		objects.sort(callback);

		return this;
	}

	/**
	 * 转换为数组(返回一个新的数组)。
	 * @returns {Array<THING.BaseObject>} 返回一个包含选择器中所有对象的新数组。
	 * @example
	 * // 获取/转换为数组模式的对象
	 * let objects = selector.objects;
	 * console.log(objects);
	 * @public
	 */
	toArray() {
		return this._objects.slice(0);
	}

	/**
	 * 检查是否包含指定元素。
	 * @param {object} object 对象。
	 * @returns {boolean} 如果选择器包含指定对象,则返回true,否则返回false。
	 * @example
	 * // 检查是否包含指定对象
	 * let exists = selector.includes(object);
	 * @public
	 */
	includes(object) {
		return this._objects.includes(object);
	}

	/**
	 * 获取对象在数组中的索引。
	 * @param {object} object 对象。
	 * @returns {number} 对象在选择器中的索引,如果对象不存在,则返回-1。
	 * @example
	 * // 获取对象在选择器中的索引
	 * let index = selector.indexOf(object);
	 * @public
	 */
	indexOf(object) {
		return this._objects.indexOf(object);
	}

	/**
	 * 删除对象。
	 * @param {number} index 起始索引。
	 * @param {number} number 要删除的对象数量。
	 * @returns {THING.Selector} 被删除的对象。
	 * @example
	 * // 删除 [1, 4] 范围内的对象
	 * let removeObjects = selector.splice(1, 4);
	 * @public
	 */
	splice(index, number) {
		return this.onCreateInstance({ objects: this._objects.splice(...arguments) });
	}

	/**
	 * 按索引插入对象。
	 * @param {number} index 要插入的索引。
	 * @param {THING.BaseObject} object 要插入的对象。
	 * @returns {THING.Selector} 返回当前选择器实例,用于链式调用。
	 * @example
	 * // 在选择器的开头插入对象
	 * selector.insert(0, [obj1, obj2]);
	 * @public
	 */
	insert(index, object) {
		this._objects.splice(index, 0, object);

		return this;
	}

	/**
	 * 移除指定索引处的对象。
	 * @param {number} index 要移除的对象的索引。
	 * @returns {THING.Selector} 返回当前选择器实例,用于链式调用。
	 * @example
	 * // 移除选择器中的第一个对象。
	 * selector.removeAt(0);
	 * @public
	 */
	removeAt(index) {
		this._objects.splice(index, 1);

		return this;
	}

	/**
	 * 交换指定索引处的对象。
	 * @param {number} index0 第一个对象的索引。
	 * @param {number} index1 第二个对象的索引。
	 * @returns {THING.Selector} 返回当前选择器实例,用于链式调用。
	 * @example
	 * // 交换选择器中索引为0和索引为3的对象。
	 * selector.swap(0, 3);
	 * @public
	 */
	swap(index0, index1) {
		this._objects._swap(index0, index1);

		return this;
	}

	/**
	 * 合并数组。
	 * @param {THING.Selector|Array<THING.BaseObject>} selector 对象数组或选择器。
	 * @returns {THING.Selector} 返回一个新的选择器实例,包含合并后的对象。
	 * @example
	 * // 将其他对象/选择器与当前选择器合并并创建新的选择器。
	 * let newSelector = selector.concat([obj1, obj2]);
	 * @public
	 */
	concat(selector) {
		// 将对象和自身合并到新的选择器中
		if (selector) {
			let candidates = this._objects.concat(selector.isSelector ? selector.objects : selector);

			return this.onCreateInstance({ objects: Array.from(new Set(candidates)) });
		}
		// 返回自身作为新的选择器
		else {
			return this.onCreateInstance({ objects: this._objects.slice() });
		}
	}

	/**
	 * 反转对象。
	 * @returns {THING.Selector} 返回当前选择器实例,用于链式调用。
	 * @example
	 * // 反转选择器中的对象。
	 * selector.reverse();
	 * @public
	 */
	reverse() {
		this._objects.reverse();

		return this;
	}

	/**
	 * 检查是否包含指定对象。
	 * @param {object} object 对象。
	 * @returns {boolean} 如果选择器包含指定对象,则返回true,否则返回false。
	 * @example
	 * // 检查选择器是否包含指定对象。
	 * let exists = selector.has(object);
	 * @public
	 */
	has(object) {
		return this._objects.indexOf(object) !== -1;
	}

	/**
	 * 检查是否为相同的选择器。
	 * @param {Array<object>|THING.Selector} objects 对象数组或选择器。
	 * @returns {boolean} 如果当前选择器与传入的对象数组或选择器相同,则返回true,否则返回false。
	 * @example
	 * let isSame = selector.equals([obj1, obj2]);
	 * @public
	 */
	equals(objects) {
		if (this.length != objects.length) {
			return false;
		}

		for (let i = 0; i < this.length; i++) {
			if (this[i] != objects[i]) {
				return false;
			}
		}

		return true;
	}

	/**
	 * 获取/设置对象的数量。
	 * @type {number}
	 * @example
	 * let length = selector.length;
	 * @public
	 */
	get length() {
		return this._objects.length;
	}
	set length(value) {
		this._objects.length = value;
	}

	/**
	 * Get the objects.
	 * @type {Array<THING.BaseObject>}
	 * @example
	 * let objects = selector.objects;
	 * @private
	 */
	get objects() {
		return this._objects;
	}

	// #endregion

	// #region Objects State Operations

	/**
	 * 获取已加载的对象。
	 * @returns {Array<THING.BaseObject>} 已加载的对象数组。
	 * @private
	 * @example
	 * let loadedObjects = selector.getLoadedObjects();
	 */
	getLoadedObjects() {
		return this._objects.filter(object => {
			return object.loaded;
		});
	}

	/**
	 * 获取未加载的对象。
	 * @returns {Array<THING.BaseObject>} 未加载的对象数组。
	 * @private
	 * @example
	 * let unloadedObjects = selector.getUnloadedObjects();
	 */
	getUnloadedObjects() {
		return this._objects.filter(object => {
			return !object.loaded;
		});
	}

	/**
	 * 获取可见的对象。
	 * @returns {Array<THING.BaseObject>} 可见的对象数组。
	 * @private
	 * @example
	 * let visibleObjects = selector.getVisibleObjects();
	 */
	getVisibleObjects() {
		return this._objects.filter(object => {
			return object.visible;
		});
	}

	/**
	 * 获取不可见的对象。
	 * @returns {Array<THING.BaseObject>} 不可见的对象数组。
	 * @private
	 * @example
	 * let invisibleObjects = selector.getInvisibleObjects();
	 */
	getInvisibleObjects() {
		return this._objects.filter(object => {
			return !object.visible;
		});
	}

	/**
	 * 将对象设置为实例化绘制模式。
	 * @param {boolean} value 如果为true,则启用实例化绘制模式。
	 * @param {object} options 选项。
	 * @example
	 * // 启用对象的实例化绘制
	 * selector.makeInstancedDrawing(true);
	 *
	 * // 禁用对象的实例化绘制
	 * selector.makeInstancedDrawing(false);
	 * @public
	 */
	makeInstancedDrawing(value, options) {
		this._objects.forEach(object => {
			if (!object.isObject3D) {
				return;
			}

			object.makeInstancedDrawing(value, options);
		});
	}

	/**
	 * 获取启用实例化绘制的对象。
	 * @returns {Array<THING.BaseObject>} 启用实例化绘制的对象数组。
	 * @example
	 * // 获取启用实例化绘制的对象
	 * let instancedDrawingObjects = selector.getInstancedDrawingObjects();
	 * @public
	 */
	getInstancedDrawingObjects() {
		return this._objects.filter(object => {
			return object.isInstancedDrawing;
		});
	}

	/**
	 * 设置可见状态。
	 * @param {boolean} value 如果为true,则显示,否则隐藏。
	 * @param {boolean} [recursive=false] 如果为true,则对所有子对象进行处理。
	 * @example
	 * // 将选择器中所有对象的可见属性设置为true
	 * selector.setVisible(true);
	 *
	 * // 将选择器中所有对象及其子对象的可见属性设置为true
	 * selector.setVisible(true, true);
	 * @public
	 */
	setVisible(value, recursive = false) {
		this._objects.forEach(object => {
			object.setVisible(value, recursive);
		});
	}

	/**
	 * 设置所有对象及其子对象的可见状态。
	 * @type {boolean}
	 * @example
	 * // 将选择器中所有对象及其子对象的可见属性设置为true
	 * selector.visible = true;
	 * @public
	 */
	set visible(value) {
		this._objects.forEach(object => {
			object.visible = value;
		});
	}

	/**
	 * 设置所有对象及其子对象的可选状态。
	 * @type {boolean}
	 * @example
	 * // 将选择器中所有对象及其子对象的可选属性设置为true
	 * selector.pickable = true;
	 * @public
	 */
	set pickable(value) {
		this._objects.forEach(object => {
			object.pickable = value;
		});
	}

	/**
	 * 设置所有对象及其子对象的激活状态。
	 * @type {boolean}
	 * @example
	 * // 将选择器中所有对象及其子对象的激活状态设置为true
	 * selector.active = true;
	 * @public
	 */
	set active(value) {
		this._objects.forEach(object => {
			object.active = value;
		})
	}
	// #endregion

	// #region Objects Resource Operations

	/**
	 * 等待所有对象加载完成。
	 * @returns {Promise<any>} 返回一个Promise,resolve时传入已加载完成的对象数组。
	 * @example
	 * // 等待所有对象加载完成,然后打印它们的名称
	 * selector.waitForComplete().then((objects) => {
	 * 	objects.forEach(object => {
	 * 		console.log(object.name);
	 * 	});
	 * });
	 * @public
	 */
	waitForComplete() {
		return this._objects.waitForComplete();
	}

	/**
	 * 按顺序等待所有对象的同步操作完成。
	 * @param {Function} callback 对每个对象执行的回调函数。
	 * @returns {Promise<any>} 返回一个Promise,resolve时传入已完成同步操作的对象数组。
	 * @example
	 * // 按顺序加载每个对象的资源
	 * selector.waitForEachAsync(async (object) => {
	 * 	return object.loadResource();
	 * });
	 * @private
	 */
	waitForEachAsync(callback) {
		return this._objects.waitForEachAsync(callback);
	}

	/**
	 * 按顺序等待所有对象的同步操作完成。
	 * @param {Function} callback 对每个对象执行的回调函数。
	 * @returns {Promise<any>} 返回一个Promise,resolve时传入已完成同步操作的对象数组。
	 * @deprecated 2.7
	 * @private
	 * @example
	 * // 按顺序加载每个对象的资源
	 * selector.waitForEachSync(async (object) => {
	 * 	return object.loadResource();
	 * });
	 */
	waitForEachSync(callback) {
		return this.waitForEachAsync(callback);
	}

	/**
	 * 销毁所有对象。
	 * @example
	 * selector.destroy();
	 * @public
	 */
	destroy() {
		let objects = this._objects.slice(0);

		objects.forEach(object => {
			object.destroy();
		});
	}

	/**
	 * 销毁所有对象 (兼容1.0)。
	 * @example
	 * selector.destroyAll();
	 * @private
	 */
	destroyAll() {
		this.destroy();
	}

	/**
	 * 加载资源。
	 * @param {object} options 加载选项。
	 * @example
	 * selector.loadResource();
	 * @public
	 */
	loadResource(options) {
		this._objects.forEach(object => {
			object.loadResource(false, options);
		});
	}

	/**
	 * 卸载资源。
	 * @example
	 * selector.unloadResource();
	 * @public
	 */
	unloadResource() {
		this._objects.forEach(object => {
			object.unloadResource();
		});
	}

	// #endregion

	// #region 对象事件操作

	/**
	 * 注册所有对象事件。
	 * @param {string} type 事件类型。
	 * @param {string} condition 选择对象的条件。
	 * @param {Function} callback 回调函数。
	 * @param {string} tag 事件标签。
	 * @param {number} priority 优先级值(默认为0,值越高越先处理)。
	 * @param {ObjectEventOptions} options 选项。
	 * @example
	 * // 注册所有实体的'click'事件监听器
	 * let mark = 0;
	 * let entity = new THING.Entity();
	 * entity.on('test', ()=> {
	 *    mark = 1;
	 * })
	 * let selector = new THING.Selector([entity]);
	 * let markOn = 0;
	 * selector.on('testOn', function(ev) {
	 * 		markOn = 1;
	 * });
	 * selector.trigger('testOn');
	 * // @expect(markOn == 1 && mark == 1);
	 * @public
	 */
	on(type, condition, callback, tag, priority, options) {
		this.applyObjects('on', arguments);
	}

	/**
	 * 注册所有对象事件,只触发一次。
	 * @param {string} type 事件类型。
	 * @param {string} condition 选择对象的条件。
	 * @param {Function} callback 回调函数。
	 * @param {string} tag 事件标签。
	 * @param {number} priority 优先级值(默认为0,值越高越先处理)。
	 * @param {ObjectEventOptions} options 选项。
	 * @example
	 * // 注册所有实体的'click'事件监听器
	 * let mark = 0;
	 * let entity = new THING.Entity();
	 * entity.on('test', ()=> {
	 *    mark = 1;
	 * })
	 * let selector = new THING.Selector([entity]);
	 * let markOnce = 0;
	 * selector.once('testOnce', function(ev) {
	 * 		markOnce = 1;
	 * });
	 * selector.trigger('testOnce');
	 * // @expect(markOnce == 1 && mark == 1);
	 * markOnce = 0;
	 * mark = 0;
	 * selector.trigger('testOnce');
	 * // @expect(markOnce == 0 && mark == 0);
	 * @public
	 */
	once(type, condition, callback, tag, priority, options) {
		this.applyObjects('once', arguments);
	}

	/**
	 * 注销所有对象事件。
	 * @param {string} type 事件类型。
	 * @param {string} condition 选择对象的条件。
	 * @param {string} tag 事件标签。
	 * @example
	 * // 通过标签名注销所有具有'click'事件监听器的实体
	 * let mark = 0;
	 * let entity = new THING.Entity();
	 * entity.on('test', ()=> {
	 *    mark = 1;
	 * })
	 * let selector = new THING.Selector([entity]);
	 * let markOff = 0;
	 * selector.on('testOff', function(ev) {
	 * 		markOff = 1;
	 * });
	 * selector.trigger('testOff');
	 * // @expect(markOff == 1 && mark == 1);
	 * markOff = 0;
	 * mark = 0;
	 * selector.off('testOff');
	 * selector.trigger('testOff');
	 * // @expect(markOff == 0 && mark == 0);
	 * @public
	 */
	off(type, condition, tag) {
		this.applyObjects('off', arguments);
	}

	/**
	 * 暂停所有对象的事件。
	 * @param {string} type 事件类型。
	 * @param {string} condition 选择对象的条件。
	 * @param {string} tag 事件标签。
	 * @example
	 * // 通过标签名暂停所有具有'click'事件监听器的实体
	 * let mark = 0;
	 * let entity = new THING.Entity();
	 * entity.on('test', ()=> {
	 *    mark = 1;
	 * })
	 * let selector = new THING.Selector([entity]);
	 * let markPause = 0;
	 * selector.on('testPause', function(ev) {
	 * 		markPause = 1;
	 * });
	 * selector.trigger('testPause');
	 * // @expect(markPause == 1 && mark == 1);
	 * markPause = 0;
	 * mark = 0;
	 * selector.PauseEvent('testPause');
	 * selector.trigger('testPause');
	 * // @expect(markPause == 0 && mark == 0);
	 * @public
	 */
	pauseEvent(type, condition, tag) {
		this.applyObjects('pauseEvent', arguments);
	}

	/**
	 * 恢复所有对象的事件。
	 * @param {string} type 事件类型。
	 * @param {string} condition 选择对象的条件。
	 * @param {string} tag 事件标签。
	 * @example
	 * // 通过标签名恢复所有具有'click'事件监听器的实体
	 * let mark = 0;
	 * let entity = new THING.Entity();
	 * entity.on('test', ()=> {
	 *    mark = 1;
	 * })
	 * let selector = new THING.Selector([entity]);
	 * let markResume = 0;
	 * selector.on('testPause', function(ev) {
	 * 		markResume = 1;
	 * });
	 * selector.trigger('testPause');
	 * // @expect(markResume == 1 && mark == 1);
	 * markResume = 0;
	 * mark = 0;
	 * selector.PauseEvent('testPause');
	 * selector.trigger('testPause');
	 * // @expect(markResume == 0 && mark == 0);
	 * selector.resumeEvent('testPause');
	 * selector.trigger('testPause');
	 * // @expect(markResume == 1 && mark == 1);
	 * @public
	 */
	resumeEvent(type, condition, tag) {
		this.applyObjects('resumeEvent', arguments);
	}

	/**
	 * 触发所有对象的事件。
	 * @param {string} type 事件类型。
	 * @param {object} ev 事件信息。
	 * @param {object} options 选项。
	 * @param {string} options.tag 标签名称。
	 * @example
	 * // 通过标签名触发所有具有'click'事件监听器的实体
	 * let mark = 0;
	 * let entity = new THING.Entity();
	 * entity.on('test', ()=> {
	 *    mark = 1;
	 * })
	 * let selector = new THING.Selector([entity]);
	 * selector.trigger('test');
	 * // @expect(mark == 1)
	 * @public
	 */
	trigger(type, ev, options) {
		this._objects.forEach(object => {
			object.trigger(type, Utils.cloneObject(ev), options?.tag);
		});
	}

	/**
	 * 触发所有对象的事件。
	 * @param {string} type 事件类型。
	 * @param {object} ev 事件信息。
	 * @param {object} options 选项。
	 * @param {string} options.tag 标签名称。
	 * @returns {Promise<any>} 返回一个Promise对象,包含所有对象的事件触发结果。
	 * @example
	 * let entity = new THING.Entity();
	 * let selector = new THING.Selector([entity]);
	 * let mark = 0;
	 * selector.on('testInvoke', function(ev) {
	 * 	mark = ev.value;
	 * });
	 * selector.invoke('testInvoke', { value: 5 });
	 * // @expect(mark == 5);
	 * @public
	 */
	invoke(type, ev, options) {
		return Promise.all(this._objects.map(object => {
			return object.invoke(type, Utils.cloneObject(ev), options?.tag);
		}));
	}

	// #endregion

	// #region Objects Lerp Operations

	stopMoving() {
		this.applyObjects('stopMoving', arguments);
	}

	moveTo() {
		this.applyObjects('moveTo', arguments);
	}

	movePath() {
		this.applyObjects('movePath', arguments);
	}

	stopRotating() {
		this.applyObjects('stopRotating', arguments);
	}

	rotateTo() {
		this.applyObjects('rotateTo', arguments);
	}

	stopScaling() {
		this.applyObjects('stopScaling', arguments);
	}

	scaleTo() {
		this.applyObjects('scaleTo', arguments);
	}

	stopFading() {
		this.applyObjects('stopFading', arguments);
	}

	fadeIn() {
		this.applyObjects('fadeIn', arguments);
	}

	fadeOut() {
		this.applyObjects('fadeOut', arguments);
	}

	stopAnimation() {
		this.applyObjects('stopAnimation', arguments);
	}

	stopAllAnimations() {
		this.applyObjects('stopAllAnimations', arguments);
	}

	playAnimation() {
		this.applyObjects('playAnimation', arguments);
	}

	// #endregion

	// #region Objects Component Operations

	addComponent() {
		if (!Utils.isClass(arguments[0])) {
			Utils.error('Please enter a class!');
			return;
		}
		this.applyObjects('addComponent', arguments);
	}

	removeComponent() {
		this.applyObjects('removeComponent', arguments);
	}

	// #endregion

	// #region Objects Wrapper Operations

	get style() {
		return _styleSelector.init(this._objects);
	}

	get inherit() {
		return _inheritSelector.init(this._objects);
	}

	// #endregion

	// #region Objects Bounding Operations

	/**
	 * 获取轴对齐的边界框(AABB)。
	 * @returns {BASE.THING.Box3} 当前选择器内所有对象合并后的 AABB。
	 * @example
	 * let selector = new THING.Selector();
	 * let box = selector.getBoundingBox();
	 * let ret = box.size[0] == 0;
	 * // @expect(ret == true);
	 * @public
	 */
	getBoundingBox() {
		let aabb = new Box3();

		this._objects.forEach(object => {
			let boundingBox = object.boundingBox;

			aabb.expandByPoint(boundingBox.min);
			aabb.expandByPoint(boundingBox.max);
		});

		return aabb;
	}

	// #endregion

	/**
	 * Check class type.
	 * @type {boolean}
	 * @example
	 * let selector = new THING.Selector();
	 * // @expect(selector.isSelector == true);
	 */
	get isSelector() {
		return true;
	}

}

// #region Static Interface

let _selector = new Selector();

Selector.init = function (param = {}) {
	let workerUrl = param['workerUrl'];
	if (workerUrl) {
		Selector.asyncSelector = new AsyncSelector({ workerUrl });
	}
}

Selector.buildExpression = function (condition, mode) {
	return new ObjectExpression(condition, mode);
}

Selector.testByExpression = function (expression, object) {
	return expression.evaluate(object);
}

Selector.testByRegExpName = function (condition, object) {
	return condition.test(object.name);
}

Selector.testByFunction = function (condition, object) {
	return condition(object);
}

Selector.test = function (condition, object) {
	return _selector.test(condition, object);
}

Selector.select = function (condition, objects) {
	return _selector.select(condition, objects);
}

Selector.query = function (condition, objects) {
	return _selector.query(condition, objects);
}

Selector.queryAsync = function (condition, root, recursive) {
	return _selector.queryAsync(condition, root, recursive);
}

Selector.updateObjectAttribute = function (object, key, value) {
	if (Selector.asyncSelector) {
		Selector.asyncSelector.updateObjectAttribute(object, key, value);
	}
}

Selector.addObject = function (object) {
	if (Selector.asyncSelector) {
		Selector.asyncSelector.addObject(object);
	}
}

Selector.removeObject = function (object) {
	if (Selector.asyncSelector) {
		Selector.asyncSelector.removeObject(object);
	}
}

Selector.updateObjectAttribute = function (object, key, value) {
	if (Selector.asyncSelector) {
		Selector.asyncSelector.updateObjectAttribute(object, key, value);
	}
}

// #endregion

export { Selector };