import { IEventAggregationService, ISubscriber } from "@studyportals/event-aggregation-service-interface";
import { ITokenBasedSessionService, SessionDestroyedEvent } from '@studyportals/student-interfaces';
import { IStudent, StudentField } from '@studyportals/studentdomain';
import { Actor, InterestType, StudentRepositoryStateType } from '../../../interfaces';
import { CatchReportException } from '../../decorators/error-decorators';
import { AnonymousStudentEventBroadcaster } from '../../infrastructure/anonymous-student-event-broadcaster';
import { CachedStudentClient } from '../../infrastructure/clients/cached-student-client';
import { LocalStudentClient } from '../../infrastructure/clients/local-student-client';
import { StudentAPIClient } from '../../infrastructure/clients/student-api-client';
import { StudentRepository } from '../student-repository';
import { StudentRepositoryState } from './student-repository-state';

export class OnlineStudentRepositoryState extends StudentRepositoryState implements ISubscriber<SessionDestroyedEvent> {

	private studentClient: CachedStudentClient | null = null;

	constructor(
		protected eventAggregationService: IEventAggregationService,
		protected sessionService: ITokenBasedSessionService,
		protected studentRepository: StudentRepository
	) {
		super(StudentRepositoryStateType.ONLINE, eventAggregationService, sessionService, studentRepository);
	}

	private constructStudentClient(): CachedStudentClient {
		const anonymousStudentEventBroadcaster = new AnonymousStudentEventBroadcaster(this.eventAggregationService);
		const localClient = new LocalStudentClient('AnonymousStudent/Online', 3600);
		const studentAPIClient = new StudentAPIClient(this.sessionService);
		return new CachedStudentClient(studentAPIClient, localClient, this.eventAggregationService, anonymousStudentEventBroadcaster);
	}

	@CatchReportException
	public initialize(): void {
		this.studentClient = this.constructStudentClient();
		this.eventAggregationService.subscribeTo(SessionDestroyedEvent.EventType, this);
	}

	public notify(event: any): void {
		this.studentClient!.clearCache();
	}

	public async setStudentData(studentData: IStudent, actor: Actor): Promise<void> {
		return this.studentClient!.setData(studentData);
	}

	public async getStudentData(studentFields: StudentField[]): Promise<IStudent> {
		return this.studentClient!.getData(studentFields);
	}

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

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

}
