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

import { Effect, Actions, ofType } from '@ngrx/effects';
import { of } from 'rxjs/observable/of';
import { catchError, exhaustMap, map } from 'rxjs/operators';

import { MemberTotpService } from '../../../service/member-totp.service';

import {
  CreateTotp,
  CreateTotpSuccess,
  CreateTotpFailure,

  Regist,
  RegistSuccess,
  RegistFailure,

  CheckCodeForMember,
  CheckCodeForMemberSuccess,
  CheckCodeForMemberFailure,

  ActionType,
} from './member-totp.action';
import {Member} from '@overflow/commons-typescript/model/member';

@Injectable()
export class Effects {

  constructor(
    private actions$: Actions,
    private memberTotpService: MemberTotpService,
  ) { }

  @Effect()
  createTotp$ = this.actions$.pipe(
    ofType(ActionType.CreateTotp),
    map(( action: CreateTotp ) => action.payload),
    exhaustMap(( member: Member ) =>
      this.memberTotpService
        .createTotp(member)
        .pipe(
          map((result: any) => {
            return new CreateTotpSuccess({ key: result.secretKey, uri: result.sourceURI});
          }),
          catchError(error => of(new CreateTotpFailure(error)))
        )
    )
  );

  @Effect()
  regist$ = this.actions$.pipe(
    ofType(ActionType.Regist),
    map(( action: Regist ) => action.payload),
    exhaustMap(( totpInfo: { member: Member, secretCode: string, code: string } ) =>
      this.memberTotpService
        .regist(totpInfo.member, totpInfo.secretCode, totpInfo.code)
        .pipe(
          map(() => {
            return new RegistSuccess();
          }),
          catchError(error => of(new RegistFailure(error)))
        )
    )
  );

  @Effect()
  checkCodeForMember$ = this.actions$.pipe(
    ofType(ActionType.CheckCodeForMember),
    map(( action: CheckCodeForMember ) => action.payload),
    exhaustMap(( totpInfo: { member: Member, code: string } ) =>
      this.memberTotpService
        .checkCodeForMember(totpInfo.member, totpInfo.code)
        .pipe(
          map((result: boolean) => {
            return new CheckCodeForMemberSuccess(result);
          }),
          catchError(error => of(new CheckCodeForMemberFailure(error)))
        )
    )
  );
}
