import { IEventAggregationService, ISubscriber } from "@studyportals/event-aggregation-service-interface";
import { ITokenBasedSessionService,	SessionServiceReadyEvent } from '@studyportals/student-interfaces';
import { IStudent, StudentField } from '@studyportals/studentdomain';
import { Actor, InterestType, StudentRepositoryStateType } from '../../../interfaces';
import { CatchReportAsyncException, CatchReportException } from '../../decorators/error-decorators';
import { Deferred } from '../deferred';
import { StudentRepository } from '../student-repository';
import { StudentRepositoryState } from './student-repository-state';

export class PendingStudentRepositoryState extends StudentRepositoryState implements ISubscriber<SessionServiceReadyEvent> {
	private state?: StudentRepositoryState;
	private lock: Deferred;

	constructor(
		eventAggregationService: IEventAggregationService,
		sessionService: ITokenBasedSessionService,
		studentRepository: StudentRepository
	) {
		super(StudentRepositoryStateType.PENDING, eventAggregationService, sessionService, studentRepository);
		this.lock = new Deferred();
	}

	@CatchReportException
	public initialize(): void {
		this.eventAggregationService.subscribeTo(SessionServiceReadyEvent.EventType, this, true);
	}

	@CatchReportAsyncException
	public async notify(event: SessionServiceReadyEvent): Promise<void> {
		await this.onSessionServiceReady(event.sessionService);
	}

	public async setStudentData(studentData: IStudent, actor: Actor): Promise<void> {
		await this.lock.untilOpen();
		return this.state!.setStudentData(studentData, actor);
	}

	public async getStudentData(studentFields: StudentField[]): Promise<IStudent> {
		await this.lock.untilOpen();
		return this.state!.getStudentData(studentFields);
	}

	public async addToCollection(type: StudentField, items: any[]): Promise<void> {
		await this.lock.untilOpen();
		return this.state!.addToCollection(type, items);
	}

	public async removeFromCollection(type: StudentField, items: any[]): Promise<void> {
		await this.lock.untilOpen();
		return this.state!.removeFromCollection(type, items);
	}

	private async onSessionServiceReady(sessionService: any): Promise<void> {

		const session = await sessionService.getSession();

		const online = this.studentRepository.onlineState;
		const offline = this.studentRepository.offlineState;

		this.state = (session === null) ? offline : online;

		this.studentRepository.updateState(this.state);
		this.lock.open();

		if (this.state === online) {
			await offline.syncData();
		}
	}
}
