import { Utils } from '../common/Utils'
import { BaseDynamicPoints } from './BaseDynamicPoints';
import { UVMode } from '../const';
import { LineUVAnimationComponent } from '../components/LineUVAnimationComponent'

// [0-15] index is reserved for BaseObject and Object3D, so index starts from 16
const Flag = {
	Closure: 1 << 16,
}

const registerComponentParam = { isResident: true };

/**
 * @class BaseLine
 * 所有线的基类
 * @memberof THING
 * @extends THING.BaseDynamicPoints
 * @public
 */
class BaseLine extends BaseDynamicPoints {

	static defaultTagArray = ['Line'];

	/**
	 * 构造函数
	 * The base line object.
	 * @param {object} param The initial parameters.
	 * @param {boolean} [param.uvScroll=false] 是否开启贴图流动
	 * @param {number[]} [param.uvScrollSpeed=[1,0]] 贴图流动速度
	 * @example
	 * class CustomLine extends THING.BaseLine {
	 *   constructor() {
	 *     super({
	 *       uvScroll: true,
	 *       uvScrollSpeed: [2, 0]
	 *     });
	 *   }
	 * }
	 * const line = new CustomLine();
	 */
	constructor(param = {}) {
		super(param);
	}

	// #region Private

	// #endregion

	// #region Overrides

	onSetupResource(param) {
		this._uvModeType = Utils.parseValue(param['uvModeType'], UVMode.Tile);
		this._groups = Utils.parseValue(param['groups'], []);
		this._groupPickedIds = Utils.parseValue(param['groupPickedIds'], []);
		this._groupsVisible = Utils.parseValue(param['groupsVisible'], []);
		this.uvScrollSpeed = Utils.parseValue(param['uvScrollSpeed'], [1.0, 0.0]);
		this.uvScroll = Utils.parseValue(param['uvScroll'], false);
		this._flags.enable(Flag.Closure, Utils.parseValue(param['closure'], false));

		super.onSetupResource(param);
	}


	onSetupBodyNode(node) {
		super.onSetupBodyNode(node);

		if (this._groups.length) {
			node.setGroups(this._groups);
		}
		node.setUVMode(this._uvModeType);
		node.setAttribute('Closure', this._flags.has(Flag.Closure));
		node.setGroupPickedIds(this._groupPickedIds);
		node.setGroupsVisible(this._groupsVisible);

		this.uvScrollSpeed = this.uvScrollSpeed;
		this.uvScroll = this.uvScroll;
	}

	onExportExternalData() {
		let external = Object.assign({}, super.onExportExternalData());
		Utils.setAttributeIfExist(external, 'closure', this);
		Utils.setAttributeIfExist(external, 'progress', this);
		Utils.setAttributeIfExist(external, 'uvModeType', this);
		Utils.setAttributeIfExist(external, 'groups', this);
		Utils.setAttributeIfExist(external, 'groupPickedIds', this);
		if (this.uvScroll) {
			Utils.setAttributeIfExist(external, 'uvScrollSpeed', this);
			Utils.setAttributeIfExist(external, 'uvScroll', this);
		}
		return external;
	}

	onSetupComponent(param) {
		super.onSetupComponent(param);
		this.addComponent(LineUVAnimationComponent, 'uvAnimation', registerComponentParam);
	}

	onRefreshPoints() {
		super.onRefreshPoints();

		let bodyNode = this.bodyNode;

		if (this._groups.length) {
			bodyNode.setGroups(this._groups);
		}

		bodyNode.setUVMode(this._uvModeType);
		bodyNode.setAttribute('Closure', this._flags.has(Flag.Closure));
	}

	// #endregion

	// #region Accessor

	/**
	 * Get/Set uv.
	 * @param {Array<number>} uv The uv value array [u, u, ...].
	 * @example
	 * // 设置 uv
	 * line.setUv([0.5, 0.5, 0.5, 0.5, 0.5, 0.5]);
	 * // 获取 uv
	 * const uv = line.getUv();
	 * @public
	 */
	setUv(uv) {
		this.bodyNode.setUv(uv);
	}

