// eslint-disable-next-line @typescript-eslint/no-unused-vars
declare interface Array<T> {
	/**
	 * 移除一個值並且回傳
	 * @param index
	 */
	ExRemoveAt(index: number): T

	/**
	 * 移除全部值(注意. 參考的也會被清空)
	 * @example
	 *
	 *  let bar: number[] = [1, 2, 3];
	 *  let bar2: number[] = bar;
	 *  bar.Clear();
	 *  console.log(bar, bar2);
	 *
	 *  // {
	 *  //     "bar": [],
	 *  //     "bar2": []
	 *  // }
	 */
	Clear(): void

	/**
	 * 拷貝
	 * PS. pass by value 多維陣列也ＯＫ
	 */
	Copy(): T[]

	/**
	 * 物件陣列排序，asc&key陣列長度請一樣
	 * PS. boolean 帶false是先true在false
	 * @link JavaScript Object 排序 http://www.eion.com.tw/Blogger/?Pid=1170#:~:text=JavaScript%20Object%20排序
	 * @param asc 是否升序排列(小到大)
	 * @param key 需排序的key(優先順序左到右)(沒有就放空)
	 */
	ObjectSort(asc?: boolean[], key?: string[]): T[]

	/**
	 * 設計給Array<cc.Component.EventHandler>forHoldButton使用
	 * Add a none persistent listener to the UnityEvent.
	 * @param call Callback function.
	 */
	// eslint-disable-next-line @typescript-eslint/ban-types
	AddListener(call: Function): void
}

Array.prototype.ExRemoveAt ||
	Object.defineProperty(Array.prototype, "ExRemoveAt", {
		enumerable: false,
		value: function (index: number): any {
			const item: any = this.splice(index, 1);
			return item[0];
		},
	});

Array.prototype.Clear ||
	Object.defineProperty(Array.prototype, "Clear", {
		enumerable: false,
		value: function (): void {
			this.length = 0;

			// let foo: number[] = [1, 2, 3];
			// let bar: number[] = [1, 2, 3];
			// let foo2: number[] = foo;
			// let bar2: number[] = bar;
			// foo = [];
			// bar.length = 0;
			// console.log(foo, bar, foo2, bar2);

			// {
			//     "foo": [],
			//     "bar": [],
			//     "foo2": [
			//       1,
			//       2,
			//       3
			//     ],
			//     "bar2": []
			// }
		},
	});

Array.prototype.Copy ||
	Object.defineProperty(Array.prototype, "Copy", {
		enumerable: false,
		value: function (): any[] {
			return Array.from(this);
		},
	});

Array.prototype.ObjectSort ||
	Object.defineProperty(Array.prototype, "ObjectSort", {
		enumerable: false,
		/**
		 * @param asc 是否升序排列(小到大)
		 * @param key 需排序的key(優先順序左到右)(沒有就放空)
		 */
		value: function (asc: boolean[] = [true], key?: string[]): any[] {
			if (this.length === 0) {
				return this;
			} else if (!key || key.length === 0) {
				console.error("ObjectSort key error");
				return this;
			} else if (asc.length !== key.length) {
				console.error(
					`ObjectSort key asc error asc.length: ${asc.length}, key.length: ${key.length}`,
				);
				return this;
			}
			for (let i: number = 0; i < key.length; i++) {
				const keyname: string = key[i];
				if (this[0][keyname] === undefined) {
					console.error(`ObjectSort has not key[${i}]: ${keyname}`);
					return this;
				}
			}
			const count: number = key ? key.length : 1;
			let arr: any[];
			for (let i: number = count - 1; i >= 0; i--) {
				arr = this.sort(function (a: any, b: any): 1 | -1 {
					let mya: any = a;
					let myb: any = b;
					if (key) {
						mya = a[key[i]];
						myb = b[key[i]];
					}

					// 加個等於數字相同不要再去排序到
					if (asc[i]) {
						return mya >= myb ? 1 : -1;
					} else {
						return mya <= myb ? 1 : -1;
					}
				});
			}
			return arr;
		},
	});
