import { Directive, Input, ElementRef, Renderer2, ViewChild, ContentChild, OnDestroy, OnInit, AfterViewInit } from '@angular/core';
import { TutorialService, Tutorial } from 'app/services/tutorial.service';
import { TutorialStepTooltipComponent } from 'app/tutorial/tutorial-step-tooltip/tutorial-step-tooltip.component';
import _ from 'lodash';
import { TUTORIAL_STEP_POSITION } from 'app/tutorial/enums/tutorial-step-position.enum';
import { TUTORIAL_STEP_STATUS } from 'app/tutorial/enums/tutorial-step-status.enum';

@Directive({
  selector: '[appTutorialStep]'
})
export class TutorialStepDirective implements OnDestroy, OnInit, AfterViewInit {

  /**
   * Indicates the Tutorial Name
   */
  @Input()
  tutorialName: string;

  /**
   * Sets the order of this step in the tutorial
   */
  @Input()
  tutorialStepOrder: number;

  /**
   * Indicates the position of the tooltip for the step
   */
  @Input()
  tutorialPosition: TUTORIAL_STEP_POSITION = TUTORIAL_STEP_POSITION.BOTTOM;

  private _status: TUTORIAL_STEP_STATUS = TUTORIAL_STEP_STATUS.NONE;

  @ContentChild(TutorialStepTooltipComponent) tooltip: TutorialStepTooltipComponent;

  get status() {
    return this._status;
  }

  /**
   * when setting the status update the host classes
   * to reflect the new status
   */
  set status(status: TUTORIAL_STEP_STATUS) {
    // update the host status
    this.updateHostStatus(this.status, status);
    this._status = status;
  }

  constructor(
    private tutorialService: TutorialService,
    private renderer: Renderer2,
    private hostElement: ElementRef
  ) { }

  ngOnInit() {

    // register the step on the tutorial
    this.tutorialService.registerTutorailStep(this.tutorialName);

    // hook to events on the tutorial
    this.tutorialService.onTutorialEnd.subscribe(tutorial => {
      if (tutorial.name == this.tutorialName) {
        this.onTutorialEnd();
      }
    });

    this.tutorialService.onTutorialStart.subscribe(tutorial => {
      if (tutorial.name == this.tutorialName) {
        this.onTutorialStart(tutorial);
      }
    });

    this.tutorialService.onTutorialNextStep.subscribe(tutorial => {
      if (tutorial.name == this.tutorialName) {
        this.onStepUpdate(tutorial);
      }
    });

    this.tutorialService.onTutorialPreviousStep.subscribe(tutorial => {
      if (tutorial.name == this.tutorialName) {
        this.onStepUpdate(tutorial);
      }
    });
  }

  /**
   * unregister the step from the service
   */
  ngOnDestroy() {
    this.tutorialService.unregisterTutorailStep(this.tutorialName);
  }

  /**
   * subscribe to the tooltip events to know to be able to comunicate with the service
   */
  ngAfterViewInit() {
    this.tooltip.onClose.subscribe(() => { this.end() });
    this.tooltip.onNext.subscribe(() => { this.next() });
    this.tooltip.onPrevious.subscribe(() => { this.previous() });
  }

  next() {
    this.tutorialService.nextStep(this.tutorialName);
  }

  previous() {
    this.tutorialService.previousStep(this.tutorialName);
  }

  end() {
    this.tutorialService.endTutorial(this.tutorialName);
  }

  /**
   * Sets the status of the step as inactive and pass the  basic
   * config to the tooltip object
   */
  private onTutorialStart(tutorial: Tutorial) {
    this.status = TUTORIAL_STEP_STATUS.INACTIVE;

    this.tooltip.currentEntry = this.tutorialStepOrder + 1;
    this.tooltip.totalEntrys = tutorial.steps;
    this.tooltip.position = this.tutorialPosition;
  }

  /**
   * Sets the status of the step to none meaning that the tutorial
   * its not running at all
   */
  private onTutorialEnd() {
    this.status = TUTORIAL_STEP_STATUS.NONE;
    this.tooltip.show = false;
  }

  /**
   * hides or shows an step
   * @param tutorial a Tutorial object that states the current position
   * of the tutorial
   */
  private onStepUpdate(tutorial: Tutorial) {
    if (tutorial.currentPosition === this.tutorialStepOrder) {
      this.status = TUTORIAL_STEP_STATUS.ACTIVE;
      // make sure that it wont be overwrriten by the host bind in the class
      // of the tooltip component
      _.defer(() => { this.tooltip.show = true; });
    } else {
      this.status = TUTORIAL_STEP_STATUS.INACTIVE;
      // make sure that it wont be overwrriten by the host bind in the class
      // of the tooltip component
      _.defer(() => { this.tooltip.show = false; });
    }
  }

  /**
   * Toggles between diferent tutorial step statuses
   * @param oldClass old class to be removed
   * @param newClass new class to be added
   */
  private updateHostStatus(oldStatus: TUTORIAL_STEP_STATUS, newStatus: TUTORIAL_STEP_STATUS) {
    if (oldStatus !== TUTORIAL_STEP_STATUS.NONE) {
      this.renderer.removeClass(this.hostElement.nativeElement, oldStatus);
    }

    if (newStatus !== TUTORIAL_STEP_STATUS.NONE) {
      this.renderer.addClass(this.hostElement.nativeElement, newStatus);
    }
  }

}
