import {
  AfterViewInit,
  Directive,
  ElementRef,
  Input,
  OnChanges,
  OnDestroy,
  OnInit,
  Renderer2,
} from '@angular/core';
// eslint-disable-next-line import/no-cycle
import { GuideService } from './guide.service';
import { AppStorage } from 'src/app/shared/app-storage';

@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() guideCondition?: boolean = true;

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

  /**
   * ignore the stored info about this guide so it will be shown as new
   */
  @Input() 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 !AppStorage.getItem(GuideDirective.localStoragePrefix + this.guideText);
  }

  public markAsSeen() {
    this.isGuideSeen = true;
    AppStorage.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;
  }
}
