import { DataStore, DataTools, TypeCheck, isNullOrUndefined } from "@kangaroo-and-rabbit/kar-cw";
import { SelectModel } from "@kangaroo-and-rabbit/kar-cw/utils/data-tools";

export class GenericDataService<TYPE> {
	protected dataStore: DataStore<TYPE>;

	setStore(dataStore: DataStore<TYPE>) {
		this.dataStore = dataStore;
	}


	gets(): Promise<TYPE[]> {
		return this.dataStore.getData();
	}

	get(id: number): Promise<TYPE> {
		let self = this;
		return new Promise((resolve, reject) => {
			self.gets()
				.then((response: TYPE[]) => {
					let data = DataTools.get(response, id);
					if (isNullOrUndefined(data)) {
						reject('Data does not exist in the local BDD');
						return;
					}
					resolve(data);
					return;
				}).catch((response) => {
					reject(response);
				});
		});
	}

	getAll(ids: number[]): Promise<TYPE[]> {
		let self = this;
		return new Promise((resolve, reject) => {
			self.gets()
				.then((response: TYPE[]) => {
					let data = DataTools.getsWhere(response,
						[
							{
								check: TypeCheck.EQUAL,
								key: 'id',
								value: ids,
							},
						]);
					resolve(data);
					return;
				}).catch((response) => {
					reject(response);
				});
		});
	}

	getFilter(filter: (subData: any) => boolean): Promise<TYPE[]> {
		let self = this;
		return new Promise((resolve, reject) => {
			self.gets()
				.then((data: TYPE[]) => {
					if (isNullOrUndefined(data)) {
						reject('Data does not exist in the local BDD');
						return;
					}
					let out: TYPE[] = [];
					for (const elem of data) {
						if (filter(elem)) {
							out.push(elem);
						}
					}
					resolve(out);
					return;
				}).catch((response) => {
					reject(response);
				});
		});
	}

	getLike(value: string): Promise<TYPE[]> {
		let self = this;
		return new Promise((resolve, reject) => {
			self.gets()
				.then((response: TYPE[]) => {
					let data = DataTools.getNameLike(response, value);
					if (isNullOrUndefined(data) || data.length === 0) {
						reject('Data does not exist in the local BDD');
						return;
					}
					resolve(data);
					return;
				}).catch((response) => {
					reject(response);
				});
		});
	}

	getOrder(): Promise<TYPE[]> {
		return this.getsWhere(
			[
				{
					check: TypeCheck.NOT_EQUAL,
					key: 'id',
					value: [undefined, null],
				},
			],
			["name", "id"],
		);
	}

	getsWhere(select: SelectModel[], orderByData?: string[]): Promise<TYPE[]> {
		let self = this;
		return new Promise((resolve, reject) => {
			self.gets()
				.then((response: TYPE[]) => {
					let data = DataTools.getsWhere(response, select, orderByData);
					resolve(data);
				}).catch((response) => {
					console.log(`[E] ${self.constructor.name}: can not retrieve BDD values`);
					reject(response);
				});
		});
	}

}