import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import {
  ActivatedRouteSnapshot,
  CanActivate,
  Router,
  RouterStateSnapshot,
  UrlTree,
} from '@angular/router';
import { marker } from '@biesbjerg/ngx-translate-extract-marker';
import { Observable } from 'rxjs';
import { DialogService } from 'src/app/shared/services/dialog.service';
import { ContactDialogComponent } from '../dialogs/contact-dialog/contact-dialog.component';
import { AccountService } from '../server-services/account.service';
import { AuthService } from '../server-services/auth.service';
import { SubscriptionService } from '../server-services/subscription.service';
import { RouterHandler } from '../services/router-handler.service';
import { ServerRestApiService } from '../services/server-rest-api.service';
import { SnackBarService } from '../services/snackbar.service';

@Injectable({
  providedIn: 'root',
})
export class MainPageGuard implements CanActivate {
  private emailChangeCallback = null;
  private accountLoadedCallback = null;

  constructor(
    private accountService: AccountService,
    private router: Router,
    private routerHandler: RouterHandler,
    private dialogService: DialogService,
    private restApiService: ServerRestApiService,
    private dialog: MatDialog,
    private authService: AuthService,
    private subscriptionService: SubscriptionService,
    private snackbarService: SnackBarService
  ) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
    let fragment = {};

    let routerResponse = this.routerHandler.processUrl(
      state.url // do not use document.location, you can not get the right info from cordova webview
    );

    if (routerResponse) {
      fragment = routerResponse.routerResponse.fragment;
    }

    if (fragment['register-confirm']) {
      let parse = this.router.parseUrl(
        '/register-confirm#register-confirm!' + fragment['register-confirm']
      );
      return parse;
    } else if (fragment['recover-account']) {
      return this.router.parseUrl(
        '/account-recovery-confirm#recover-account!' + fragment['recover-account']
      );
    } else if (fragment['email-change']) {
      var newEmailToken = fragment['email-change'];

      var editEmailPromise: Promise<boolean | UrlTree> = new Promise((resolve) => {
        this.emailChangeCallback = () => {
          this.authService.unsubscribeSelfAccountKeyringLoaded(this.emailChangeCallback);
          this.accountService
            .editEmail(newEmailToken)
            .then((res) => {
              this.dialogService.openAlertDialog(
                marker('Email change'),
                marker('Email changed successfully! Please log in with your new email.')
              );

              let loginNavigation = () => {
                this.restApiService.unsubscribeOnWSAuthClosed(loginNavigation);
                resolve(this.router.parseUrl('/login'));
              };

              this.restApiService.subscribeOnWSAuthClosed(loginNavigation);
            })
            .catch((err) => {
              console.error('editEmail', err);
              this.dialogService.openAlertDialog(
                marker('Error'),
                marker('Error occured during the process'),
                err?.message
              );
              resolve(false);
            });
        };
        this.authService.onSelfAccountKeyringLoaded(this.emailChangeCallback);
      });

      return editEmailPromise;
    } else if (fragment['contact']) {
      let eventFinishedPromise: Promise<boolean | UrlTree> = new Promise((resolve) => {
        let event = () => {
          this.subscriptionService.unsubscribeWorkspaceLoaded(event);

          console.log('MainPageGuard', 'isAnonym', this.authService.isAnonym());
          if (this.authService.isAnonym()) return resolve(this.router.parseUrl('/login'));

          this.accountService
            .getAccount(fragment['contact'])
            .then((user) => {
              let ref = this.dialog.open(ContactDialogComponent, {
                data: user,
              });
              resolve(true);
            })
            .catch((err) => {
              this.snackbarService.showSnackbar(marker('Could not found the user'));
              console.error('contact error', err);
              resolve(false);
            });
        };

        this.subscriptionService.subscribeWorkspaceLoaded(event);
      });

      return eventFinishedPromise;
    }

    var accountLoadedPromise: Promise<boolean | UrlTree> = new Promise((resolve) => {
      this.accountLoadedCallback = () => {
        this.authService.unsubscribeSelfAccountKeyringLoaded(this.accountLoadedCallback);

        if (this.authService.isAnonym() || this.authService.isAnonym() === null) {
          resolve(this.router.parseUrl('/login'));
        } else resolve(true);
      };

      this.authService.onSelfAccountKeyringLoaded(this.accountLoadedCallback);
    });

    return accountLoadedPromise;
  }
}
