/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import './slider.css'

const TRANSITION_TIME = 400
const NEIGHBOR_SCALE_TIME = 100
const MAIN_SLIDE_OPACITY = 1
const THROTTLE_SCROLL_TIME = 25
const INTERVAL_MINIMUM = 200

export default {
  created () {
    this._clones = []
    this.innerOffset = 0
    this._indicator = null
  },

  beforeUpdate () {
    this._getWrapperSize()
  },

  updated () {
    const children = this.$children
    const len = children && children.length
    if (children && len > 0) {
      for (let i = 0; i < len; i++) {
        const vm = children[i]
        if (vm.$options._componentTag === 'indicator'
          || vm.$vnode.data.ref === 'indicator') {
          vm._watcher.get()
          break
        }
      }
    }
    weex.utils.fireLazyload(this.$el, true)
    if (this._preIndex !== this.currentIndex) {
      this._slideTo(this.currentIndex)
    }
  },

  mounted () {
    this._getWrapperSize()
    this._slideTo(this.currentIndex)
    weex.utils.fireLazyload(this.$el, true)
  },

  methods: {
    _getWrapperSize () {
      const wrapper = this.$refs.wrapper
      if (wrapper) {
        const rect = wrapper.getBoundingClientRect()
        this._wrapperWidth = rect.width
        this._wrapperHeight = rect.height
      }
    },

    _formatChildren (createElement) {
      const children = this.$slots.default || []
      let indicatorVnode
      const cells = children.filter(vnode => {
        if (!vnode.tag) return false
        if (vnode.componentOptions && vnode.componentOptions.tag === 'indicator') {
          indicatorVnode = vnode
          return false
        }
        return true
      }).map(vnode => {
        return createElement('li', {
          ref: 'cells',
          staticClass: `weex-slider-cell weex-ct${this.isNeighbor ? ' neighbor-cell' : ''}`
        }, [vnode])
      })
      if (indicatorVnode) {
        indicatorVnode.data.attrs = indicatorVnode.data.attrs || {}
        indicatorVnode.data.attrs.count = cells.length
        indicatorVnode.data.attrs.active = this.currentIndex
        this._indicator = indicatorVnode
      }
      return cells
    },

    _renderSlides (createElement) {
      this._cells = this._formatChildren(createElement)
      this.frameCount = this._cells.length
      return createElement(
        'nav',
        {
          ref: 'wrapper',
          attrs: { 'weex-type': this.isNeighbor ? 'slider-neighbor' : 'slider' },
          on: weex.createEventMap(
            this,
            ['scroll', 'scrollstart', 'scrollend'],
            {
              touchstart: this._handleTouchStart,
              touchmove: weex.utils.throttle(weex.utils.bind(this._handleTouchMove, this), 25),
              touchend: this._handleTouchEnd,
              touchcancel: this._handleTouchCancel
            }
          ),
          staticClass: 'weex-slider weex-slider-wrapper weex-ct',
          staticStyle: weex.extractComponentStyle(this)
        },
        [
          createElement('ul', {
            ref: 'inner',
            staticClass: 'weex-slider-inner weex-ct'
          }, this._cells),
          this._indicator
        ]
      )
    },

    // get standard index
    _normalizeIndex (index) {
      const newIndex = (index + this.frameCount) % this.frameCount
      return Math.min(Math.max(newIndex, 0), this.frameCount - 1)
    },

    _startAutoPlay () {
      if (!this.autoPlay || this.autoPlay === 'false') {
        return
      }
      if (this._autoPlayTimer) {
        clearTimeout(this._autoPlayTimer)
        this._autoPlayTimer = null
      }
      let interval = parseInt(this.interval - TRANSITION_TIME - NEIGHBOR_SCALE_TIME)
      interval = interval > INTERVAL_MINIMUM ? interval : INTERVAL_MINIMUM
      this._autoPlayTimer = setTimeout(weex.utils.bind(this._next, this), interval)
    },

    _stopAutoPlay () {
      if (this._autoPlayTimer) {
        clearTimeout(this._autoPlayTimer)
        this._autoPlayTimer = null
      }
    },

    _slideTo (index, isTouchScroll) {
      if (this.frameCount <= 0) {
        return
      }
      if (!this.infinite || this.infinite === 'false') {
        if (index === -1 || index > (this.frameCount - 1)) {
          this._slideTo(this.currentIndex)
          return
        }
      }

      if (!this._preIndex && this._preIndex !== 0) {
        if (this._showNodes && this._showNodes[0]) {
          this._preIndex = this._showNodes[0].index
        }
        else {
          this._preIndex = this.currentIndex
        }
      }

      if (this._sliding) {
        return
      }
      this._sliding = true

      const newIndex = this._normalizeIndex(index)
      const inner = this.$refs.inner
      const step = this._step = this.frameCount <= 1 ? 0 : this._preIndex - index

      if (inner) {
        this._prepareNodes()
        const translate = weex.utils.getTransformObj(inner).translate
        const match = translate && translate.match(/translate[^(]+\(([+-\d.]+)/)
        const innerX = match && match[1] || 0
        const dist = innerX - this.innerOffset
        this.innerOffset += step * this._wrapperWidth
        // transform the whole slides group.
        inner.style.webkitTransition = `-webkit-transform ${TRANSITION_TIME / 1000}s ease-in-out`
        inner.style.mozTransition = `transform ${TRANSITION_TIME / 1000}s ease-in-out`
        inner.style.transition = `transform ${TRANSITION_TIME / 1000}s ease-in-out`
        inner.style.webkitTransform = `translate3d(${this.innerOffset}px, 0, 0)`
        inner.style.mozTransform = `translate3d(${this.innerOffset}px, 0, 0)`
        inner.style.transform = `translate3d(${this.innerOffset}px, 0, 0)`

        // emit scroll events.
        if (!isTouchScroll) {
          this._emitScrollEvent('scrollstart')
        }
        setTimeout(() => {
          this._throttleEmitScroll(dist, () => {
            this._emitScrollEvent('scrollend')
          })
        }, THROTTLE_SCROLL_TIME)

        this._loopShowNodes(step)

        setTimeout(() => {
          if (this.isNeighbor) {
            this._setNeighbors()
          }

          setTimeout(() => {
            inner.style.webkitTransition = ''
            inner.style.mozTransition = ''
            inner.style.transition = ''
            for (let i = this._showStartIdx; i <= this._showEndIdx; i++) {
              const node = this._showNodes[i]
              if (!node) { continue }
              const elm = node.firstElementChild
              elm.style.webkitTransition = ''
              elm.style.mozTransition = ''
              elm.style.transition = ''
            }
            // clean cloned nodes and rearrange slide cells.
            this._rearrangeNodes(newIndex)
          }, NEIGHBOR_SCALE_TIME)
        }, TRANSITION_TIME)
      }

      if (newIndex !== this._preIndex) {
        this.$emit('change', weex.utils.createEvent(this.$el, 'change', {
          index: newIndex
        }))
      }
    },

    _clearNodesOffset () {
      const end = this._showEndIdx
      for (let i = this._showStartIdx; i <= end; i++) {
        let node = this._showNodes[i]
        node = node && node.firstElementChild
        if (!node) { continue }
        weex.utils.addTransform(this._showNodes[i].firstElementChild, {
          translate: 'translate3d(0px, 0px, 0px)'
        })
      }
    },

    _loopShowNodes (step) {
      if (!step || this.frameCount <= 1) {
        return
      }
      const sign = step > 0 ? 1 : -1
      let i = step <= 0 ? this._showStartIdx : this._showEndIdx
      const end = step <= 0 ? this._showEndIdx : this._showStartIdx
      for (; i !== end - sign; i -= sign) {
        const nextIdx = i + step
        this._showNodes[nextIdx] = this._showNodes[i]
        this._showNodes[nextIdx]._showIndex = nextIdx
        delete this._showNodes[i]
      }
      this._showStartIdx += step
      this._showEndIdx += step
    },

    _prepareNodes () {
      // test if the next slide towards the direction exists.
      // e.g. currentIndex 0 -> 1: should prepare 4 slides: -1, 0, 1, 2
      // if not, translate a node to here, or just clone it.
      const step = this._step
      if (!this._inited) {
        this._initNodes()
        this._inited = true
        this._showNodes = {}
      }
      if (this.frameCount <= 1) {
        this._showStartIdx = this._showEndIdx = 0
        const node = this._cells[0].elm
        node.style.opacity = 1
        node.style.zIndex = 99
        node.index = 0
        this._showNodes[0] = node
        node._inShow = true
        node._showIndex = 0
        return
      }
      const showCount = this._showCount = Math.abs(step) + 3
      this._showStartIdx = step <= 0 ? -1 : 2 - showCount
      this._showEndIdx = step <= 0 ? showCount - 2 : 1
      this._clearNodesOffset()
      this._positionNodes(this._showStartIdx, this._showEndIdx, step)
    },

    _initNodes () {
      const total = this.frameCount
      const cells = this._cells
      for (let i = 0; i < total; i++) {
        const node = cells[i].elm
        node.index = i
        node._inShow = false
        node.style.zIndex = 0
        node.style.opacity = 0
      }
    },

    _positionNodes (begin, end, step, anim) {
      const cells = this._cells
      const start = step <= 0 ? begin : end
      const stop = step <= 0 ? end : begin
      const sign = step <= 0 ? -1 : 1
      let cellIndex = this._preIndex + sign
      for (let i = start; i !== stop - sign; i = i - sign) {
        const node = cells[this._normalizeIndex(cellIndex)].elm
        cellIndex = cellIndex - sign
        this._positionNode(node, i)
      }
    },

    /**
     * index: position index in the showing cells' view.
     */
    _positionNode (node, index) {
      const holder = this._showNodes[index]
      if (node._inShow && holder !== node) {
        if (holder) { this._removeClone(holder) }
        node = this._getClone(node.index)
      }
      else if (node._inShow) {
        return
      }

      node._inShow = true
      const translateX = index * this._wrapperWidth - this.innerOffset
      weex.utils.addTransform(node, {
        translate: `translate3d(${translateX}px, 0px, 0px)`
      })
      node.style.zIndex = 99 - Math.abs(index)
      node.style.opacity = 1
      node._showIndex = index
      this._showNodes[index] = node
    },

    _getClone (index) {
      let arr = this._clones[index]
      if (!arr) {
        this._clones[index] = arr = []
      }
      if (arr.length <= 0) {
        const origNode = this._cells[index].elm
        const clone = origNode.cloneNode(true)
        clone._isClone = true
        clone._inShow = origNode._inShow
        clone.index = origNode.index
        clone.style.opacity = 0
        clone.style.zIndex = 0
        const ct = this.$refs.inner
        ct.appendChild(clone)
        arr.push(clone)
      }
      return arr.pop()
    },

    _removeClone (node) {
      const idx = node.index
      this._hideNode(node)
      const arr = this._clones[idx]
      arr.push(node)
    },

    _hideNode (node) {
      node._inShow = false
      node.style.opacity = 0
      node.style.zIndex = 0
    },

    /**
     * hide nodes from begin to end in showArray.
     * if it is clone node, just move the clone node to the buffer.
     */
    _clearNodes (begin, end) {
      for (let i = begin; i <= end; i++) {
        const node = this._showNodes[i]
        if (!node) { return }
        if (node._isClone) {
          this._removeClone(node)
        }
        else if (!node._inShow) {
          this._hideNode(node)
        }
        delete this._showNodes[i]
      }
    },

    /**
     * copy node style props (opacity and zIndex) and transform status from
     * one element to another.
     */
    _copyStyle (from, to, styles = ['opacity', 'zIndex'], transformExtra = {}) {
      weex.utils.extendKeys(to.style, from.style, styles)
      const transObj = weex.utils.getTransformObj(from)
      for (const k in transformExtra) {
        transObj[k] = transformExtra[k]
      }
      weex.utils.addTransform(to, transObj)
      const fromInner = from.firstElementChild
      const toInner = to.firstElementChild
      toInner.style.opacity = fromInner.style.opacity
      weex.utils.copyTransform(fromInner, toInner)
    },

    /**
     * replace a clone node with the original node if it's not in use.
     */
    _replaceClone (clone, pos) {
      const origNode = this._cells[clone.index].elm
      if (origNode._inShow) {
        return
      }
      const origShowIndex = origNode._showIndex
      const styleProps = ['opacity', 'zIndex']
      let cl
      if (Math.abs(origShowIndex) <= 1) {
        // leave a clone to replace the origNode in the show zone(-1 ~ 1).
        cl = this._getClone(origNode.index)
        this._copyStyle(origNode, cl)
        this._showNodes[origShowIndex] = cl
      }
      origNode._inShow = true
      const transObj = weex.utils.getTransformObj(clone)
      transObj.translate = transObj.translate.replace(/[+-\d.]+[pw]x/, ($0) => {
        return pos * this._wrapperWidth - this.innerOffset + 'px'
      })
      this._copyStyle(clone, origNode, styleProps, transObj)
      this._removeClone(clone)
      if (!cl) {
        delete this._showNodes[origShowIndex]
      }
      this._showNodes[pos] = origNode
      origNode._showIndex = pos
    },

    _rearrangeNodes (newIndex) {
      if (this.frameCount <= 1) {
        this._sliding = false
        this.currentIndex = 0
        return
      }

      // clear autoPlay timer (and restart after updated hook).
      this._startAutoPlay()

      /**
       * clean nodes. replace current node with non-cloned node.
       * set current index to the new index.
       */
      const shows = this._showNodes
      for (let i = this._showStartIdx; i <= this._showEndIdx; i++) {
        shows[i]._inShow = false
      }
      for (let i = -1; i <= 1; i++) {
        const node = shows[i]
        if (!node._isClone) {
          node._inShow = true
        }
        else {
          this._replaceClone(node, i)
        }
      }

      this._clearNodes(this._showStartIdx, -2)
      this._showStartIdx = -1
      this._clearNodes(2, this._showEndIdx)
      this._showEndIdx = 1
      this._sliding = false

      // set current index to the new index.
      this.currentIndex = newIndex
      this._preIndex = newIndex
    },

    /**
     * according to the attrs: neighborScale, neighborAlpha, neighborSpace.
     * 1. apply the main cell transform effects.
     * 2. set the previous cell and the next cell's positon, scale and alpha.
     * 3. set other cells' scale and alpha.
     */
    _setNeighbors () {
      for (let i = this._showStartIdx; i <= this._showEndIdx; i++) {
        const elm = this._showNodes[i].firstElementChild
        elm.style.webkitTransition = `all ${NEIGHBOR_SCALE_TIME / 1000}s ease`
        elm.style.mozTransition = `all ${NEIGHBOR_SCALE_TIME / 1000}s ease`
        elm.style.transition = `all ${NEIGHBOR_SCALE_TIME / 1000}s ease`
        const transObj = {
          scale: `scale(${i === 0 ? this.currentItemScale : this.neighborScale})`
        }
        let translateX
        if (!this._neighborWidth) {
          this._neighborWidth = parseFloat(elm.style.width) || elm.getBoundingClientRect().width
        }
        // calculate position offsets according to neighbor scales.
        if (Math.abs(i) === 1) {
          const dist = ((this._wrapperWidth - this._neighborWidth * this.neighborScale) / 2
            + this.neighborSpace * weex.config.env.scale) / this.neighborScale
          translateX = -i * dist
        }
        else {
          // clear position offsets.
          translateX = 0
        }
        transObj.translate = `translate3d(${translateX}px, 0px, 0px)`
        weex.utils.addTransform(elm, transObj)
        elm.style.opacity = i === 0 ? MAIN_SLIDE_OPACITY : this.neighborAlpha
      }
    },

    _next () {
      let next = this.currentIndex + 1
      if (this.frameCount <= 1) {
        next--
      }
      this._slideTo(next)
    },

    _prev () {
      let prev = this.currentIndex - 1
      if (this.frameCount <= 1) {
        prev++
      }
      this._slideTo(prev)
    },

    _handleTouchStart (event) {
      const touch = event.changedTouches[0]
      this._stopAutoPlay()
      const inner = this.$refs.inner
      this._touchParams = {
        originalTransform: inner.style.webkitTransform
          || inner.style.mozTransform
          || inner.style.transform,
        startTouchEvent: touch,
        startX: touch.pageX,
        startY: touch.pageY,
        timeStamp: event.timeStamp
      }
    },

    _handleTouchMove (event) {
      const tp = this._touchParams
      if (!tp) { return }
      if (this._sliding) {
        if (process.env.NODE_ENV === 'development') {
          console.warn(`[vue-render] warn: can't scroll the slider during sliding.`)
        }
        return
      }
      const { startX, startY } = this._touchParams
      const touch = event.changedTouches[0]
      const offsetX = touch.pageX - startX
      const offsetY = touch.pageY - startY
      tp.offsetX = offsetX
      tp.offsetY = offsetY
      let isV = tp.isVertical
      if (typeof isV === 'undefined') {
        isV = tp.isVertical = Math.abs(offsetX) < Math.abs(offsetY)
        if (!isV) {
          this._emitScrollEvent('scrollstart')
        }
      }
      // vertical scroll. just ignore it.
      if (isV) {
        return
      }
      // horizontal scroll. trigger scroll event.
      event.preventDefault()
      const inner = this.$refs.inner
      if (inner && offsetX) {
        if (!this._nodesOffsetCleared) {
          this._nodesOffsetCleared = true
          this._clearNodesOffset()
        }
        this._emitScrollEvent('scroll', {
          offsetXRatio: offsetX / this._wrapperWidth
        })
        inner.style.webkitTransform = `translate3d(${this.innerOffset + offsetX}px, 0, 0)`
        inner.style.mozTransform = `translate3d(${this.innerOffset + offsetX}px, 0, 0)`
        inner.style.transform = `translate3d(${this.innerOffset + offsetX}px, 0, 0)`
      }
    },

    _handleTouchEnd (event) {
      this._startAutoPlay()
      const tp = this._touchParams
      if (!tp) { return }
      const isV = tp.isVertical
      if (typeof isV === 'undefined') {
        return
      }
      const inner = this.$refs.inner
      const { offsetX } = tp
      if (inner) {
        this._nodesOffsetCleared = false
        // TODO: test the velocity if it's less than 0.2.
        const reset = Math.abs(offsetX / this._wrapperWidth) < 0.2
        const direction = offsetX > 0 ? 1 : -1
        const newIndex = reset ? this.currentIndex : (this.currentIndex - direction)
        this._slideTo(newIndex, true)
      }
      delete this._touchParams
    },

    _handleTouchCancel (event) {
      return this._handleTouchEnd(event)
    },

    _emitScrollEvent (type, data = {}) {
      this.$emit(type, weex.utils.createEvent(this.$el, type, data))
    },

    _throttleEmitScroll (offset, callback) {
      let i = 0
      const throttleTime = THROTTLE_SCROLL_TIME
      const cnt = parseInt(TRANSITION_TIME / throttleTime) - 1
      const sign = offset > 0 ? 1 : -1
      const r = Math.abs(offset / this._wrapperWidth)
      const throttledScroll = () => {
        if (++i > cnt) {
          return callback && callback.call(this)
        }
        const ratio = this._step === 0
          ? sign * r * (1 - i / cnt)
          : sign * (r + (1 - r) * i / cnt)
        this._emitScrollEvent('scroll', {
          offsetXRatio: ratio
        })
        setTimeout(throttledScroll, THROTTLE_SCROLL_TIME)
      }
      throttledScroll()
    }
  }
}
