import { Injectable } from '@angular/core';
import {
  Resolve,
  ActivatedRouteSnapshot,
  RouterStateSnapshot
} from '@angular/router';
import { Observable, throwError } from 'rxjs';
import { map, tap, mergeMap, catchError, take } from 'rxjs/operators';

import { Store } from '@ngrx/store';

import { ProtocolService } from '@ucap-webmessenger/protocol';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { PublicApiService } from '@ucap-webmessenger/api-public';

import * as AppStore from '../store';
import * as VersionInfoStore from '../store/setting/version-info';
import { LoginInfo, KEY_LOGIN_INFO } from '../types';
import { InnerProtocolService } from '@ucap-webmessenger/protocol-inner';
import {
  AuthenticationProtocolService,
  SSOMode,
  LoginResponse
} from '@ucap-webmessenger/protocol-authentication';

import * as AuthenticationStore from '@app/store/account/authentication';

@Injectable()
export class AppMessengerResolver implements Resolve<void> {
  constructor(
    private store: Store<any>,
    private sessionStorageService: SessionStorageService,
    private publicApiService: PublicApiService,
    private protocolService: ProtocolService,
    private authenticationProtocolService: AuthenticationProtocolService,
    private innerProtocolService: InnerProtocolService
  ) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): void | Observable<void> | Promise<void> {
    const loginInfo = this.sessionStorageService.get<LoginInfo>(KEY_LOGIN_INFO);

    return new Promise<void>((resolve, reject) => {
      this.publicApiService
        .versionInfo2({
          deviceType: loginInfo.deviceType,
          companyGroupType: 'C',
          companyCode: loginInfo.companyCode,
          loginId: loginInfo.loginId
        })
        .pipe(
          take(1),
          tap(versionInfo2Res => {
            this.store.dispatch(VersionInfoStore.fetchSuccess(versionInfo2Res));
          }),
          mergeMap(versionInfo2Res =>
            this.protocolService.connect(versionInfo2Res.serverIp)
          ),
          mergeMap(() => this.innerProtocolService.conn({})),
          mergeMap(connRres =>
            this.authenticationProtocolService.login({
              loginId: loginInfo.loginId,
              loginPw: loginInfo.loginPw,
              deviceType: loginInfo.deviceType,
              deviceId: ' ',
              token: '',
              localeCode: loginInfo.localeCode,
              pushId: ' ',
              companyCode: loginInfo.companyCode,
              passwordEncodingType: 1,
              clientVersion: '',
              reconnect: false,
              ip: 'localhost',
              hostName: '',
              ssoMode: SSOMode.AUTH,
              userSpecificInformation: 'PRO_000482',
              productId: 'PRO_000482',
              productName: 'EZMessenger'
            })
          ),
          map(loginRes => {
            this.store.dispatch(
              AuthenticationStore.loginSuccess({
                loginInfo: loginRes
              })
            );
          }),
          catchError(err => {
            return throwError(err);
          })
        )
        .subscribe(
          () => {
            resolve();
          },
          err => {
            reject();
          }
        );
    });
  }
}
