/**
* part of the code from vant https://github.com/youzan/vant/
* @Author momoko
*/

<template>
  <div :class="[c(),cusClass]" ref="swipeContent">
    <div
      :class="c('track')"
      :style="trackStyle"
      @touchstart="touchStart"
      @touchmove="touchMove"
      @touchend="touchEnd"
      @touchcancel="touchEnd"
      @transitionend="transitionend"
    >
      <slot/>
    </div>
    <div v-if="showIndicators && count > 1" :class="[c('indicators'), { [c('indicators--vertical')]: vertical }]">
      <slot name="indicators">
        <i
          v-for="item in count"
          :key="item"
          :class="[c('indicators-item'), {[c('indicators-item--active')]: item - 1 === activeIndex }]"
        />
      </slot>
    </div>
  </div>
</template>

<script>
  import SwipeItem from './SwipeItem'
  import {base, touch} from '../../common/mixins'

  // 上抛的事件集合
  const emit = {
    start: 'start',
    move: 'move',
    change: 'change',
  }

  export default {
    SwipeItem,
    name: 'Swipe',
    mixins: [base, touch],

    props: {
      index: {
        // .sync 当前的位置索引,从0开始
        type: Number,
        default: 0,
      },
      auto: {
        // 是否自动播放
        type: Boolean,
        default: true,
      },
      loop: {
        // 是否循环播放
        type: Boolean,
        default: true,
      },
      interval: {
        // 自动轮播间隔时间
        type: Number,
        default: 3000,
      },
      threshold: {
        // 滑动超过这个距离(px)时才切换
        type: Number,
        default: 200,
      },
      duration: {
        // 动画时长
        type: Number,
        default: 500,
      },
      touchable: {
        // 是否可以手势滑动
        type: Boolean,
        default: true,
      },
      vertical: {
        // 是否纵向滚动
        type: Boolean,
        default: false,
      },
      showIndicators: {
        // 是否显示提示点
        type: Boolean,
        default: true,
      },
      cusClass: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        width: 0, // swipe 盒子宽
        height: 0, // swipe 盒子高
        offset: 0, // track 偏移量
        deltaX: 0,
        deltaY: 0,
        active: 0, // 活动的 index
        swipes: [], // swipe-items
        swiping: true, // 关闭 swipe 动画,
      }
    },
    computed: {
      activeIndex() {
        return (this.active + this.count) % this.count
      },
      count() {
        return this.swipes.length
      },
      delta() {
        // 差异量
        return this.vertical ? this.deltaY : this.deltaX
      },
      size() {
        // swipe-item 长度
        return this[this.vertical ? 'height' : 'width']

      },
      trackSize() {
        return this.count * this.size
      },
      trackStyle() {
        return {
          [this.vertical ? 'height' : 'width']: `${this.trackSize}px`,
          transitionDuration: `${this.swiping ? 0 : this.duration}ms`,
          transform: `translate${this.vertical ? 'Y' : 'X'}(${this.offset}px)`,
          //transform: `translate3d(${this.vertical ? `${this.offsetX}px,${this.offset}px,0` : `${this.offset}px,${this.offsetY}px,0)`}`,

        }
      },
    },
    watch: {
      swipes() {
        this.init()
      },
      index(value) {
        value === this.activeIndex || this.init()
      },
      auto(auto) {
        if (!auto) {
          this.clear()
        }
      },
    },

    created() {
      this.timer = null // 定时器
      //this.init();
    },
    mounted() {
      this.init();
    },
    destroyed() {
      this.clear()
    },
    methods: {
      init() {
        let vm = this;
        vm.clear();

        if (vm.$el) {
          vm.width = vm.$el.offsetWidth || document.documentElement.offsetWidth;
          vm.height = vm.$el.offsetHeight || document.documentElement.offsetHeight;
        } else {
          //获取窗口宽度
          if (window.innerWidth)
            vm.width = window.innerWidth;
          else if ((document.body) && (document.body.clientWidth))
          //获取窗口高度
            vm.width = document.body.clientWidth;
          if (window.innerHeight)
            vm.height = window.innerHeight;
          else if ((document.body) && (document.body.clientHeight))
            vm.height = document.body.clientHeight;
          //通过深入Document内部对body进行检测,获取窗口大小
          if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientWidth) {
            vm.height = document.documentElement.clientHeight;
            vm.width = document.documentElement.clientWidth;
          }
        }
        if (!vm.width) {
          vm.width = 750;
          vm.height = 1334;
        }
        this.active = this.index || 0;
        this.offset = this.count > 1 ? -this.size * this.active : 0
        this.swipes.forEach(swipe => {
          swipe.offset = 0;
        })

        this.swipeHeight=this.itemsHeight[this.active];
        this.autoPlay()
      },

      touchStart(e) {
        if (!this.$props.touchable) return

        this.$emit(emit.start, this.activeIndex)

        this.clear()
        this.swiping = true
        this.onTouchStart(e)
        this.correctPosition()
      },

      touchMove(e) {
        if (!this.touchable) return

        this.onTouchMove(e)

        if ((this.vertical && this.direction === 'vertical') || this.direction === 'horizontal') {
          event.preventDefault()
          event.stopPropagation()
        }

        this.$emit(emit.move, this.delta)

        this.move(0, Math.min(Math.max(this.delta, -this.size), this.size))
      },

      touchEnd(e) {
        if (!this.touchable) return
        if (this.delta) {
          const offset = this.vertical ? this.offsetY : this.offsetX
          this.move(offset > this.threshold ? (this.delta > 0 ? -1 : 1) : 0)
          this.swiping = false
        }
        this.correctPosition()
        this.autoPlay()
      },

      transitionend() {
        this.$emit(emit.change, this.activeIndex)
        this.$emit('update:index', this.activeIndex)
      },
      scopeToTop() {
        this.$refs.swipeContent.scrollTop = 0;
      },
      move(move = 0, offset = 0) {
        const {delta, active, count, swipes, trackSize} = this
        const atFirst = active === 0
        const atLast = active === count - 1
        const outOfBounds = !this.loop && ((atFirst && (offset > 0 || move < 0)) || (atLast && (offset < 0 || move > 0)))

        if (outOfBounds || count <= 1) {
          return
        }

        if (move) {
          if (active === -1) {
            swipes[count - 1].offset = 0
          }
          swipes[0].offset = atLast && move > 0 ? trackSize : 0
          this.active += move;

          this.scopeToTop();
        } else {
          if (atFirst) {
            swipes[count - 1].offset = delta > 0 ? -trackSize : 0
          } else if (atLast) {
            swipes[0].offset = delta < 0 ? trackSize : 0
          }
        }

        this.offset = offset - this.active * this.size
      },

      // 超出边界时移动到正确的位置
      correctPosition() {
        if (this.active <= -1) {
          this.move(this.count)
        }
        if (this.active >= this.count) {
          this.move(-this.count)
        }
      },

      clear() {
        clearTimeout(this.timer)
      },

      autoPlay() {
        if (this.auto && this.count > 1) {
          this.clear()
          this.timer = setTimeout(() => {
            this.swiping = true
            this.correctPosition()

            setTimeout(() => {
              this.swiping = false
              this.move(1)
              this.autoPlay()
            }, 30)
          }, this.interval)
        }
      },
    },
  }
</script>

<style lang="stylus">

  .hls-swipe {
    overflow: auto;
    position: relative;
    user-select: none;
    width: 100%;
    &-item {
      float: left;
      height: 100%;
      img {
        width 100%
        max-width 100%
      }
    }

    &-track {
      height: 100%;
    }

    &-indicators {
      display: flex;
      position: absolute;
      left: 50%;
      bottom: 20px;
      transform: translateX(-50%);

      &--vertical {
        left: 20px;
        top: 50%;
        bottom: auto;
        flex-direction: column;
        transform: translateY(-50%);

        .hips-swipe-indicators-item:not(:last-child) {
          margin-bottom: 12px;
        }
      }

      &-item {
        border-radius: 100%;
        background-color: rgba(0, 0, 0, 0.2);
        width: 12px;
        height: 12px;
        margin-top: 12px;

        &:not(:last-child) {
          margin-right: 12px;
          //margin-top: 12px;
        }
        /*&:not(:first-child){
          margin-top: 12px;
        }*/

        &--active {
          background-color: rgba(0, 0, 0, 0.5);
        }
      }
    }
  }
</style>