<template>
  <div>
    <page-header content="机柜编辑"></page-header>
    <div class="cabinet-page-container">
      <div class="log-container" :style="{height:cabinetHeight+'px'}">
        <el-form inline label-width="54px">
          <el-form-item label="搜索">
            <el-input v-model.trim="listQuery.content" clearable maxlength="16" placeholder="请输入内容关键字" @keyup.enter.native="getCabinetLogList">
              <i slot="suffix" class="el-input__icon el-icon-search" @click="getCabinetLogList"></i>
            </el-input>
          </el-form-item>
        </el-form>
        <div class="w100p border-bottom pl10 pr10 h50 flex-col justify-center " v-for="(log,index) in logList" :key="index">
          <div class="flex align-center justify-between">
            <div class="log-time">{{ log.createTime | dateFormat }}</div>
            <div class="log-username">{{ log.operateUsername }}</div>
          </div>
          <div class="log-content mt5">{{ log.content }}</div>
        </div>
        <pagination small :total="logTotal" :page.sync="listQuery.page" :size.sync="listQuery.size" @change="getCabinetLogList"/>
      </div>

      <div class="cabinet-container">
        <img src="./assets/cabinet-top.png" class="cabinet-top-icon"/>
        <div class="cabinet-middle-container">
          <div class="cabinet-ruler-container" :style="{height:cabinetHeight+'px'}">
            <div class="cabinet-number-container">
              <div class="cabinet-number" v-for="item in Math.floor(deviceCount/5)+1">{{ deviceCount - (item - 1) * 5 }}U</div>
            </div>
            <div class="cabinet-scale-body"></div>
            <div class="cabinet-scale-container">
              <div class="cabinet-scale" v-for="index in deviceCount+1" :key="index"></div>
            </div>
          </div>
          <draggable class="cabinet-body"
                     :style="{height:cabinetHeight+'px'}"
                     ref="cabinet-body"
                     chosenClass="device-container-chosen"
                     :value="cabinetDeviceList"
                     :ghostClass="moveInCabinet?'':'device-container-ghost'"
                     delay="0"
                     :forceFallback="true"
                     group="cabinet"
                     animation="0"
                     @start="onStart1"
                     @choose="onChoose1"
                     :move="onMove1"
                     @end="onEnd1">
            <div class="device-container" v-for="(device, index) in cabinetDeviceList" :key="index" :style="{
                  'line-height': (device.layerCount * (deviceHeight + deviceSpace) - deviceSpace) + 'px',
                  'height': (device.layerCount * (deviceHeight + deviceSpace) - deviceSpace) + 'px',
                  'position': 'absolute',
                  'top':(device.top + 10) + 'px'
              }">
              <img src="./assets/device-icon.png" class="device-icon"/>
              <div class="device-name">{{ device.name }}</div>
              <img src="./assets/device-icon2.png" class="device-icon2"/>
            </div>
          </draggable>
        </div>
        <img src="./assets/cabinet-bottom.png" class="cabinet-bottom-icon"/>
      </div>

      <div class="option-container" :style="{'margin-top':scrollY+'px'}">
        <div class="device-container device-add-container" @click="onAddDefault">
          <img src="./assets/device-icon.png" class="device-icon"/>
          <div class="device-name">新增设备模板</div>
          <img src="./assets/device-icon2.png" class="device-icon2"/>
        </div>

        <draggable class="default-cabinet-container"
                   :value="defaultDeviceList"
                   chosenClass="device-container-chosen"
                   delay="0"
                   :forceFallback="true"
                   :options="{group:{name: 'cabinet',pull:'clone'},sort: false}"
                   animation="0"
                   @start="onStart2"
                   :move="onMove2"
                   @end="onEnd2">
          <div class="device-container" v-for="device in defaultDeviceList" :key="device.id" @dblclick="onEditDefault(device)" :style="{
              'line-height': (device.layerCount * (deviceHeight + deviceSpace) - deviceSpace) + 'px',
              'height': (device.layerCount * (deviceHeight + deviceSpace) - deviceSpace) + 'px',
            }">
            <img src="./assets/device-icon.png" class="device-icon"/>
            <div class="device-name">{{ device.name }}</div>
            <img src="./assets/device-icon2.png" class="device-icon2"/>
          </div>
        </draggable>
      </div>
    </div>

    <dialog-edit v-if="editDialogVisible" :visible.sync="editDialogVisible" :data="selectItem" :type="selectType" @add="getDefaultDeviceList" @update="getDefaultDeviceList" @delete="getDefaultDeviceList" @confirm="addDeviceConfirm"/>
  </div>
</template>

