import { KeenSliderInstance, KeenSliderOptions } from "keen-slider";
import KeenSlider from "keen-slider";
import { dots, arrows } from "@lib/keen-slider-plugins";
import * as $ from "jquery";

export default class KeenSliderHelper {
  private static isSliderScrollable(instance: KeenSliderInstance) {
    return (
      (instance.options.slides as { perView: number }).perView <
      instance.slides.length
    );
  }

  static registerArrows(slider: KeenSliderInstance) {
    const id = $(slider.container).attr("id");
    let $arrows: JQuery<HTMLElement> | undefined;
    let initialized = false;

    if (id) {
      $arrows = $(`.keen-arrows[for=${id}]`);
    }
    if (!$arrows) {
      $arrows = $(slider.container).find(".keen-arrows");
    }

    function init() {
      if ($arrows) {
        $arrows.find(".keen-arrow.left").on("click", slider.prev);
        $arrows.find(".keen-arrow.right").on("click", slider.next);
        $arrows.show();
      }
      initialized = true;
    }

    function destroy() {
      if ($arrows) {
        $arrows.find(".keen-arrow.left").off("click", slider.prev);
        $arrows.find(".keen-arrow.right").off("click", slider.next);
        $arrows.hide();
      }
      initialized = false;
    }

    if (this.isSliderScrollable(slider)) {
      init();
    }

    slider.on("optionsChanged", (i) => {
      if (!initialized && this.isSliderScrollable(i)) {
        init();
      } else if (initialized && !this.isSliderScrollable(i)) {
        destroy();
      }
    });
  }

  static registerAutoScroll(slider: KeenSliderInstance) {
    let timeout: any = null;
    let paused = false;
    let initialized = false;

    function clearNextTimeout() {
      clearTimeout(timeout);
    }
    function nextTimeout() {
      clearTimeout(timeout);
      if (paused || !initialized) return;
      timeout = setTimeout(() => {
        slider.next();
      }, 2000);
    }

    function pause() {
      paused = true;
      clearNextTimeout();
    }

    function resume() {
      paused = false;
      nextTimeout();
    }

    function init() {
      nextTimeout();
      slider.container.addEventListener("mouseover", pause);
      slider.container.addEventListener("mouseout", resume);
      initialized = true;
    }

    function destroy() {
      clearNextTimeout();
      slider.container.removeEventListener("mouseover", pause);
      slider.container.removeEventListener("mouseout", resume);
      initialized = false;
    }

    if (this.isSliderScrollable(slider)) {
      init();
    }

    slider.on("dragStarted", clearNextTimeout);
    slider.on("animationEnded", nextTimeout);
    slider.on("updated", nextTimeout);
    slider.on("optionsChanged", (i) => {
      if (!initialized && this.isSliderScrollable(i)) {
        init();
      } else if (initialized && !this.isSliderScrollable(i)) {
        destroy();
      }
    });
  }

  static registerSlider(
    $sliders: JQuery<HTMLElement>,
    args: any,
    is_automatic: boolean = false
  ) {
    $sliders?.each((_i, el) => {
      var automatic = is_automatic || Number($(el).data("automatic"));
      var infinite = Number($(el).data("infinite"));

      var slides = args?.slides?.perView
        ? args?.slides?.perView
        : Number($(el).data("slides"));
      var slidesMd = Number($(el).data("slides-md"));
      var slidesSm = Number($(el).data("slides-sm"));

      var spacing = args?.slides?.spacing
        ? args?.slides?.spacing
        : Number($(el).data("spacing"));
      var spacingMd = Number($(el).data("spacing-md"));
      var spacingSm = Number($(el).data("spacing-sm"));

      var origin = $(el).data("origin");
      origin = origin ? origin : "auto";
      var originMd = $(el).data("origin-md");
      var originSm = $(el).data("origin-sm");

      var showArrows = Boolean($(el).data("arrows"));
      var showDots = Boolean($(el).data("dots"));

      const defaultArgs: KeenSliderOptions = {
        loop: infinite == 1 ? true : false,
        slides: {
          perView: slides ? slides : 4,
          spacing,
          origin,
        },
        breakpoints: {
          "(max-width: 575.9px)": {
            slides: {
              perView: slidesSm ? slidesSm : 1,
              spacing: spacingSm ? spacingSm : spacing,
              origin: originSm ? originSm : origin,
            },
          },
          "(min-width: 576px)": {
            slides: {
              perView: slidesMd ? slidesMd : 2,
              spacing: spacingMd ? spacingMd : spacing,
              origin: originMd ? originMd : origin,
            },
          },
          "(min-width: 768px)": {
            slides: {
              perView: slides,
              spacing,
              origin,
            },
          },
        },
        optionsChanged: (i) => {
          if (!this.isSliderScrollable(i)) {
            i.update(null, 0);
          }
        },
      };

      const plugins = [];
      if (showArrows) {
        plugins.push(arrows);
      }
      if (showDots) {
        plugins.push(dots);
      }

      const slider = new KeenSlider(el, { ...defaultArgs, ...args }, plugins);

      (el as any)._keenSlider = slider;

      if (automatic) {
        this.registerAutoScroll(slider);
      }
      this.registerArrows(slider);
    });
  }
}
