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

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

import { CookieService } from 'ngx-cookie-service';
import { RPCService } from '@loafer/ng-rpc';

import {
  SigninSuccess,
  SigninCookieSuccess,
  ActionType as AuthActionType,
} from '@overflow/shared/auth/store/auth';

import {
  SigninRedirect,
  SigninCookie,
  SigninCookieFailure,
  ActionType,
} from './app-signin.action';

import { AuthService } from '../../service/auth.service';

import { DomainMember } from '@overflow/commons-typescript/model/domain';


@Injectable()
export class Effects {

  constructor(
    private actions$: Actions,
    private rpcService: RPCService,
    private cookieService: CookieService,
    private authService: AuthService,
    private router: Router
  ) { }

  @Effect({ dispatch: false })
  signinSuccess$ = this.actions$.pipe(
    ofType(AuthActionType.SigninSuccess),
    map((action: SigninSuccess) => action.payload),
    tap((info: {authToken: string, domainMember: DomainMember, returnURL: string}) => {
      const expires = new Date();
      expires.setDate(expires.getDate() + 1);
      this.cookieService.set('authToken', info.authToken, expires, '/');
      const queryString = `authToken=${info.authToken}`;
      this.rpcService.connect(queryString);

      this.router.navigateByUrl(info.returnURL ? info.returnURL : '/');
    })
  );

  @Effect()
  signinCookie$ = this.actions$.pipe(
    ofType(ActionType.SigninCookie),
    map((action: SigninCookie) => action.payload),
    exhaustMap((signinInfo: { authToken: string, returnURL: string }) =>
      this.authService
        .signin_cookie(signinInfo.authToken)
        .pipe(
          map((domainMember: DomainMember) => {
            return new SigninCookieSuccess({ domainMember: domainMember, returnURL: signinInfo.returnURL });
          }),
          catchError(error => of(new SigninCookieFailure(error)))
        )
    )
  );

  @Effect({ dispatch: false })
  signinCookieSuccess$ = this.actions$.pipe(
    ofType(AuthActionType.SigninCookieSuccess),
    map((action: SigninCookieSuccess) => action.payload),
    tap((info: {domainMember: DomainMember, returnURL: string}) => {
      const authToken = this.cookieService.get('authToken');
      const queryString = `authToken=${authToken}`;
      this.rpcService.connect(queryString);

      this.router.navigateByUrl(info.returnURL ? info.returnURL : '/');
    })
  );

  @Effect({ dispatch: false })
  signinRedirect$ = this.actions$.pipe(
    ofType(ActionType.SigninRedirect),
    map((action: SigninRedirect) => action.payload),
    tap((info: {returnURL: string}) => {
      this.router.navigate(['/auth/signin'], {queryParams: {returnURL: info.returnURL}});
    })
  );

}
