<template>
  <div class="slide-layout" ref="layout">
    <div class="slide-content"
      :class="{animation: !pauseAnimation}"
      :style="{
        transform: 'translateX(' + (left + activeLeft) + 'px)',
        width: contentWidth + 'px',
      }">
      <div v-for="(item, i) in slideItems" :key="i"
        class="slide-item"
        :class="{active: i === showActive}"
        :style="{width: itemWidth + 'px', transform: 'translateX(' + i + '00%)'}">
        <slot name="item" :data="item" :active="i === showActive" :index="i - extend" />
      </div>
    </div>
    <div class="slide-control" v-if="ctrl">
      <slot v-for="(item, i) in items" name="ctrl-item" :index="i" :active="i === mapActive" />
    </div>
  </div>
</template>

<script>

function extendItems (items, extend) {
  let result = [...items]
  if (items.length <= 1) return result

  let insertBefore = items.length - 1
  let insertAfter = 0

  for (var i = 0; i < extend; i++) {
    if (insertAfter >= items.length) {
      insertAfter = 0
    }
    if (insertBefore < 0) {
      insertBefore = items.length - 1
    }

    result.push(items[insertAfter])
    result.unshift(items[insertBefore])
    insertBefore--
    insertAfter++
  }

  return result
}

export default {
  name: 'slide',
  props: {
    items: {
      default: () => [],
      type: Array
    },
    ctrl: {
      default: false
    },
    extend: {
      default: 1,
      type: Number
    },
    focus: {
      default: 0,
      type: Number
    }
  },
  data () {
    let slideItems = extendItems(this.items, this.extend)

    return {
      slideItems,
      active: 0,
      mapActive: 0,
      animations: [],
      pauseAnimation: true,
      outWidth: window.outerWidth,
      activeLeft: 0
    }
  },
  computed: {
    itemWidth () {
      return this.outWidth
    },
    contentWidth () {
      return this.slideItems.length * this.outWidth
    },
    showActive () {
      return this.slideItems.length === 1 ? 0 : this.active + this.extend
    },
    left () {
      return -this.showActive * this.itemWidth
    }
  },
  watch: {
    focus: {
      immediate: true,
      handler (newVal) {
        this.active = newVal
      }
    },
    active (newVal) {
      let newActive = null
      if (newVal === -1) {
        newActive = this.items.length - 1
      } else if (newVal >= this.items.length) {
        newActive = 0
      }
      if (newActive !== null) {
        this.mapActive = newActive

        clearTimeout(this.timeout1)
        this.timeout1 = setTimeout(() => {
          this.pauseAnimation = true
          setTimeout(() => {
            this.active = newActive
            setTimeout(() => {
              this.pauseAnimation = false
            }, 16)
          })
        }, 300)
      } else {
        this.mapActive = this.active
      }
    },
    mapActive: {
      immediate: true,
      handler (newVal) {
        this.$emit('slidechange', this.items[newVal], newVal)
      }
    }
  },
  methods: {
    next () {
      this.active++
    },
    prev () {
      this.active--
    },
    startHandle (ev) {
      this.pauseAnimation = true
      this.startX = ev.touches[0].clientX
    },
    moveHandle (ev) {
      this.activeLeft = ev.touches[0].clientX - this.startX
    },
    endHandle (ev) {
      if (this.activeLeft > 100) {
        this.prev()
      } else if (this.activeLeft < -100) {
        this.next()
      }
      this.pauseAnimation = false
      this.activeLeft = 0
    }
  },
  mounted () {
    setTimeout(() => {
      this.pauseAnimation = false
    })
    this.outWidth = this.$refs.layout.offsetWidth
    this.startHandle = this.startHandle.bind(this)
    this.moveHandle = this.moveHandle.bind(this)
    this.endHandle = this.endHandle.bind(this)
    this.$refs.layout.addEventListener('touchstart', this.startHandle, false)
    this.$refs.layout.addEventListener('touchmove', this.moveHandle, false)
    this.$refs.layout.addEventListener('touchend', this.endHandle, false)
  },
  beforeDestroy () {
    this.$refs.layout.removeEventListener('touchstart', this.startHandle, false)
    this.$refs.layout.removeEventListener('touchmove', this.moveHandle, false)
    this.$refs.layout.removeEventListener('touchend', this.endHandle, false)
  }
}
</script>

<style scoped>
.slide-layout {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.slide-content {
  height: 100%;
  position: relative;
}

.slide-item {
  height: 100%;
  overflow: hidden;
  position: absolute;
  top: 0;
}

.animation {
  transition: all .2s linear;
}

.slide-control {
  position: absolute;
  bottom: 7.5%;
  left: 50%;
  transform: translateX(-50%);
}
</style>
