import { KeenSliderInstance, KeenSliderPlugin } from "keen-slider";

const createDiv = (className: string) => {
  var div = document.createElement("div");
  className.split(" ").forEach((name) => div.classList.add(name));
  return div;
};

const removeElement = (element: HTMLElement) => {
  element.parentNode.removeChild(element);
};

const dots: KeenSliderPlugin = (slider: KeenSliderInstance) => {
  let dots: HTMLDivElement = null;

  function markup(remove?: boolean) {
    if (remove) {
      removeElement(dots);
      return;
    }
    dots = createDiv("dots");
    slider.track.details.slides.forEach((_e, idx) => {
      var dot = createDiv("dot");
      dot.addEventListener("click", () => slider.moveToIdx(idx));
      dots.appendChild(dot);
    });
    slider.container.appendChild(dots);
  }

  function updateClasses() {
    const slide = slider.track.details.rel;
    Array.from(dots.children).forEach(function (dot, idx) {
      idx === slide ? dot.classList.add("active") : dot.classList.remove("active");
    });
  }

  slider.on("created", () => {
    markup();
    updateClasses();
    slider.container.classList.add("has-dots");
  });

  slider.on("optionsChanged", () => {
    markup(true);
    markup();
    updateClasses();
  });

  slider.on("slideChanged", () => {
    updateClasses();
  });

  slider.on("destroyed", () => {
    markup(true);
    slider.container.classList.remove("has-dots");
  });
};

const arrows: KeenSliderPlugin = (slider: KeenSliderInstance) => {
  let arrowLeft: HTMLDivElement = null,
    arrowRight: HTMLDivElement = null;

  function markup(remove?: boolean) {
    if (remove) {
      removeElement(arrowLeft);
      removeElement(arrowRight);
      return;
    }

    arrowLeft = createDiv("keen-arrow left");
    arrowRight = createDiv("keen-arrow right");

    arrowLeft.addEventListener("click", () => slider.prev());
    arrowRight.addEventListener("click", () => slider.next());

    slider.container.appendChild(arrowLeft);
    slider.container.appendChild(arrowRight);
  }

  slider.on("created", () => {
    markup();
    slider.container.classList.add("has-arrows");
  });
  slider.on("destroyed", () => {
    markup(true);
    slider.container.classList.remove("has-arrows");
  });
};

const adaptiveHeight: KeenSliderPlugin = (slider: KeenSliderInstance) => {
  function updateHeight() {
    const imgsCollection = slider.slides[slider.track.details.rel].getElementsByTagName("img");

    if (imgsCollection.length) {
      slider.container.style.height = imgsCollection[0].offsetHeight + "px";
    }
  }
  slider.on("created", () => {
    slider.container.classList.add("has-adaptive-height");
    setTimeout(() => {
      updateHeight();
    }, 100);
  });
  slider.on("slideChanged", updateHeight);
  slider.on("updated", updateHeight);
  slider.on("destroyed", () => slider.container.classList.remove("has-adaptive-height"));
  window.addEventListener("resize", updateHeight);
};

const thumbs = (thumbsSlider: KeenSliderInstance): KeenSliderPlugin => {
  return (mainSlider: KeenSliderInstance) => {
    const registerListeners = () => {
      thumbsSlider.slides.forEach((slide, idx) => {
        slide.addEventListener("click", () => {
          mainSlider.moveToIdx(idx);
        });
      });
    };

    mainSlider.on("created", () => {
      registerListeners();
      mainSlider.update({ ...mainSlider.options, breakpoints: {}, slides: { perView: 1 } });
      mainSlider.container.classList.add("has-thumbs");
    });

    mainSlider.on("destroyed", () => mainSlider.container.classList.remove("has-thumbs"));

    mainSlider.on("slideChanged", (instance) => {
      const mAbs = instance.track.details.abs;
      const tAbs = thumbsSlider.track.details.abs;
      if (mAbs >= tAbs + (thumbsSlider.options.slides as { perView: number }).perView && tAbs < thumbsSlider.track.details.maxIdx) {
        thumbsSlider.next();
      } else if (mAbs < tAbs && tAbs > thumbsSlider.track.details.minIdx) {
        thumbsSlider.prev();
      }
    });
  };
};

export { dots, arrows, adaptiveHeight, thumbs };
