import {
  AfterViewInit,
  Directive,
  ElementRef,
  Input,
  OnChanges,
  OnDestroy,
  OnInit,
  Renderer2,
} from "@angular/core";
import { GuideService } from "./guide.service";

@Directive({
  selector: "[appGuide]",
})
export class GuideDirective
  implements OnInit, OnDestroy, OnChanges, AfterViewInit
{
  /**
   * text of the guide
   */
  @Input("appGuide") guideText: string;

  /**
   * If the condition is true, the guide will start immediately
   */
  @Input("guideIf") guideCondition?: boolean = true;

  /**
   * define an dequence
   */
  @Input("guideStep") guideStep?: number = 0;

  /**
   * ignore the stored info about this guide so it will be shown as new
   */
  @Input("guideReset") guideReset?: boolean = false;

  private alreadyRegistered: boolean = false;
  private isGuideSeen: boolean = false;

  private initDone: boolean = false;

  public static localStoragePrefix: string = "guide-";

  constructor(
    private renderer: Renderer2,
    private el: ElementRef,
    private guideService: GuideService
  ) {}

  ngOnInit() {
    this.isGuideSeen = !this.isGuideNew() && !this.guideReset;
    if (!this.isGuideSeen) {
      if (this.guideCondition) {
        this.guideService.subscribeDirective(this);
        this.alreadyRegistered = true;
      }
    }
    this.initDone = true;
  }

  ngAfterViewInit() {
    if (this.alreadyRegistered) {
      this.guideService.startGuide();
    }
  }

  ngOnDestroy() {
    this.guideService.unsubscribe(this);
  }

  // on changes come before onInit, because we have Inputs
  ngOnChanges() {
    if (
      this.initDone &&
      !this.isGuideSeen &&
      !this.alreadyRegistered &&
      this.guideCondition
    ) {
      this.guideService.subscribeDirective(this);
      this.alreadyRegistered = true;
      this.guideService.startGuide();
    }
  }

  private isGuideNew(): boolean {
    return (
      !localStorage.getItem(GuideDirective.localStoragePrefix + this.guideText)
    );
  }

  public markAsSeen() {
    this.isGuideSeen = true;
    localStorage.setItem(
      GuideDirective.localStoragePrefix + this.guideText,
      "1"
    );
  }

  private activateResolver;
  public activate(): Promise<void> {
    return new Promise((resolve, reject) => {
      this.activateResolver = resolve;
      this.el.nativeElement.addEventListener("click", this.onClick);
    });
  }

  public onClick = () => {
    if (this.activateResolver) {
      this.markAsSeen();
      this.el.nativeElement.removeEventListener(
        "click",
        this.onClick
      );
      this.activateResolver();
      this.activateResolver = null;
    }
  };

  public getStep(): number {
    return this.guideStep;
  }

  public getElementNode() {
    return this.el.nativeElement;
  }

  public getGuideText(){
    return this.guideText;
  }
}
