import { defineComponent, ref, computed, watch, onMounted, onUnmounted, provide, createElementBlock, openBlock, normalizeStyle, normalizeClass, createElementVNode, createCommentVNode, renderSlot, Fragment, renderList, createVNode, unref } from "vue";
import { IconChevronLeft, IconChevronRight } from "../_utils/icons.mjs";
import Gallery from "./effects/gallery.mjs";
import Toggle from "./effects/toggle.mjs";
import { carouselInjectKey } from "./provide.mjs";
import { carouselProps } from "./types.mjs";
const _hoisted_1 = { class: "o-carousel-wrap" };
const _hoisted_2 = ["onClick"];
const _hoisted_3 = { class: "o-carousel-arrow-prev" };
const _hoisted_4 = { class: "o-carousel-arrow-icon" };
const _hoisted_5 = { class: "o-carousel-arrow-next" };
const _hoisted_6 = { class: "o-carousel-arrow-icon" };
const _sfc_main = /* @__PURE__ */ defineComponent({
  __name: "OCarousel",
  props: carouselProps,
  emits: ["before-change", "change", "update:activeIndex", "pause"],
  setup(__props, { expose: __expose, emit: __emit }) {
    const props = __props;
    const emits = __emit;
    const containerRef = ref(null);
    const total = computed(() => {
      var _a;
      return (_a = containerRef.value) == null ? void 0 : _a.children.length;
    });
    const isAutoPlay = ref(props.autoPlay);
    watch(
      () => props.autoPlay,
      (a) => {
        isAutoPlay.value = a;
      }
    );
    const fixIndex = (idx) => {
      if (!total.value) {
        return idx;
      }
      const i = idx % total.value;
      return i >= 0 ? i : i + total.value;
    };
    const activeIndex = ref(props.activeIndex ? fixIndex(props.activeIndex) : 0);
    watch(
      () => props.activeIndex,
      (v) => {
        activeIndex.value = v ?? 0;
      }
    );
    const initialized = ref(false);
    const slidesRef = ref(null);
    const slideElList = computed(() => {
      var _a;
      const c = (_a = containerRef.value) == null ? void 0 : _a.children;
      return c ? Array.from(c).map((el) => el) : null;
    });
    let slidesInstance = null;
    let isChanging = false;
    const activeSlideByIndex = (index) => {
      return new Promise((resolve) => {
        const to = fixIndex(index);
        const from = activeIndex.value;
        if (isChanging || !slideElList.value) {
          resolve(false);
          return;
        }
        if (to === from) {
          resolve(true);
          return;
        }
        isChanging = true;
        if (slidesInstance) {
          activeIndex.value = to;
          emits("update:activeIndex", to);
          slidesInstance.active(to).then(() => {
            isChanging = false;
            resolve(true);
          });
        } else {
          isChanging = false;
          resolve(false);
        }
      });
    };
    let timer = null;
    const isPlaying = ref(isAutoPlay.value);
    const pausePlay = () => {
      if (timer) {
        clearInterval(timer);
        timer = null;
        isPlaying.value = false;
        emits("pause", activeIndex.value);
      }
    };
    const resumePlay = () => {
      if (isAutoPlay.value) {
        setTimeout(() => {
          startPlay();
        }, 0);
      }
    };
    const startPlay = () => {
      pausePlay();
      isPlaying.value = true;
      timer = window.setInterval(() => {
        activeSlideByIndex(activeIndex.value + 1);
      }, props.interval);
    };
    const activeSlide = (index, resumeAutoPlay = true) => {
      pausePlay();
      return activeSlideByIndex(index).then((success) => {
        if (!success) {
          return;
        }
        if (!props.pauseOnHover || resumeAutoPlay) {
          resumePlay();
        }
      });
    };
    const initSlides = () => {
      if (!slideElList.value || !containerRef.value || initialized.value) {
        return;
      }
      const options = {
        activeClass: props.activeClass,
        onTouchstart: () => {
          pausePlay();
        },
        onTouchend: () => {
          resumePlay();
        },
        onBeforeChange: (to, from) => {
          emits("before-change", to, from);
        },
        onChanged: (to, from) => {
          activeIndex.value = to;
          emits("update:activeIndex", to);
          emits("change", to, from);
        }
      };
      let EffectType = null;
      switch (props.effect) {
        case "gallery": {
          EffectType = Gallery;
          break;
        }
        case "toggle": {
          EffectType = Toggle;
          break;
        }
        default: {
          EffectType = Gallery;
          break;
        }
      }
      if (EffectType) {
        slidesInstance = new EffectType(slideElList.value, containerRef.value, activeIndex.value, options);
      }
      if (props.clickToSwitch) {
        slideElList.value.forEach((el, idx) => {
          el.addEventListener("click", () => {
            if (idx !== activeIndex.value) {
              activeSlide(idx);
            }
          });
        });
      }
      initialized.value = true;
    };
    watch(
      () => props.autoPlay,
      (v) => {
        if (v) {
          startPlay();
        } else {
          pausePlay();
        }
      }
    );
    const init = () => {
      initSlides();
      if (isAutoPlay.value) {
        startPlay();
      }
    };
    onMounted(() => {
      if (!props.manualInit) {
        init();
      }
    });
    onUnmounted(() => {
      if (timer) {
        clearInterval(timer);
        timer = null;
      }
      slidesInstance == null ? void 0 : slidesInstance.destroyed();
    });
    provide(carouselInjectKey, {
      effect: props.effect
    });
    const play = () => {
      isAutoPlay.value = true;
      startPlay();
    };
    const pause = () => {
      isAutoPlay.value = false;
      pausePlay();
    };
    const onHoverIn = () => {
      if (props.pauseOnHover) {
        pausePlay();
      }
    };
    const onHoverOut = () => {
      if (props.pauseOnHover) {
        resumePlay();
      }
    };
    __expose({
      init,
      play,
      pause,
      active: activeSlide
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(
        "div",
        {
          ref_key: "slidesRef",
          ref: slidesRef,
          class: normalizeClass(["o-carousel", [
            {
              "o-carousel-visible": initialized.value,
              "o-carousel-click-to-switch": props.clickToSwitch,
              "o-carousel-hover-arrow": props.arrow === "hover",
              "o-carousel-autoplay": isAutoPlay.value,
              "is-playing": isPlaying.value
            },
            `o-carousel-effect-${props.effect}`
          ]]),
          style: normalizeStyle({
            "--carousel-interval": props.interval + "ms"
          }),
          onMouseenter: onHoverIn,
          onMouseleave: onHoverOut
        },
        [
          createElementVNode("div", _hoisted_1, [
            createElementVNode(
              "div",
              {
                ref_key: "containerRef",
                ref: containerRef,
                class: normalizeClass([`o-carousel-container-${props.effect}`])
              },
              [
                renderSlot(_ctx.$slots, "default")
              ],
              2
              /* CLASS */
            )
          ]),
          !props.hideIndicator ? (openBlock(), createElementBlock(
            "div",
            {
              key: 0,
              class: normalizeClass(["o-carousel-indicator-wrap", props.indicatorWrapClass])
            },
            [
              (openBlock(true), createElementBlock(
                Fragment,
                null,
                renderList(total.value, (item, idx) => {
                  return openBlock(), createElementBlock("div", {
                    key: item,
                    class: "o-carousel-indicator-item",
                    onClick: ($event) => props.indicatorClick && activeSlide(idx)
                  }, [
                    renderSlot(_ctx.$slots, "indicator", {
                      active: item - 1 === activeIndex.value,
                      index: idx
                    }, () => [
                      createElementVNode(
                        "div",
                        {
                          class: normalizeClass(["o-carousel-indicator-bar", {
                            "o-carousel-indicator-bar-selected": item - 1 === activeIndex.value
                          }])
                        },
                        _cache[2] || (_cache[2] = [
                          createElementVNode(
                            "div",
                            { class: "o-carousel-indicator-line" },
                            null,
                            -1
                            /* HOISTED */
                          )
                        ]),
                        2
                        /* CLASS */
                      )
                    ])
                  ], 8, _hoisted_2);
                }),
                128
                /* KEYED_FRAGMENT */
              ))
            ],
            2
            /* CLASS */
          )) : createCommentVNode("v-if", true),
          props.arrow !== "never" ? (openBlock(), createElementBlock(
            "div",
            {
              key: 1,
              class: normalizeClass(["o-carousel-arrow-wrap", props.arrowWrapClass])
            },
            [
              createElementVNode("div", {
                onClick: _cache[0] || (_cache[0] = ($event) => activeSlide(activeIndex.value - 1, false))
              }, [
                renderSlot(_ctx.$slots, "arrow-prev", {}, () => [
                  createElementVNode("div", _hoisted_3, [
                    createElementVNode("div", _hoisted_4, [
                      renderSlot(_ctx.$slots, "arrow-prev-icon", {}, () => [
                        createVNode(unref(IconChevronLeft))
                      ])
                    ])
                  ])
                ])
              ]),
              createElementVNode("div", {
                onClick: _cache[1] || (_cache[1] = ($event) => activeSlide(activeIndex.value + 1, false))
              }, [
                renderSlot(_ctx.$slots, "arrow-next", {}, () => [
                  createElementVNode("div", _hoisted_5, [
                    createElementVNode("div", _hoisted_6, [
                      renderSlot(_ctx.$slots, "arrow-next-icon", {}, () => [
                        createVNode(unref(IconChevronRight))
                      ])
                    ])
                  ])
                ])
              ])
            ],
            2
            /* CLASS */
          )) : createCommentVNode("v-if", true)
        ],
        38
        /* CLASS, STYLE, NEED_HYDRATION */
      );
    };
  }
});
export {
  _sfc_main as default
};
