<template>
    <transition-group :name="$style.turnover" :css="false" :tag="tag" :appear="appear"
                      @appear="enter" @enter="enter" @leave="leave">
        <slot></slot>
    </transition-group>
</template>

<style module>
    .turnover:global(-move) {
        transition: .3s;
    }
</style>

<script>
  import { prefixed } from '../../tools/prefix/index'

  let delayName = prefixed('transitionDelay')
  let durationName = prefixed('transitionDuration')

  export default {
    props: {
      tag: {
        type: String,
        default: 'div'
      },
      appear: {
        type: Boolean,
        default: true
      },
      duration: { // 过渡时间，单位ms
        type: Number,
        default: 200
      },
      timingFunction: { // 过渡缓动函数
        type: String,
        default: 'ease'
      },
      from: { // 初始状态的样式
        type: Object,
        default () {
          return {
            opacity: 0,
            transform: 'translate3d(50%, -50%, 0)'
          }
        }
      },
      to: { // leave时的最终样式，未设置默认跟from一致
        validator (value) {
          return value === undefined || value instanceof Object
        }
      }
    },
    computed: {
      $style () {
        return this.$options.cssModules
      },
      toStyle () {
        return this.to || this.from
      }
    },
    methods: {
      enter (el, done) {
        let siblings = [].slice.call(this.$el.children)
        let interval = this.duration / siblings.length
        let delay = siblings.indexOf(el) * interval

        Object.assign(el.style, {
          [delayName]: `${delay}ms`,
          [durationName]: `${this.duration}ms`
        })
        Object.keys(this.from).forEach((prop) => {
          el.style[prefixed(prop)] = this.from[prop]
        })
        setTimeout(() => {
          Object.keys(this.from).forEach((prop) => {
            el.style[prefixed(prop)] = ''
          })
          setTimeout(done, delay + this.duration)
        })
      },
      leave (el, done) {
        let siblings = [].slice.call(this.$el.children)
        let interval = this.duration / siblings.length
        let delay = (siblings.length - 1 - siblings.indexOf(el)) * interval

        Object.assign(el.style, {
          [delayName]: `${delay}ms`,
          [durationName]: `${this.duration}ms`
        })
        setTimeout(() => {
          Object.keys(this.toStyle).forEach((prop) => {
            el.style[prefixed(prop)] = this.toStyle[prop]
          })
          setTimeout(done, delay + this.duration)
        })
      }
    }
  }
</script>