import {
  ActivatedRouteSnapshot,
  CanActivate,
  Router,
  RouterStateSnapshot,
  UrlTree
} from "@angular/router";
import {Injectable} from "@angular/core";
import {AuthorizationService} from "../service/authorization.service";
import {TokenProvider} from "../provider/token.provider";
import {HttpClient} from "@angular/common/http";
import {ErvuPermission} from "../enum/ErvuPermission";

@Injectable({providedIn: 'root'})
export class RolesGuard implements CanActivate{

  private allowedPermissions: string[];

  constructor(protected authService: AuthorizationService,
              protected tokenProvider: TokenProvider,
              protected router: Router, private httpClient: HttpClient) {
  }

  async canActivate(
      route: ActivatedRouteSnapshot, state: RouterStateSnapshot
  ): Promise<boolean | UrlTree> {
    if (!await this.tokenProvider.getToken()) {
      return this.getUrlOnFailure()
    }
    this.allowedPermissions = route.data && route.data.permissions ? route.data.permissions : [];
    let checkOrg = route.data && route.data.checkOrg;

    if (!this.authService.isAuthorized()) {
      return this.authService.getCurrentSession()
          .then(() => {
            if (checkOrg) {
              return this.checkOrgByAppId(route.params.id);
            }
            return this.checkPermissions() ? true : this.getUrlOnFailure();
          })
          .catch(() => this.getUrlOnFailure());
    }
    else {
      return checkOrg ? this.checkOrgByAppId(route.params.id) : this.checkPermissions();
    }
  }

  protected getUrlOnFailure(): UrlTree {
    return null;
  }

  protected checkPermissions(): boolean {
    return this.allowedPermissions.length === 0
           || this.authService.hasAnyPermission(this.allowedPermissions);
  }

  private checkOrgByAppId(id: string): Promise<boolean | UrlTree> {
    if (this.authService.hasAnyPermission([ErvuPermission.CREATOR, ErvuPermission.REVIEWER])) {
      return this.httpClient.get("allowed", {
        headers: {
          'app-number': id,
          'check-parents': (!this.authService.hasPermission(ErvuPermission.CREATOR)).toString()
        },
        observe: 'response'
      })
          .toPromise()
          .then(response => {
            return response.body ? true : this.getUrlOnFailure();
          })
          .catch(() => this.getUrlOnFailure());
    }
    else if (this.authService.hasPermission(ErvuPermission.APPROVER)) {
      return Promise.resolve(true);
    }

    return Promise.resolve(this.getUrlOnFailure());
  }
}