<script>
import draggable from 'vuedraggable'
import dialogEdit from './dialog-edit'

export default {
  name: 'DeviceDeviceCabinet',
  components: {
    draggable, dialogEdit
  },
  data() {
    return {
      // 注意同时修改scss中的样式变量
      // cabinetHeight = deviceCount * (deviceHeight + deviceSpace) - deviceSpace + 20padding + 8border;
      cabinetHeight: 1201, // 机柜高度
      deviceCount: 56, // 机柜放设备总数
      deviceHeight: 18, // 设备高度
      deviceSpace: 3, // 设备间隙

      moveDevice: undefined,// 准备添加的设备
      offsetY: 0, // 记录鼠标点击时相对设备顶部的起始偏移量
      scrollY: 0, // 记录Y轴滚动位置

      cabinetBodyOffset: {  // 机柜位置
        width: 0, // 机柜宽度
        height: 0, // 机柜高度
        left: 0, // 机柜与窗口左侧实时距离
        top: 0, // 机柜与窗口顶部实时距离
        originalTop: 0, // 机柜与窗口顶部初始距离
      },
      moveInCabinet: false, // 是否在机柜内移动

      cabinetId: undefined,// 机柜id
      cabinetDeviceList: [], // 机柜中的设备列表

      defaultDeviceList: [], // 可选择的设备列表

      editDialogVisible: false, // 编辑对话框是否可见
      selectItem: undefined, // 选中的单条记录
      selectType: 1, // 对话框类型 1:默认设备  2:机柜中的设备

      listQuery: { // 查询对象
        page: 1,
        size: 23
      },
      logList: [], // 结果列表
      logTotal: 0, // 总结果数量
    }
  },

  watch: {
    "$store.state.app.sidebar.opened"() {
      setTimeout(() => this.calcCabinetBodyRect(), 300); // 菜单栏收缩动画有300ms
    }
  },

  mounted() {
    if (this.$route.query.id) {
      this.listQuery.cabinetId = Number(this.$route.query.id);
      this.deviceCount = Number(this.$route.query.layerCount);
      this.cabinetHeight = this.deviceCount * (this.deviceHeight + this.deviceSpace) - this.deviceSpace + 20 + 8;
      this.listQuery.size = Math.floor((this.cabinetHeight - 110) / 50);
      this.calcCabinetBodyRect();
      window.addEventListener('resize', this.calcCabinetBodyRect);
      window.addEventListener('scroll', this.calcCabinetBodyRect);
      this.getDefaultDeviceList();
      this.getCabinetDeviceList();
      this.getCabinetLogList();
    } else {
      this.$router.back();
    }
  },

  destroyed() {
    window.removeEventListener('resize', this.calcCabinetBodyRect);
    window.removeEventListener('scroll', this.calcCabinetBodyRect);
    this.$eventBus.$emit("DeviceCabinetUpdate");
  },

  methods: {
    // 计算机柜尺寸位置
    calcCabinetBodyRect() {
      const rect = this.$refs['cabinet-body'].$el.getBoundingClientRect();
      this.cabinetBodyOffset.width = rect.width;
      this.cabinetBodyOffset.height = rect.height;
      this.cabinetBodyOffset.left = rect.x;
      this.cabinetBodyOffset.top = rect.y;
      this.cabinetBodyOffset.originalTop = this.cabinetBodyOffset.originalTop === 0 ? rect.y : this.cabinetBodyOffset.originalTop;
      this.scrollY = this.cabinetBodyOffset.originalTop - this.cabinetBodyOffset.top;
      this.$forceUpdate();
    },

    // 显示添加默认设备弹窗
    onAddDefault() {
      this.selectType = 1;
      this.selectItem = undefined;
      this.editDialogVisible = true;
    },

    // 显示添加默认设备弹窗
    onEditDefault(item) {
      this.selectType = 1;
      this.selectItem = item;
      this.editDialogVisible = true;
    },

    // 获取默认设备列表
    getDefaultDeviceList() {
      this.$axios.get("/v1/device/template/list", {params: {size: 99, order: "+id"}}).then(data => {
        this.defaultDeviceList = data.list.map(item => {
          item.top = 0;
          return item;
        })
      })
    },

    // 显示添加设备确认对话框
    showAddDeviceConfirmDialog(item) {
      item.cabinetId = this.listQuery.cabinetId;
      this.selectType = 2;
      this.selectItem = item;
      this.editDialogVisible = true;
    },

    // 获取机柜中的设备
    getCabinetDeviceList() {
      this.$axios.get('/v1/device/cabinet/child/device/list', {params: {cabinetId: this.listQuery.cabinetId, size: 99}}).then(data => {
        this.cabinetDeviceList = data.list;
      });
    },

    // 修改机柜中的设备信息
    updateCabinetDevice(device) {
      this.$axios.put('/v1/device/cabinet/child/device/update', device).then(() => {
      });
    },

    // 确认添加设备
    addDeviceConfirm(device) {
      this.getCabinetLogList();
      this.cabinetDeviceList.push(device);
    },

    // 获取机柜日志
    getCabinetLogList() {
      // 缓存参数
      if (this.$store.state.app.paramCache) {
        this.$storage.setData(this.$options.name, this.listQuery);
      }

      this.$axios.get('/v1/device/cabinet/log/list', {params: this.listQuery}).then(data => {
        this.logList = data.list;
        this.logTotal = data.total;
      });
    },

    onChoose1(e) {
      console.log('onChoose1', e)
      this.moveInCabinet = true
      this.offsetY = e.originalEvent.offsetY
    },

    onStart1(e) {
      console.log('onStart1', e)
    },

    onMove1(e) {
      return e.relatedContext.component.$el.className !== 'default-cabinet-container'
    },

    onEnd1(e) {
      console.log('onEnd1', e)
      if (this.isInRect(e.originalEvent.clientX, e.originalEvent.clientY)) {
        let device = {...this.cabinetDeviceList[e.oldIndex]}
        let oldDevice = this.cabinetDeviceList.splice(e.oldIndex, 1)[0]
        if (!this.calcTopAndCheckCover(device, e.originalEvent.clientY - this.offsetY - this.cabinetBodyOffset.originalTop)) {
          this.cabinetDeviceList.push(device)
          this.updateCabinetDevice(device);
        } else {
          this.cabinetDeviceList.push(oldDevice)
          this.$message('无法放置')
        }
        // this.autoSort()
      } else {
        this.$confirm('此操作将永久删除该设备, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.$axios.delete(`/v1/device/cabinet/child/device/delete/${this.cabinetDeviceList[e.oldIndex].id}`).then(data => {
            this.cabinetDeviceList.splice(e.oldIndex, 1);
            this.getCabinetLogList();
          });
        }).catch(() => {
        });
      }
    },

    onStart2(e) {
      console.log('onStart2', e)
      this.moveInCabinet = false
      this.offsetY = e.originalEvent.offsetY
    },

    onMove2(e, originalEvent) {
      return true
    },

    onEnd2(e) {
      console.log('onEnd2', e.originalEvent.clientY)
      if (this.isInRect(e.originalEvent.clientX, e.originalEvent.clientY + this.scrollY)) {
        let device = {...this.defaultDeviceList[e.oldIndex]}
        if (!this.calcTopAndCheckCover(device, e.originalEvent.clientY + this.scrollY - this.offsetY - this.cabinetBodyOffset.originalTop)) {
          this.showAddDeviceConfirmDialog(device);
        } else {
          this.$message('无法放置')
        }

        // this.autoSort()
      }
    },

    calcTopAndCheckCover(device, top) {
      // 计算当前设备的上下边位置
      device.top = top < 0 ? 0 : Math.floor(top / (this.deviceHeight + this.deviceSpace)) * (this.deviceHeight + this.deviceSpace)
      device.bottom = device.top + device.layerCount * (this.deviceHeight + this.deviceSpace) - this.deviceSpace
      // 下边界超出
      if (device.bottom > this.cabinetHeight - 20) { // padding 20
        return true
      }

      // 上边界在已有对象内、下边界在已有对象内、上下边界在已有对象内、上下边界将已有对象包裹
      if (this.cabinetDeviceList.findIndex(item => device.top >= item.top && device.top <= item.bottom
          || device.bottom >= item.top && device.bottom <= item.bottom
          || item.top >= device.top && item.bottom <= device.bottom
          || item.bottom >= device.top && item.bottom <= device.bottom) < 0) {
        return false
      }

      // 如果当前行无法放入，则尝试放入下一行
      device.top += this.deviceHeight + this.deviceSpace
      device.bottom += this.deviceHeight + this.deviceSpace

      // 下边界超出
      if (device.bottom > this.cabinetHeight - 20) { // padding 20
        return true
      }

      // 上边界在已有对象内、下边界在已有对象内、上下边界在已有对象内、上下边界将已有对象包裹
      return this.cabinetDeviceList.findIndex(item => device.top >= item.top && device.top <= item.bottom
          || device.bottom >= item.top && device.bottom <= item.bottom
          || item.top >= device.top && item.bottom <= device.bottom
          || item.bottom >= device.top && item.bottom <= device.bottom) >= 0;
    },

    autoSort() {
      let sum = 0
      this.cabinetDeviceList.sort((a, b) => a.top - b.top)
      this.cabinetDeviceList.forEach((device, index) => {
        device.top = sum
        sum += device.layerCount * (this.deviceHeight + this.deviceSpace)
      })
    },

    isInRect(x, y) {
      return (x > this.cabinetBodyOffset.left && x < this.cabinetBodyOffset.left + this.cabinetBodyOffset.width
          && y > this.cabinetBodyOffset.top + this.scrollY && y < this.cabinetBodyOffset.top + this.scrollY + this.cabinetBodyOffset.height)
    }
  }
}
</script>

