<template>
  <div id="slide" :style="{width: Width, height: Height}" v-el:wrap @touchstart.prevent="touchstart($event)" @touchmove.prevent="touchmove($event)" @touchend.prevent="touchend($event)">
    <ul>
      <li v-for="item in list" track-by="$index" v-bind:style="SlideState[$index]">
        <a :href="item.link">
          <img :src="item.img">
        </a>
      </li>
    </ul>
    <div class="dot-wrap" v-if="Dot && list.length > 1" v-bind:style="Position === 'left' ? {left: 0} : {right: 0}">
      <span class="dot" v-for="item in Slide" v-bind:class="cacheState.indexOf('middle') % Slide.length === $index ? 'active' : ''"></span>
    </div>
  </div>
</template>

<style scoped>
  #slide {
    position: relative;
    overflow: hidden;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden; 
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d;
  }

  #slide, #slide ul, #slide li, #slide img, #slide .dot-wrap{
    padding: 0;
    margin: 0;
  }

  #slide ul, #slide li{
    list-style: none;
  }

  #slide img{
    border: none;
    outline: none;
  }

  #slide a{
    text-decoration: none;
  }

  #slide ul li{
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
  }

  #slide ul li a{
    width: 100%;
    height: 100%;
    display: block;
  }

  #slide ul li img{
    width: 100%;
    height: 100%;
  }

  #slide .dot-wrap{
    z-index: 200;
    position: absolute;
    bottom: 0;
    overflow: hidden;
    clear: both;
  }
  
  #slide .dot-wrap .dot{
    display: inline-block;
    border-radius: 50%;
    background: rgba(255,255,255,0.6);
  }

  #slide .dot-wrap .dot.active{
    background: white;
  }

  [data-dpr="1"] #slide .dot-wrap{
    padding: 5px 5px 3px 5px;
  }

  [data-dpr="1"] #slide .dot-wrap .dot{
    width: 6px;
    height: 6px;
    margin: 2px;
  }

  [data-dpr="2"] #slide .dot-wrap{
    padding: 10px 10px 6px 10px;
  }

  [data-dpr="2"] #slide .dot-wrap .dot{
    width: 12px;
    height: 12px;
    margin: 4px;
  }

  [data-dpr="3"] #slide .dot-wrap{
    padding: 15px 15px 9px 15px;
  }

  [data-dpr="3"] #slide .dot-wrap .dot{
    width: 18px;
    height: 18px;
    margin: 6px;
  }

</style>
  
<script>
export default {
  props: {
    'Slide': {
      type: Array,
      required: true
    },
    'Millisec': {
      type: Number,
      default: 5
    },
    'Duration': {
      type: Number,
      default: 300
    },
    'Dot': {
      type: Boolean,
      default: true
    },
    'Position': {
      type: String,
      default: 'right'
    },
    'Width': {
      type: String,
      default: '100%'
    },
    'Height': {
      type: String,
      default: '200px'
    }
  },
  data () {
    return {
      SlideState: [],
      cacheState: [],
      time: 0,
      timer: null,
      sx: '',
      t: '',
      tl: '',
      tr: '',
      tlX: '',
      trX: '',
      tX: ''
    }
  },
  methods: {
    touchstart: function (event) {
      clearInterval(this.timer)
      this.sx = event.changedTouches[0].clientX
      this.t = event.target.parentNode.parentNode
      this.tX = 0
      this.tlX = -this.t.offsetWidth
      this.trX = this.t.offsetWidth
    },
    touchmove: function (event) {
      if (this.list.length < 2) {
        return 
      } 
      const sm = event.changedTouches[0].clientX
      const l = sm - this.sx
      this.time = 0
      this.SlideState.splice(this.cacheState.indexOf('middle'), 1, formatStyle(this.time, l + this.tX, 100))
      this.SlideState.splice(this.cacheState.indexOf('left'), 1, formatStyle(this.time, l + this.tlX, 100))
      this.SlideState.splice(this.cacheState.indexOf('right'), 1, formatStyle(this.time, l + this.trX, 100))
    },
    touchend: function (event) {
      const se = event.changedTouches[0].clientX
      this.time = this.Duration
      if (Math.floor(se) > Math.floor(this.sx)) {
        this.slide('negative')
        this.slide('negative')
      }
      if (Math.floor(se) !== Math.floor(this.sx)) {
        this.slide('positive')
      } else {
        window.location.href = event.target.parentNode.href
      }
      this.timer = setInterval(() => {
        this.slide('positive')
      }, this.Millisec * 1000)
    },
    slide: function (direction) {
      this.cacheState = store(this.cacheState, direction)
      this.SlideState = cache2slide(this, this.cacheState)
    }
  },
  ready () {
    // init
    const l = this.list.length
    const duration = this.Duration
    if (l < 2) {
      return
    }
    this.cacheState = ['left', 'middle', 'right']
    for (var i = 0; i < l - 3; i++) {
      this.cacheState.push('visible')
    }
    this.slide('negative')
    // Interval
    this.timer = setInterval(() => {
      this.time = duration
      this.slide('positive')
    }, this.Millisec * 1000)

    window.addEventListener('orientationchange', () => {
      this.time = 0
      this.SlideState = cache2slide(this, this.cacheState)
    });

  },
  mounted () {
    this.ready()
  },
  computed: {
    'list': function () {
      const l = this.Slide.length
      if (l > 1 && l < 4) {
        return this.Slide.concat(this.Slide)
      } else {
        return this.Slide
      }
    },
    'left': function () {
      return formatStyle(this.time, -this.$els.wrap.offsetWidth, '100')
    },
    'middle': function () {
      return formatStyle(this.time, 0, '100')
    },
    'right': function () {
      return formatStyle(this.time, this.$els.wrap.offsetWidth, '100')
    },
    'visible': function () {
      return formatStyle(0, this.$els.wrap.offsetWidth, '1')
    }
  }
}

function store (arr, how) {
  if (how === 'positive') {
    arr.unshift(arr.pop())
  } else if (how === 'negative') {
    arr.push(arr.shift())
  }
  return arr
}

function formatStyle (t, w, Z) {
  return {
    'transition': 'all ' + t + 'ms ease',
    '-webkit-transition': 'all ' + t + 'ms ease',
    transform: 'translate3d(' + w + 'px,0px,0px)',
    '-webkit-transform': 'translate3d(' + w + 'px,0px,0px)',
    'z-index': Z
  }
}

function cache2slide (obj, cache) {
  let arr = []
  cache.forEach((value, index) => {
    arr.push(obj[value])
  })
  return arr
}

</script>
