import apiService, { ApiService } from './api.service';
import { CodeVo } from './common.interface';

/**
 * Code service
 */
export class CodeService {
	/**
	 * Instance  of code service
	 */
	private static _instance: CodeService | null = null;

	/**
	 * Api  of code service
	 */
	private _api: ApiService = null;

	/**
	 * Creates an instance of code service.
	 */
	constructor() {
		this._api = apiService;
	}

	/**
	 * Gets instance
	 *
	 * @returns instance
	 */
	public static getInstance(): CodeService {
		if (this._instance === null) {
			this._instance = new CodeService();
		}
		return this._instance;
	}

	/**
	 * Loaded codes of code service
	 */
	private _loadedCodes: { [key: string]: CodeVo[] } = {};

	/**
	 * Inits form value
	 *
	 * @param container
	 * @param codeList
	 */
	public initFormValue(container: { [key: string]: any }, codeList: string[]) {
		const initValues: any[] = [];
		codeList.forEach((key) => {
			initValues.push(container[key]);
			container[key] = null;
		});
		setTimeout(() => {
			codeList.forEach((key, i) => {
				container[key] = initValues[i];
			});
		}, 100);
	}

	/**
	 * Synks code
	 *
	 * @param container
	 * @param codeList
	 * @returns code
	 */
	public synkCode(container: { [key: string]: any }, codeList: { [key: string]: string }): Promise<void> {
		return new Promise<void>((resolve) => {
			let added = 0;
			for (const key in codeList) {
				added++;
				const codeCd = codeList[key];
				this.getCode(codeCd)
					.then((codeData) => {
						container[key] = codeData;
					})
					.finally(() => {
						added--;
						if (added === 0) {
							resolve();
						}
					});
			}
		});
	}

	/**
	 * Gets code
	 *
	 * @param key
	 * @returns code
	 */
	public getCode(key: string): Promise<CodeVo[]> {
		return new Promise<CodeVo[]>((resolve) => {
			if (this._loadedCodes[key] === undefined) {
				const codeData: CodeVo[] = [];
				this._loadedCodes[key] = codeData;
				this._api.get('api/codes/' + key).then((result) => {
					if (Array.isArray(result)) {
						result.forEach((item) => {
							codeData.push(item);
						});
					}
					resolve(codeData);
				});
			} else {
				resolve(this._loadedCodes[key]);
			}
		});
	}
}

export default CodeService.getInstance();
