/*
 * Copyright (C) 2017 Robert Bosch GmbH Copyright (C) 2017 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */

import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import {
  AccessControlAuthenticationService,
  AuthenticationService,
  MacmaAuthenticationService,
} from '@bci-web-core/auth';
import { from, Observable, of, Subject, throwError } from 'rxjs';
import { catchError, mergeMap, takeUntil, tap } from 'rxjs/operators';

@Component({
  selector: 'bci-app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss'],
})
export class Login2Component implements OnInit, OnDestroy {
  model: { username?: string; password?: string; tenant?: string } = {};
  loading = false;
  errorMsg = '';
  useTenant = false;

  destroy$: Subject<boolean> = new Subject<boolean>();

  constructor(
    private _router: Router,
    private _authenticationService: AuthenticationService,
    private _activatedRoute: ActivatedRoute
  ) {}

  ngOnInit() {
    if (this._authenticationService instanceof MacmaAuthenticationService) {
      (<MacmaAuthenticationService>this._authenticationService).login();
    }

    this._authenticationService
      .isAuthenticated()
      .pipe(
        mergeMap((authenticated) => {
          if (authenticated === true) {
            return this.redirectToAttemptedRoute();
          }
          return this.getSsoParameterAndTrySso();
        }),
        takeUntil(this.destroy$)
      )
      .subscribe();

    this.model.username = '';
    this.model.password = '';
  }

  login() {
    // Needed for manual login with Internet Explorer
    document.execCommand('ClearAuthenticationCache', false);
    this.loading = true;
    (<AccessControlAuthenticationService>this._authenticationService)
      .login(this.model.username, this.model.password, this.useTenant ? this.model.tenant : null)
      .pipe(
        tap((t) => console.log(t)),
        takeUntil(this.destroy$)
      )
      .subscribe(
        () => {
          this.errorMsg = '';
          console.log('Logged in with user credentials');
          this.loading = false;
          this.redirectToAttemptedRoute();
        },
        (error) => {
          console.error(`Couldn't log in with user credentials: ${JSON.stringify(error)}`);
          this.errorMsg =
            'Login failed with the provided credentials. Please ensure customer, username and password are correct.';
          // this.notificationService.error(error);
          this.loading = false;
        }
      );
  }

  public ngOnDestroy(): void {
    this.destroy$.next(true);
    this.destroy$.unsubscribe();
  }

  private getSsoParameterAndTrySso(): Observable<boolean> {
    return this._activatedRoute.queryParamMap.pipe(
      mergeMap((params) => {
        const sso = params.get('sso');
        if (!sso || sso !== 'false') {
          return this.trySso();
        } else {
          return of(false);
        }
      })
    );
  }

  private trySso(): Observable<boolean> {
    return this._authenticationService.isAuthenticated().pipe(
      mergeMap((authenticated) => {
        if (!authenticated) {
          return (<AccessControlAuthenticationService>this._authenticationService)
            .login(undefined, undefined, undefined, true)
            .pipe(
              mergeMap(() => {
                console.log('Logged in with WinAuth');
                return this.redirectToAttemptedRoute();
              }),
              catchError((error) => {
                console.error("Couldn't log in with WinAuth.", error);
                return throwError("Couldn't log in with WinAuth.");
              })
            );
        }
        return throwError('Already authenticated');
      })
    );
  }

  private redirectToAttemptedRoute(): Observable<boolean> {
    // Get the redirect URL from our auth service
    // If no redirect has been set, use the default
    let redirect = this._authenticationService.redirectUrl ? this._authenticationService.redirectUrl : '/';

    if (redirect.indexOf('?') >= 0) {
      redirect = redirect.substr(0, redirect.indexOf('?'));
    }

    // Redirect the user
    console.log('Redirecting to ' + redirect);
    return from(this._router.navigate([redirect], { queryParamsHandling: 'preserve' }));
  }
}
