function converPx (value) {
  if (/^-?\d+[ur]px$/i.test(value)) {
    return value.replace(/(^-?\d+)[ur]px$/i, (text, num) => {
      return `${uni.upx2px(parseFloat(num))}px`
    })
    // eslint-disable-next-line no-useless-escape
  } else if (/^-?[\d\.]+$/.test(value)) {
    return `${value}px`
  }
  return value || ''
}

function converType (type) {
  return type.replace(/[A-Z]/g, text => {
    return `-${text.toLowerCase()}`
  }).replace('webkit', '-webkit')
}

function getStyle (action) {
  const animateTypes1 = ['matrix', 'matrix3d', 'scale', 'scale3d', 'rotate3d', 'skew', 'translate', 'translate3d']
  const animateTypes2 = ['scaleX', 'scaleY', 'scaleZ', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'skewX', 'skewY', 'translateX', 'translateY', 'translateZ']
  const animateTypes3 = ['opacity', 'background-color']
  const animateTypes4 = ['width', 'height', 'left', 'right', 'top', 'bottom']
  const animates = action.animates
  const option = action.option
  const transition = option.transition
  const style = {}
  const transform = []
  animates.forEach(animate => {
    let type = animate.type
    let args = [...animate.args]
    if (animateTypes1.concat(animateTypes2).includes(type)) {
      if (type.startsWith('rotate') || type.startsWith('skew')) {
        args = args.map(value => parseFloat(value) + 'deg')
      } else if (type.startsWith('translate')) {
        args = args.map(converPx)
      }
      if (animateTypes2.indexOf(type) >= 0) {
        args.length = 1
      }
      transform.push(`${type}(${args.join(',')})`)
    } else if (animateTypes3.concat(animateTypes4).includes(args[0])) {
      type = args[0]
      const value = args[1]
      style[type] = animateTypes4.includes(type) ? converPx(value) : value
    }
  })
  style.transform = style.webkitTransform = transform.join(' ')
  style.transition = style.webkitTransition = Object.keys(style).map(type => `${converType(type)} ${transition.duration}ms ${transition.timingFunction} ${transition.delay}ms`).join(',')
  style.transformOrigin = style.webkitTransformOrigin = option.transformOrigin
  return style
}

export function startAnimation (context) {
  const animation = context.animation
  if (!animation || !animation.actions || !animation.actions.length) {
    return
  }
  let index = 0
  const actions = animation.actions
  const length = animation.actions.length
  function animate () {
    const action = actions[index]
    const transition = action.option.transition
    const style = getStyle(action)
    Object.keys(style).forEach(key => {
      context.$el.style[key] = style[key]
    })

    index += 1
    if (index < length) {
      setTimeout(animate, transition.duration + transition.delay)
    }
  }

  setTimeout(() => {
    animate()
  }, 0)
}

export default {
  props: ['animation'],
  watch: {
    animation () {
      startAnimation(this)
    }
  },
  mounted () {
    startAnimation(this)
  }
}
