import { Directive, ElementRef, Input, OnDestroy, TemplateRef, ViewContainerRef } from '@angular/core';
import { AccessControl, Permission, Query } from 'accesscontrol';
import { Subscription } from 'rxjs';
import { AuthService } from './auth.service';
import { ActionType, PossessionType, QueryType } from './interfaces';

@Directive({
  selector: '[can]'
})
export class CanDirective implements OnDestroy {
  query: QueryType;


  // @Input() canOwn: boolean;

  //readAny:art
  @Input('can') set authCan(authQuery: QueryType) {
    this.query = authQuery;
    this.update();
  }

  constructor(
    private sys: AuthService,
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
  ) {

  }

  private async isAuthed() {
    let ac = await this.sys.$ac;


    if (ac == null) {
      console.warn('[authCan]', `No ac`);
      return false;
    }
    if (!this.query) {
      console.warn('[authCan]', `No auth query`);
      return false;
    }

    let [action, possession, resource, owned] = this.query;
    //console.log('authQuery', action, resource, owned);
    //即便查询是 own, 但是用户用用any权限， 可以直接跳过下面的检查
    if(possession == 'own') {
      let isAnyAuthed = this.checkAuth(ac, action, 'any', resource);
      if (isAnyAuthed) return true;
    }

    let isAuthed = this.checkAuth(ac, action, possession, resource);
    if (possession == 'any') return isAuthed;
    if (action == 'create') return isAuthed;
    return isAuthed && owned;
  }

  private checkAuth(ac: AccessControl, action: ActionType, possession: PossessionType, resource: string): boolean {
    try {
      let role = 'user';
      let grant = ac.permission({ role, action, possession, resource })
      //console.log('granted:', grant.granted, this.query);
      return grant.granted;
    } catch (err) {
      console.warn('[authCan]', err);
      return false;
    }
  }


  private async update() {
    let isAuthed = await this.isAuthed();
    if (isAuthed) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
      this.viewContainer.clear();
    }
  }

  ngOnDestroy() {
  }

}
