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

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

import { Member } from '@overflow/commons-typescript/model/member';
import { MemberService } from '../../../service/member.service';

import {
  Signin,
  Signup,
  SignupSuccess,
  SignupFailure,
  Modify,
  ModifySuccess,
  ModifyFailure,
  ResetPassword,
  ResetPasswordSuccess,
  ResetPasswordFailure,
  ModifyPassword,
  ModifyPasswordSuccess,
  ModifyPasswordFailure,
  ActionType,
} from './member.action';

import {
  SigninSuccess,
  SigninFailure,
  SigninCookieSuccess,
  SigninCookieFailure,
} from '@overflow/shared/auth/store/container/auth';
import { DomainMember } from '@overflow/commons-typescript/model/domain';


@Injectable()
export class Effects {

  constructor(
    private actions$: Actions,
    private memberService: MemberService,
    private router: Router
  ) { }

  @Effect()
  signin$ = this.actions$.pipe(
    ofType(ActionType.Signin),
    map((action: Signin) => action.payload),
    exhaustMap((signinInfo: { email: string, password: string, returnURL: string }) =>
      this.memberService
        .signin(signinInfo.email, signinInfo.password)
        .pipe(
          map((result: { authToken: string, domainMember: DomainMember }) => {
            return new SigninSuccess({ authToken: result.authToken, domainMember: result.domainMember, returnURL: signinInfo.returnURL });
          }),
          catchError(error => of(new SigninFailure(error)))
        )
    )
  );

  @Effect()
  signup$ = this.actions$.pipe(
    ofType(ActionType.Signup),
    map((action: Signup) => action.payload),
    exhaustMap((signupInfo: { member: Member, password: string }) =>
      this.memberService
        .signup(signupInfo.member, signupInfo.password)
        .pipe(
          map((member: Member) => {
            return new SignupSuccess(member);
          }),
          catchError(error => of(new SignupFailure(error)))
        )
    )
  );

  @Effect()
  modify$ = this.actions$.pipe(
    ofType(ActionType.Modify),
    map((action: Modify) => action.payload),
    exhaustMap((member: Member) =>
      this.memberService
        .modify(member)
        .pipe(
          map((newMember: Member) => {
            return new ModifySuccess(newMember);
          }),
          catchError(error => of(new ModifyFailure(error)))
        )
    )
  );

  @Effect()
  resetPassword$ = this.actions$.pipe(
    ofType(ActionType.ResetPassword),
    map((action: ResetPassword) => action.payload),
    exhaustMap((email: string) =>
      this.memberService
        .sendEmailResetPassword(email)
        .pipe(
          map((newMember: Member) => {
            return new ResetPasswordSuccess(newMember);
          }),
          catchError(error => of(new ResetPasswordFailure(error)))
        )
    )
  );

  @Effect()
  modifyPassword$ = this.actions$.pipe(
    ofType(ActionType.ModifyPassword),
    map((action: ModifyPassword) => action.payload),
    exhaustMap((info: { token: string, password: string, confirmPassword: string }) =>
      this.memberService
        .resetPassword(info.token, info.password, info.confirmPassword)
        .pipe(
          map((newMember: Member) => {
            return new ModifyPasswordSuccess(newMember);
          }),
          catchError(error => of(new ModifyPasswordFailure(error)))
        )
    )
  );
}