	/**
	 * Get uv.
	 * @returns {Array<number>} The uv value array [u, u, ...].
	 * @example
	 * // 获取 uv
	 * const uv = line.getUv();
	 * @public
	 */
	getUv() {
		return this.bodyNode.getUv();
	}

	/**
	 * Get/Set UV mode type.
	 * @type {UVMode}
	 * @private
	 */
	get uvModeType() {
		return this._uvModeType;
	}
	set uvModeType(value) {
		if (this._uvModeType == value) {
			return;
		}

		this._uvModeType = value;

		this.onRefreshPoints();
	}

	/**
	 * 获取/设置点的索引分组。
	 * @type {Array<Array<number>>}
	 * @example
	 * // 设置分组
	 * [[startIndex, length], [startIndex, length]]
	 * this.groups = [[0, 1], [3, 4]];
	 * // 获取分组
	 * const groups = this.groups;
	 * // 获取分组数量
	 * const groupCount = this.groups.length;
	 * // 获取分组中的点数量
	 * const groupPointCount = this.groups[0].length;
	 * @public
	 */
	get groups() {
		return this._groups;
	}
	set groups(value) {
		if (value) {
			this._groups = value.slice(0);
		}
		else {
			this._groups = [];
		}

		this.onRefreshPoints();
	}
	/**
	 * 获取/设置选中的组 Ids。
	 * @type {Array<number>}
	 * @example
	 * // 设置选中的组 Ids
	 * this.groupPickedIds = [0, 1, 2];
	 * // 获取选中的组 Ids
	 * const groupPickedIds = this.groupPickedIds;
	 * @public
	 */
	get groupPickedIds() {
		return this._groupPickedIds;
	}
	set groupPickedIds(value) {
		if (value) {
			this._groupPickedIds = value.slice(0);
		}
		else {
			this._groupPickedIds.length = 0;
		}

		this.bodyNode.setGroupPickedIds(this._groupPickedIds);
	}

	/**
	 * 获取/设置分组的可见性。
	 * @type {Array<boolean>}
	 * @example
	 * // 设置分组的可见性
	 * this.groupsVisible = [true, false, true];
	 * // 获取分组的可见性
	 * const groupsVisible = this.groupsVisible;
	 * @public
	 */
	get groupsVisible() {
		return this._groupsVisible;
	}
	set groupsVisible(value) {
		if (value) {
			this._groupsVisible = value.slice(0);
		}
		else {
			this._groupsVisible.length = 0;
		}

		this.bodyNode.setGroupsVisible(this._groupsVisible);
	}

	/**
	 * 启用/禁用闭包。
	 * @type {boolean}
	 * @example
	 * // 启用闭包
	 * this.closure = true;
	 * // 禁用闭包
	 * this.closure = false;
	 * @public
	 */
	get closure() {
		return this._flags.has(Flag.Closure);
	}
	set closure(value) {
		if (this._flags.enable(Flag.Closure, value)) {
			this.onRefreshPoints();
		}
	}

	/**
	 * 设置/获取 贴图流动速度
	 * @default [1.0,0.0]
	 * @type {Array<number>}
	 * @example
	 * // 设置贴图流动速度
	 * this.uvScrollSpeed = [1.0, 0.0];
	 * // 获取贴图流动速度
	 * const uvScrollSpeed = this.uvScrollSpeed;
	 * @public
	 */
	set uvScrollSpeed(value) {
		this.uvAnimation.setUVScrollSpeed(value);
	}
	get uvScrollSpeed() {
		return this.uvAnimation.getUVScrollSpeed();
	}

	/**
	 * 开启/关闭 贴图动画
	 * </br>启用/禁用 UV 滚动动画
	 * @type {boolean}
	 * @example
	 * // 设置贴图动画
	 * this.uvScroll = true;
	 * // 获取贴图动画
	 * const uvScroll = this.uvScroll;
	 * @public
	 */
	set uvScroll(value) {
		this.uvAnimation.setUVScroll(value);
	}
	get uvScroll() {
		return this.uvAnimation.getUVScroll();
	}

	// #endregion

	get isLine() {
		return true;
	}

}

export { BaseLine }