import { InobyModule } from "@lib/inoby-module";
import * as $ from "jquery";

enum dragState {
  none,
  dragStart,
  dragMove,
  dragEnd,
}

class WPBSCalendarDragModule extends InobyModule {
  private lastTouchedDate: Element = null;
  private $usedCalendar: JQuery<HTMLElement>;
  private $startDate: JQuery<HTMLElement>;
  private dragState = dragState.none;

  public run() {
    if (window.inoby_vars.wpbs_calendar_drag) {
      this.initDrag();
    }
  }

  /**
   * Initalize calendar dragging
   */
  private initDrag(): void {
    /**
     * pri kliku ktory som vyvolal ja potrebujem vediet v akom som kalendari
     * aby som si potom vedel z neho tahat elementy
     */
    $(document).on("click", ".wpbs-container .wpbs-is-bookable", (e) => {
      this.$usedCalendar = $(e.currentTarget).closest(".wpbs-main-wrapper");
    });

    /**
     * Stlacil som mys. Poznacim si ze mozno zacinam dragovat a na ktory datum som klikol
     */
    $(document).on(
      "mousedown touchstart",
      ".wpbs-container .wpbs-is-bookable",
      (e) => {
        this.dragState = dragState.dragStart;
        this.$startDate = this.getTouchedElement(e.originalEvent);
      }
    );

    /**
     * ak som stlacil mys a hybem nou, poznacim si ze dragujem a nasimulujem
     * klik na datume ktory mam poznaceny ako zaciatok
     */
    $(document).on("mousemove touchmove", (e) => {
      if (this.dragState === dragState.dragStart) {
        this.dragState = dragState.dragMove;
        this.$startDate.trigger("click");
      }
    });

    /**
     * na mouseup si pozriem ci dragujem. Ak ano tak si skontrolujem
     * zaciatok a koniec selekcie datumov a kliknem na ten spravny koniec
     */
    $(document).on("mouseup touchend", (e) => {
      const wasDrag = this.dragState === dragState.dragMove;
      this.dragState = dragState.dragEnd;
      if (wasDrag) {
        const lastClass = this.$startDate.hasClass("wpbs-selected-first")
          ? ".wpbs-selected-last"
          : ".wpbs-selected-first";
        var $target = this.$usedCalendar.find(lastClass);
        $target.trigger("click");
      }
    });

    /**
     * simulovanie mouse eventov aby sa vysvecovali datumy aj na dotykovych zariadeniach
     */
    $(document).on("touchmove", ".wpbs-container .wpbs-date", (e) => {
      const target = this.getTouchElement(e.originalEvent);
      e.preventDefault(); // vypne scrollovenie
      if (this.lastTouchedDate != target) {
        $(this.lastTouchedDate)?.trigger("mouseleave");
        $(target)?.trigger("mouseenter");
        this.lastTouchedDate = e.target;
      }
    });
  }

  private getTouchedElement(event: any, args: any = null) {
    var target: Element;
    if (event instanceof TouchEvent) {
      target = this.getTouchElement(event);
    } else {
      target = document.elementFromPoint(event.clientX, event.clientY);
    }
    return $(target).parents(".wpbs-date");
  }

  private getTouchElement(event: TouchEvent) {
    var changedTouch = event.changedTouches[0];
    return document.elementFromPoint(
      changedTouch.clientX,
      changedTouch.clientY
    );
  }
}

new WPBSCalendarDragModule().runOnReady();
