import { ChangeDetectorRef, Directive, Input, OnDestroy, TemplateRef, ViewContainerRef } from '@angular/core';
import { combineLatest, Subscription } from 'rxjs';
import { BixiACService } from './ac.service';

type StrOrStrArray = string | string[];

@Directive({
  selector: '[ac],[acAny],[ace],[aceAny]'
})
export class BixiACDirective implements OnDestroy {
  subscription = Subscription.EMPTY;

  constructor(
    private viewContainer: ViewContainerRef,
    // tslint:disable-next-line:no-any
    private templateRef: TemplateRef<any>,
    private acService: BixiACService,
    private changeDetector: ChangeDetectorRef
  ) {
    this.subscription = combineLatest([this.acService.permissions$, this.acService.roles$])
      .subscribe(() => {
        this.checkView();
      });
  }

  @Input()
  set isRole(isRole: boolean) {
    this._isRole = isRole;
    this.checkView();
  }

  @Input()
  set ac(value: StrOrStrArray) {
    this._ac = value;
    this.checkView();
  }

  @Input()
  set acAny(value: StrOrStrArray) {
    this._acAny = value;
    this.checkView();
  }

  @Input()
  set ace(value: StrOrStrArray) {
    this._ace = value;
    this.checkView();
  }

  @Input()
  set aceAny(value: StrOrStrArray) {
    this._aceAny = value;
    this.checkView();
  }

  private _isRole: boolean = false;
  private _ac: StrOrStrArray;
  private _acAny: StrOrStrArray;
  private _ace: StrOrStrArray;
  private _aceAny: StrOrStrArray;

  private checkView(): void {
    this.viewContainer.clear();
    if (this.hasPermissions()) {
      if (this.templateRef) {
        this.viewContainer.createEmbeddedView(this.templateRef);
        this.changeDetector.markForCheck();
      }
    }
  }

  private hasPermissions() {
    const isRole = this._isRole;
    if (this._ac) {
      return this.acService.ac(this._ac, { isRole });
    }
    if (this._acAny) {
      return this.acService.acAny(this._acAny, { isRole });
    }
    if (this._ace) {
      return this.acService.ace(this._ace, { isRole });
    }
    if (this._aceAny) {
      return this.acService.aceAny(this._aceAny, { isRole });
    }
    return false;
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}