<style scoped lang="scss">

// 机柜高度
$cabinet-height: 1201px;
// 机柜宽度
$cabinet-width: 315px;
// 机柜左边距
$cabinet-margin-left: 70px;
// 机柜右边距
$cabinet-margin-right: 50px;
// 层高
$layer-height: 18px;
// 层间距
$layer-space: 3px;
// 设备宽度
$device-width: 287px;

.cabinet-page-container {
  display: flex;
  justify-content: center;

  //div {
  //  box-sizing: border-box;
  //}

  .log-container {
    width: $device-width;
    border: 1px solid #777777;
    height: $cabinet-height;
    margin-right: $cabinet-margin-right;
    font-size: 12px;
    padding-top: 5px;

    .log-time {
      color: #ff9264;
    }

    .log-username {
      color: #777777;
    }

    .log-content {
      color: #333333;
    }
  }

  .cabinet-container {
    display: flex;
    flex-direction: column;
    margin-right: $cabinet-margin-right;

    .cabinet-top-icon {
      width: 315px;
      height: 7px;
      margin-left: 128px;
    }

    .cabinet-middle-container {
      display: flex;

      .cabinet-ruler-container {
        height: $cabinet-height;
        display: flex;
        padding: 12px 0;

        .cabinet-number-container {
          display: flex;
          flex-direction: column;
          justify-content: space-between;
          align-items: flex-end;
          margin-right: 20px;
          //height: calc(100% + 10px);
          //margin-top: -5px;
          //margin-bottom: -5px;
          height: calc(100% - 10px);
          margin-top: 5px;
          margin-bottom: 5px;

          .cabinet-number {
            font-size: 12px;
            //font-family: Microsoft YaHei-3970(82674968);
            font-weight: 400;
            color: #1A202B;
          }
        }

        .cabinet-scale-body {
          height: 100%;
          width: 2px;
          background: #939393;
        }

        .cabinet-scale-container {
          height: 100%;
          display: flex;
          flex-direction: column;
          justify-content: space-between;

          .cabinet-scale {
            width: 11px;
            height: 2px;
            background: #939393;
          }
        }
      }

      .cabinet-body {
        margin-left: $cabinet-margin-left;
        width: $cabinet-width;
        height: $cabinet-height;
        border: 4px solid #6788F6;
        padding: 10px;
        position: relative;

        span {
          display: inline-block;
          width: 100%;
          height: 100%;
        }
      }
    }

    .cabinet-bottom-icon {
      width: 264px;
      height: 13px;
      margin-left: 151px;
    }
  }

  // 右侧选项容器
  .option-container {
    display: flex;
    flex-direction: column;

    // 新增服务器按钮
    .device-add-container {
      display: flex;
      align-items: center;
      justify-content: space-between;
      height: calc(2 * #{$layer-height + $layer-space} - #{$layer-space});
      line-height: calc(2 * #{$layer-height + $layer-space} - #{$layer-space});
      width: $device-width;
      border: 1px solid #6788F6;
      padding: 0 17px 0 6px;
      margin-bottom: 30px;
      cursor: pointer;
    }
  }

  // 默认设备容器
  .default-cabinet-container {
    display: flex;
    flex-direction: column;
    padding-top: 20px;
  }

  // 机柜中的设备
  .device-container {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: $device-width;
    border: 1px solid #6788F6;
    padding: 0 17px 0 6px;
    margin-bottom: $layer-space;
    cursor: move;


    .device-icon {
      width: 19px;
      height: 10px;
    }

    .device-name {
      font-size: 12px;
      //font-family: Microsoft YaHei-3970(82674968);
      font-weight: 400;
      color: #1A202B;
    }

    .device-icon2 {
      width: 20px;
      height: 8px;
    }
  }

  /*选中样式*/
  .device-container-chosen {
    border: solid 2px #3089dc !important;
  }

  .device-container-ghost {
    display: none !important;
  }
}
</style>
