<template>
  <div ref="layout" class="layout fit no-scroll no-wrap relative-position">
    <slot />
    <!-- v-touch-pan.prevent.mouse.mouseMightPrevent="handlePan" -->
    <div class="mark" v-if="showMoveBar" @mousemove.stop="move" @mouseup.stop="moveUp"></div>
    <div v-if="showMoveBar" class="move-bar" :style="moveBarStyle" @mouseup.stop="moveUp"></div>
    <q-resize-observer @resize="onResize" />
  </div>
</template>
<script>
import _ from 'underscore'
// import { dom } from 'quasar'
// const { offset } = dom

// let ji = 0;
let barSize = 6
let types = 'top,left,center,right,bottom'.split(',')
let typeMins = 't,l,c,r,b'.split(',')
let typeMinMap = {}
typeMins.forEach((item, index) => {
  typeMinMap[item] = types[index]
})

export default {
  name: 'kyb-layout',
  props: {
    type: String,
    confStr: String,
    conf: {
      type: Object,
      default: function() {
        return {}
      }
    },
    items: { type: Array }
  },
  data: function() {
    let confInner = { items: [] }
    if (this.confStr) {
      this.confStr.split(',').forEach((item, index) => {
        if (index === 0 && (item === 'row' || item === 'column')) {
          confInner.type = item
        } else {
          let itemAr = item.split('-')
          confInner.items.push({
            type: typeMinMap[itemAr[0]] || itemAr[0],
            size: parseInt(itemAr[1]),
            resize:
              itemAr.length > 2 && (itemAr[2] === 'true' || itemAr[2] === '1')
          })
        }
        // console.log("confInner", confInner);
      })
    } else {
      confInner = JSON.parse(JSON.stringify(this.conf))
    }

    confInner.type || (confInner.type = 'row')

    if (this.type) {
      confInner.type = this.type
    }
    confInner.items || (confInner.items = [])

    return {
      confInner: confInner,
      itemMap: {},
      centerMap: {},
      showMoveBar: false,
      size: {},
      moveBarStyle: {},
      selectIndex: null
    }
  },
  created: function() {
    // 子对象创建成功后初始化
    this.$on('item-init', msg => {
      // console.log("item is ok: ", msg);
      this.confInner.items.push(msg)
      this.fixData()
      this.reSize()
    })
    this.$on('item-delete', msg => {
      // console.log("item is ok: ", msg);
      let index = this.confInner.items.findIndex(item => item === msg)
      this.confInner.items.splice(index, 1)
      this.fixData()
      this.reSize()
    })
    // 子对象按下开始拖动时的事件
    this.$on('item-bar-mousedown', msg => {
      // console.log('msg.itemConf: ', msg)
      this.startMove(msg)
    })
  },

  methods: {
    itemInit: function(data) {
      // alert(data)
      // console.log("item data: ", data);
    },
    onResize(size) {
      this.size = size
      // console.log('size:', this.size)
      this.reSize()
    },
    fixData: function() {
      types.forEach(type => {
        this.itemMap[type] = []
      })

      this.confInner.items.forEach(v => {
        let item = v.itemConf
        let isLeftOrRight = item.type === 'left' || item.type === 'right'
        // alert(this.confInner.type);
        if (
          (isLeftOrRight && this.confInner.type === 'row') ||
          ((!isLeftOrRight && this.confInner.type === 'column') ||
            item.type === 'center')
        ) {
          if (item.type === 'center') {
            this.itemMap[item.type] = item
          } else {
            item.typeIndex = this.itemMap[item.type].length
            item.posNum =
              item.typeIndex > 0
                ? this.itemMap[item.type][item.typeIndex - 1].posNum +
                  this.itemMap[item.type][item.typeIndex - 1].size
                : 0
            this.itemMap[item.type].push(item)
          }
        }
      })
    },
    reSize: function() {
      // let d = {}
      this.centerMap = { left: 0, right: 0, top: 0, bottom: 0 }
      let center

      this.confInner.items.forEach((v, index) => {
        let element = v.itemConf
        let type = element.type
        // let isTopOrLeft = type === 'left' || type === 'top'
        let isLeftOrRight = type === 'left' || type === 'right'
        if (
          (isLeftOrRight && this.confInner.type === 'column') ||
          (!isLeftOrRight && this.confInner.type === 'row') ||
          type === 'center'
        ) {
          if (type === 'center') center = v
          return
        }
        let point = {
          top: isLeftOrRight ? 0 : 'auto',
          bottom: isLeftOrRight ? 0 : 'auto',
          left: !isLeftOrRight ? 0 : 'auto',
          right: !isLeftOrRight ? 0 : 'auto'
        }
        point[type] = this.centerMap[type]
        this.centerMap[type] += parseInt(element.size)
        point[this.confInner.type === 'row' ? 'width' : 'height'] = element.size
          ? element.size
          : 0
        this.setStyle(element.styleInner, point)
        v.$forceUpdate()
      })
      if (center) {
        this.setStyle(center.itemConf.styleInner, this.centerMap)
        center.$forceUpdate()
      }
      Object.assign(this.itemMap.center, this.centerMap)
      // console.log('size:', this.size.width, this.size.height)
      if (this.size.width) {
        this.itemMap.center.width =
          this.size.width - this.centerMap.left - this.centerMap.right
      }
      if (this.size.height) {
        this.itemMap.center.height =
          this.size.height - this.centerMap.top - this.centerMap.bottom
      }
      // return d;
    },

    setStyle(target, source) {
      let m = {}
      _.each(source, (v, k) => {
        m[k] = v !== 'auto' ? v + 'px' : v
      })
      Object.assign(target, m)
    },
    startMove(event) {
      let type = event.type
      let index = event.typeIndex
      let item = this.itemMap[type][index]
      if (!item.resize) return
      // console.log("------ item", this.itemMap);
      // eslint-disable-next-line no-unused-vars
      let isTopOrLeft = item.type === 'top' || item.type === 'left'
      let isLeftOrRight = item.type === 'left' || item.type === 'right'

      // let size = parseInt(
      //   item.styleInner[isLeftOrRight ? 'width' : 'height'].replace(/px/, '')
      // )
      // let startNum = parseInt(item.styleInner[item.type].replace(/px/, ''))
      this.moveBarStyle = {
        left: 'auto',
        right: 'auto',
        top: 'auto',
        bottom: 'auto'
      }
      this.moveBarStyle.moveNum = item.posNum + item.size - barSize
      this.moveBarStyle[isLeftOrRight ? 'top' : 'left'] = '0px'
      this.moveBarStyle[isLeftOrRight ? 'bottom' : 'right'] = '0px'
      this.moveBarStyle[isLeftOrRight ? 'width' : 'height'] = barSize + 'px'

      // console.log('size:', this.size.width, this.size.height)
      this.selectIndex = index
      this.selectType = item.type
      this.showMoveBar = true
      // this.layoutOffset = offset(this.$refs.layout)

      // eslint-disable-next-line no-unused-vars
      if (index === this.itemMap[type].length - 1) {
        this.minSize = item.posNum
        this.maxSize =
          (isLeftOrRight
            ? this.itemMap.center.width
            : this.itemMap.center.height) + this.itemMap.center[item.type]
      } else {
        let nextObj = this.itemMap[type][index + 1]
        this.minSize = item.posNum
        this.maxSize =
          nextObj.posNum + nextObj.size - (nextObj.resize ? barSize : 0)
      }
      // if (!isTopOrLeft) {
      //   this.maxSize -= barSize
      // }
      this.maxSize -= barSize

      this.moveBarStyle[item.type] = this.moveBarStyle.moveNum + 'px'
      // console.log('maxSize:', item.type, this.moveBarStyle.moveNum)
      this.mouseStart = event.mouseStart
      // this.$set(this.moveBarStyle, "display", "block");
      // console.log("kkkk", this.selectIndex, this.selectType);
    },
    move($event) {
      let isTopOrLeft = this.selectType === 'top' || this.selectType === 'left'
      let t =
        this.selectType === 'left' || this.selectType === 'right'
          ? 'clientX'
          : 'clientY'
      this.moveEndSize = (this.mouseStart - $event[t]) * (isTopOrLeft ? -1 : 1)
      let moveEnd = this.moveBarStyle.moveNum + this.moveEndSize
      moveEnd = moveEnd > this.maxSize ? this.maxSize : moveEnd
      moveEnd = moveEnd < this.minSize ? this.minSize : moveEnd
      this.moveEndSize = moveEnd - this.moveBarStyle.moveNum

      this.moveBarStyle[this.selectType] = moveEnd + 'px'

      this.$forceUpdate()
    },
    moveUp($event) {
      if (!this.showMoveBar) return
      this.showMoveBar = false
      if (!this.moveEndSize && this.moveEndSize !== 0) return
      let typeList = this.itemMap[this.selectType]
      let obj = typeList[this.selectIndex]
      obj.size += this.moveEndSize
      obj.size = obj.size < 0 ? 0 : obj.size
      if (this.selectIndex < typeList.length - 1) {
        let next = typeList[this.selectIndex + 1]
        next.size -= this.moveEndSize
        next.size = next.size < 0 ? 0 : next.size
      }
      this.fixData()
      this.reSize()
      delete this.moveEndSize
    }
  }
}
</script>
<style lang="stylus">
.layout>.layout-item, .layout>.resize-line, .layout>.move-bar, .layout>.center, .layout>.mark {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.layout>.mark {
  background: $grey-6;
  opacity: 0.2;
}

.resize-line {
  background: $grey-6;
}

.move-bar {
  background: $primary;
  opacity: 0.5;
}

.resize-line:hover {
  background: $grey-8;
}

.layout.auto-content > .layout-item {
  position: static;
}
</style>
