<style scoped>
  .waterfall-flow--no-data {
    line-height: 2;
    color: #ccc;
    text-align: center;
  }
  .visibility {
    visibility: hidden;
  }
  .waterfall-flow__wrapper {
    width: 100%;
  }
  .waterfall-flow__body {
    list-style: none;
    min-height: 88px;
    position: relative;
  }
  .waterfall-flow__footer {

  }
</style>

<template>
  <div class="waterfall-flow__wrapper">
    <p class="waterfall-flow--no-data" v-if="list.length === 0">暂无数据</p>
    <ul class="waterfall-flow__body" ref="body" v-if="list.length">
      <waterfall-flow-item v-for="(item, index) in list" :key="index" :item="item" :selected="selected">
        <slot name="body" :item="item">

        </slot>
      </waterfall-flow-item>
    </ul>
    <div class="waterfall-flow__footer" v-if="list.length">
      <slot name="footer">

      </slot>
    </div>
  </div>
</template>

<script>
import emitter from '@src/mixins/emitter.js'
import WaterfallFlowItem from './WaterfallFlowItem.vue'
import { throttle } from 'lodash'
import {addResizeListener, removeResizeListener} from './element-ui-utils-resize-event.js'

export default {
  name: 'WaterfallFlow',
  componentName: 'WaterfallFlow',
  mixins: [emitter],
  components: {
    'waterfall-flow-item': WaterfallFlowItem
  },
  props: {
    list: {
      type: Array,
      default () {
        return []
      }
    },
    spaceY: {
      type: Number,
      default () {
        return 0
      }
    },
    selected: {
      type: Array,
      default () {
        return []
      }
    }
  },
  data () {
    return {}
  },
  wrapWidth: 0,
  itemWidth: 0,
  rowNumber: 0,
  interval: 0,
  heightArray: [],
  handleResize: null,
  methods: {
    async changeList () {
      if (this.list.length === 0) {
        return
      }
      if (this.$refs['body']) {
        this.$refs['body'].style.visibility = 'hidden'
      }
      // let loadingInstance = Loading.service({ target: this.$el })

      await this.waitComplete()
      this.init()
      const _items = this.$children.filter((item) => item.$options.componentName === 'WaterfallFlowItem')
      for (let i = 0; i < _items.length; i++) {
        this.itemPosition(_items[i].$el)
      }

      const maxValue = Math.max.apply(null, this.heightArray)

      // loadingInstance.close()
      this.$refs['body'].style.height = maxValue + 'px'
      this.$refs['body'].style.visibility = 'visible'
    },
    init () {
      const _items = this.$children.filter((item) => item.$options.componentName === 'WaterfallFlowItem')

      this.wrapWidth = this.$el.offsetWidth
      this.itemWidth = _items[0].$el.offsetWidth
      this.rowNumber = Math.floor(this.wrapWidth / this.itemWidth) || 1
      this.interval = Math.floor(this.wrapWidth % this.itemWidth / (this.rowNumber - 1))
      this.heightArray = new Array(this.rowNumber).fill(0)
    },
    waitComplete () {
      this.broadcast('WaterfallFlowItem', 'ask-complete')

      return new Promise((resolve, reject) => {
        let count = 0
        this.$on('complete', () => {
          count++
          if (count === this.list.length) {
            this.$off('complete')
            resolve('complete')
          }
        })
      })
    },
    itemPosition (el) {
      const elHeight = el.offsetHeight

      const min = this.minRow()

      let x = this.interval * min.index + this.itemWidth * min.index
      if (min.index === 0) {
        x = 0
      }
      if (min.index === this.rowNumber - 1) {
        x = this.wrapWidth - this.itemWidth
      }

      let y = min.value

      el.style.left = x + 'px'
      el.style.top = y + 'px'

      let _spaceY = this.spaceY || this.interval

      this.heightArray[min.index] = min.value + elHeight + _spaceY
    },
    minRow () {
      const minValue = Math.min.apply(null, this.heightArray)

      const index = this.heightArray.findIndex(val => val === minValue)

      return { value: minValue, index }
    }
  },
  watch: {
    async list (val, old) {
      await this.$nextTick()
      val !== old && this.changeList()
    }
  },
  async mounted () {
    await this.changeList()
    let _w = this.$el.offsetWidth

    this.handleResize = throttle(() => {
      //  console.log('handle resize' _w, this.$el.offsetWidth)
      if (_w === this.$el.offsetWidth) return
      this.changeList()
      _w = this.$el.offsetWidth
    }, 1000)

    addResizeListener(this.$el, this.handleResize)
  },
  destroyed () {
    if (this.$el && this.handleResize) removeResizeListener(this.$el, this.handleResize)
  }
}
</script>
