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

import { Effect, Actions, ofType } from '@ngrx/effects';
import { Action } from '@ngrx/store';

import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/exhaustMap';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';

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

import {
  Signin,
  SigninCookie,
  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$: Observable<Action> = this.actions$
    .ofType(ActionType.Signin)
    .map((action: Signin) => action.payload)
    .switchMap(payload => {
      return this.memberService.signin(payload.email, payload.password);
    })
    .map((result: { authToken: string, domainMember: DomainMember }) => {
      return new SigninSuccess({ authToken: result.authToken, domainMember: result.domainMember });
    })
    .catch((error: RESTClientError) => {
      return of(new SigninFailure(error));
    });

  @Effect()
  signinCookie$: Observable<Action> = this.actions$
    .ofType(ActionType.SigninCookie)
    .map((action: SigninCookie) => action.payload)
    .switchMap((payload) => {
      return this.memberService.signin_cookie(payload.authToken);
    })
    .map((domainMember: DomainMember) => {
      return new SigninCookieSuccess(domainMember);
    })
    .catch((error: RESTClientError) => {
      return of(new SigninFailure(error));
    });

  @Effect()
  signup$: Observable<Action> = this.actions$
    .ofType(ActionType.Signup)
    .map((action: Signup) => action.payload)
    .exhaustMap(payload =>
      this.memberService.signup(payload.member, payload.password)
        .map(member => new SignupSuccess(member))
        .catch(error => of(new SignupFailure(error)))
    );

  @Effect()
  modify$: Observable<Action> = this.actions$
    .ofType(ActionType.Modify)
    .map((action: Modify) => action.payload)
    .exhaustMap(payload =>
      this.memberService.modify(payload)
        .map(member => new ModifySuccess(member))
        .catch(error => of(new ModifyFailure(error)))
    );

  @Effect()
  resetPassword$: Observable<Action> = this.actions$
    .ofType(ActionType.ResetPassword)
    .map((action: ResetPassword) => action.payload)
    .exhaustMap(payload =>
      this.memberService
        .sendEmailResetPassword(payload)
        .map(member => new ResetPasswordSuccess(member))
        .catch(error => of(new ResetPasswordFailure(error)))
    );

  @Effect()
  ModifyPassword$: Observable<Action> = this.actions$
    .ofType(ActionType.ModifyPassword)
    .map((action: ModifyPassword) => action.payload)
    .exhaustMap(payload =>
      this.memberService
        .resetPassword(payload.token, payload.password, payload.confirmPassword)
        .map(member => new ModifyPasswordSuccess(member))
        .catch(error => of(new ModifyPasswordFailure(error)))
    );
}
