<template>
  <div class="carousel-container" :style="containerStyle">
    <div
      class="content"
      ref="content"
      :class="direction"
      :style="{ left: leftRem, top: topRem }"
      @mouseover="mouseoverHandler"
      @mouseleave="mouseleaveHandler"
    >
      <slot></slot>
      <slot></slot>
    </div>
  </div>
</template>

<script lang="ts">
  import { defineComponent, ref, computed, onMounted, PropType } from "vue";

  enum DirectionEnum {
    vertical = "vertical",
    horizontal = "horizontal",
  }

  export default defineComponent({
    props: {
      /**
       * 轮播方向
       */
      direction: {
        type: String as PropType<DirectionEnum>,
        default: DirectionEnum.vertical,
      },
      /**
       * 轮播时间
       */
      speed: {
        type: Number,
        default: 10,
      },
      /**
       * 轮播是否受控
       */
      animationControls: {
        type: Boolean,
        default: true,
      },
    },
    setup(props) {
      const left = ref(0);
      const top = ref(0);
      const leftRem = computed(() => left.value * 0.01 + "rem");
      const topRem = computed(() => top.value * 0.01 + "rem");

      const content = ref<HTMLElement>();
      const timer = ref<number | null>(null);
      const containerStyle = ref<{ width: number | string; height: number | string }>({
        width: 0,
        height: 0,
      });
      /**
       * 轮播开始
       */
      const animationStart = () => {
        const baseSize = document.documentElement.clientWidth / 1920;
        const carousel = () => {
          const carouselDom = content.value;
          if (props.direction === DirectionEnum.vertical) {
            if (carouselDom) {
              const swiperHeight = carouselDom.offsetHeight;
              containerStyle.value = {
                width: "100%",
                height: (swiperHeight / 2) * 0.01 + "rem",
              };
              const swiperHeightRem = swiperHeight / baseSize;
              const step = swiperHeightRem / 2 / 60 / props.speed;
              top.value -= step;
              if (top.value < -swiperHeightRem / 2) {
                top.value = 0;
              }
              timer.value = requestAnimationFrame(carousel);
            }
          } else if (props.direction === DirectionEnum.horizontal) {
            if (carouselDom) {
              const swiperWidth = carouselDom.offsetWidth;
              containerStyle.value = {
                width: (swiperWidth / 2) * 0.01 + "rem",
                height: "100%",
              };
              const swiperWidthRem = swiperWidth / baseSize;
              const step = swiperWidthRem / 2 / 60 / props.speed;
              left.value -= step;
              if (left.value < -swiperWidthRem / 2) {
                left.value = 0;
              }
              timer.value = requestAnimationFrame(carousel);
            }
          } else {
            console.error(`请传入正确的direction参数。`);
          }
        };
        carousel();
      };
      onMounted(() => {
        animationStart();
      });

      /**
       * 轮播暂停
       */
      const animationPause = () => {
        timer.value && cancelAnimationFrame(timer.value);
      };

      /**
       * 鼠标hover
       */
      const mouseoverHandler = () => {
        if (props.animationControls) {
          animationPause();
        }
      };

      /**
       * 鼠标离开
       */
      const mouseleaveHandler = () => {
        if (props.animationControls) {
          animationStart();
        }
      };

      return { content, leftRem, topRem, animationPause, mouseoverHandler, mouseleaveHandler, containerStyle };
    },
  });
</script>

<style lang="less" scoped>
  .carousel-container {
    overflow: hidden;
    position: relative;

    .content {
      position: absolute;
      left: 0;
      top: 0;
      display: flex;

      &.horizontal {
        flex-direction: row;
        height: 100%;
      }

      &.vertical {
        width: 100%;
        flex-direction: column;
      }
    }
  }
</style>
