/** @file
 * @author Edouard DUPIN
 * @copyright 2018, Edouard DUPIN, all right reserved
 * @license PROPRIETARY (see license file)
 */

import { Injectable } from '@angular/core';

import { SessionService, DataStore, TypeCheck } from '@kangaroo-and-rabbit/kar-cw';
import { Media, Season, Series, SeriesResource, UUID } from 'app/back-api';
import { ProgressCallback, RESTAbort, RESTConfig } from 'app/back-api/rest-tools';
import { environment } from 'environments/environment';
import { GenericDataService } from './GenericDataService';
import { SeasonService, MediaService } from '.';



@Injectable()
export class SeriesService extends GenericDataService<Series> {
	getRestConfig(): RESTConfig {
		return {
			server: environment.server.karideo,
			token: this.session.getToken()
		}
	}
	private lambdaGets(): Promise<Series[]> {
		return SeriesResource.gets({ restConfig: this.getRestConfig() });
	}

	constructor(
		private session: SessionService,
		private MediaService: MediaService,
		private seasonService: SeasonService,
	) {
		super();
		console.log('Start SeriesService');
		const self = this;
		this.setStore(new DataStore<Series>(() => self.lambdaGets()));
	}

	/**
	 * Get all the video for a specific series
	 * @param id - Id of the series.
	 * @returns a promise on the list of video elements
	 */
	getVideo(id: number): Promise<Media[]> {
		let self = this;
		return new Promise((resolve, reject) => {
			self.MediaService.getsWhere(
				[
					{
						check: TypeCheck.EQUAL,
						key: 'seriesId',
						value: id,
					}, {
						check: TypeCheck.EQUAL,
						key: 'seasonId',
						value: undefined,
					},
				],
				['episode', 'name'])
				.then((data: Media[]) => {
					resolve(data);
				}).catch((response) => {
					reject(response);
				});
		});
	}

	/**
	 * Get the number of video in this series ID
	 * @param id - Id of the series.
	 * @returns The number of video present in this series
	 */
	countVideo(id: number): Promise<number> {
		let self = this;
		return new Promise((resolve, reject) => {
			self.MediaService.getsWhere(
				[
					{
						check: TypeCheck.EQUAL,
						key: 'seriesId',
						value: id,
					},
				])
				.then((data: Media[]) => {
					resolve(data.length);
				})
				.catch((response) => {
					reject(response);
				});
		});
	}

	/**
	 * Get all the season of a specific series
	 * @param id - ID of the series
	 * @returns the required List.
	 */
	getSeason(id: number): Promise<Season[]> {
		let self = this;
		return new Promise((resolve, reject) => {
			self.seasonService.getsWhere(
				[
					{
						check: TypeCheck.EQUAL,
						key: 'parentId',
						value: id,
					},
				], ['id'])
				.then((data: Season[]) => {
					resolve(data);
				})
				.catch((response) => {
					reject(response);
				});
		});
	}

	getSeriesWithType(typeId: number): Promise<Series[]> {
		let self = this;
		return new Promise((resolve, reject) => {
			self.getsWhere([
				{
					check: TypeCheck.EQUAL,
					key: 'parentId',
					value: typeId,
				}],
				['name'])
				.then((data: Series[]) => {
					resolve(data);
				})
				.catch((response) => {
					reject(response);
				});
		});
	}

	patch(id: number, data: Series): Promise<Series> {
		const self = this;
		return new Promise((resolve, reject) => {
			SeriesResource.patch(
				{
					restConfig: this.getRestConfig(),
					params: {
						id
					},
					data
				})
				.then((value: Media) => {
					self.dataStore.updateValue(value);
					resolve(value);
				})
				.catch((error) => {
					reject(error);
				});
		});
	}

	delete(id: number): Promise<void> {
		const self = this;
		return new Promise((resolve, reject) => {
			SeriesResource.remove(
				{
					restConfig: this.getRestConfig(),
					params: {
						id
					}
				})
				.then(() => {
					self.dataStore.delete(id);
					resolve();
				})
				.catch((error) => {
					reject(error);
				});
		});
	}

	deleteCover(id: number, coverId: UUID): Promise<Series> {
		let self = this;
		return new Promise((resolve, reject) => {
			SeriesResource.removeCover({
				restConfig: this.getRestConfig(),
				params: {
					id,
					coverId
				}
			}).then((value) => {
				self.dataStore.updateValue(value);
				resolve(value);
			}).catch((error) => {
				reject(error);
			});
		});
	}
	uploadCover(id: number,
		file: File,
		progress: ProgressCallback | undefined = undefined,
		cancelHandle: RESTAbort | undefined = undefined): Promise<Media> {
		let self = this;
		return new Promise((resolve, reject) => {
			SeriesResource.uploadCover({
				restConfig: this.getRestConfig(),
				params: {
					id,
				},
				data: {
					file,
				},
				callbacks: {
					progressUpload: progress,
					abortHandle: cancelHandle,
				}
			}).then((value) => {
				self.dataStore.updateValue(value);
				resolve(value);
			}).catch((error) => {
				reject(error);
			});
		});
	}


}

