<template>
  <div id="main" class="h-all">
    <el-container class="page-main adapt-height-box h-all">

      <!-- 顶部菜单栏 -->
      <el-header height="auto">
        <el-row type="flex" justify="space-between" style="margin-bottom: 3px;">
          <el-col :span="7" style="text-align:left;">
            <label>{{ $t('TopologicalGraphShow.discoveryTitle') }}:</label>
            <el-select v-model="selectedTemplateKey" size="mini" clearable :placeholder="$t('common.selectOption')">
              <el-option
                v-for="item in templateList"
                :key="item.discoveryTemplateKey"
                :label="item.discoveryTemplateName"
                :value="item.discoveryTemplateKey">
              </el-option>
            </el-select>
            <el-button icon="el-icon-search" size='mini' type="primary" @click="discover">{{ $t('TopologicalGraphShow.discover') }}</el-button>
          </el-col>
          <el-col :span="17" style="text-align:left; padding-right:30px;">
            <el-progress v-if="isDiscovering" :text-inside="true" :stroke-width="22" :percentage="discoverPercent" :status="discoverDone?'success':null"></el-progress>
<!--            <el-button v-if="canSaveTopology" icon="el-icon-upload" size='mini' type="primary" @click="saveTopology">{{ $t('TopologicalGraphShow.saveTopology') }}</el-button>-->
          </el-col>
        </el-row>
      </el-header>

      <!-- 拓扑图和发现列表区域 -->
      <div id="ContentBox" class="adapt-height adapt-height-box">

        <!-- 拓扑图 -->
        <div id="EleDiscTopo" >
          <ElementDiscoveryTopology
            ref="ElementDiscoveryTopology"
            class="adapt-height h-all"
            style="margin:0; padding:0; overflow: hidden;"
            :drawGraphSizeConfig="drawGraphSizeConfig"
            :discoveryCollection="discoveryCollection"
            :selectDevicesList="selectDevicesList"
            :selectLinksList="selectLinksList"
            @updateSelectList="updateSelectList"
          ></ElementDiscoveryTopology>
        </div>

        <!-- 拓扑图和表格间的调整控件 -->
        <div id="Resizer" @mousedown="dragControllerDiv"></div>

        <!-- 发现网元 & 发现链路 -->
        <div id="DiscoverElementAndLink" class="adapt-height">
          <el-footer style="margin: 0px;padding: 0px;" width="auto" height="100%">
            <DiscoverDisplay
              :discoveryCollection="discoveryCollection"
              :selectDevicesList="selectDevicesList"
              :selectLinksList="selectLinksList"
            ></DiscoverDisplay>
          </el-footer>
        </div>

      </div>

    </el-container>

    <CommandExecuteContext v-bind:commands="commandContext"></CommandExecuteContext>
  </div>
</template>

<script>
import CommandExecuteContext from '../../commands/CommandExecuteContext'
import ElementDiscoveryTopology from './ElementDiscoveryTopology'
import DiscoverDisplay from './DiscoverDisplay'
import EdTemplateService from '../../domain/services/Template/EdTemplateService'
import { EventBus } from '../../domain/EventBus'
import HelperUtil from '../../utils/HelperUtil'
import ElementDiscoverService from '../../domain/services/ElementDiscoverService'
import DeviceCommands from '@/commands/DeviceCommands'
import DeviceService from '@/domain/services/DeviceService.js'
import LinkService from '@/domain/services/LinkService'
import PortService from '@/domain/services/PortListService.js'

export default {
  name: 'ElementDiscoveryManagement',

  // 引用的组件
  components: {
    CommandExecuteContext,
    ElementDiscoveryTopology, // 拓扑图显示组件
    DiscoverDisplay // 底部网元发现表格组件
  },

  // 接收顶层组件的传参
  props: {
    discoveryCollection: Object
  },

  // 本组件数据
  data () {
    return {
      loadingInstance: null,
      commandContext: {},
      templateList: null, // 网元发现模板列表
      templateLoading: false, // 下拉框是否显示加载中
      selectedTemplateKey: null, // 已选择的网元发现模板的 key
      drawGraphSizeConfig: {
        svgWidth: '100%',
        svgHeight: '100%',
        imageWidth: 32,
        imageHeight: 32,
        textSize: 14
      },
      selectDevicesList: [], // 选择的多个设备
      selectLinksList: [], // 选择的多个链路

      deleteList: [],
      // 级联删除链路
      linkList: [],
      // 级联删除接入业务portList
      portList: [],
      deviceList: []
    }
  },
  created () {
    this.getTemplateList1()
  },

  computed: {
    deleteCommand () {
      return DeviceCommands.deleteDeviceCommand(this.deleteList, this.commandContext)
    },

    // 网元发现返回对象中的进度百分比
    discoverPercent () {
      return this.discoveryCollection === null ? 0 : this.discoveryCollection.findPercent
    },
    // 网元发现是否完成
    discoverDone () {
      return this.discoveryCollection === null ? false : this.discoveryCollection.checkFindIsEnd
    },
    // 是否正在发现中
    isDiscovering () {
      return !(this.discoverDone || this.discoveryCollection === null)
    },
    // 是否显示保存拓扑按钮
    canSaveTopology () {
      return !this.isDiscovering && (this.selectDevicesList.length > 0 || this.selectLinksList.length > 0)
    },
    // 新发现的网元集合，key为deviceKey，value为device对象
    discoveredDeviceMap () {
      if (this.discoveryCollection === null) return {}
      return HelperUtil.arrayToObject(this.discoveryCollection.devicesNew, 'deviceKey')
    },
    // 新发现的链路集合，key为linkKey，value为link对象
    discoveredLinkMap () {
      if (this.discoveryCollection === null) return {}
      return HelperUtil.arrayToObject(this.discoveryCollection.linksNew, 'linkKey')
    },
    // 与已有网元IP存在冲突的新发现网元集合
    ipConflictDevicesMap () {
      if (this.discoveryCollection === null) return {}
      const devicesMap = {}
      const {devicesInDb, devicesNew} = this.discoveryCollection
      const existingDevicesIpMap = new Map(devicesInDb.map(e => [e.ipAddress, e]))
      devicesNew.forEach(device => {
        if (existingDevicesIpMap.has(device.ipAddress)) {
          devicesMap[device.deviceKey] = {
            displayName: device.displayName,
            targetDevice: existingDevicesIpMap.get(device.ipAddress)
          }
        }
      })
      return devicesMap
    }
  },

  methods: {
    /**
     * @description 上下拖动改变控制器div大小
     * @author weixin
     * @date 2020/7/27
     */
    dragControllerDiv ({clientY: startY}) {
      const svgBox = document.getElementById('ContentBox')
      const svgTop = document.getElementById('EleDiscTopo')
      const svgResize = document.getElementById('Resizer')
      const svgDown = document.getElementById('DiscoverElementAndLink')

      svgResize.top = svgResize.offsetTop
      svgBox.onmousemove = function ({clientY: endY}) {
        let moveLen = svgResize.top + (endY - startY)
        const maxT = svgBox.clientHeight - svgResize.offsetHeight
        if (moveLen < 50) moveLen = 50
        if (moveLen > maxT - 50) moveLen = maxT - 50
        svgResize.style.top = moveLen
        svgTop.style.height = `${moveLen}px`
        svgDown.style.height = `${svgBox.clientHeight - moveLen - 5}px`
      }
      svgBox.onmouseup = function (e) {
        svgBox.onmousemove = null
        svgBox.onmouseup = null
      }
    },

    /**
     * @description 获取所有网元发现模板
     * @author weixin
     * @date 2020/7/14 15:18
     * @param 下拉框出现为true，隐藏为false
     */
    getTemplateList (state) {
      if (state === false || this.templateList !== null) return
      // 当展开下拉框且 templateList 为 null 时，从服务器读取模板数据
      this.templateLoading = true
      EdTemplateService.getAllTemplateCollection().then(result => {
        this.templateList = Object.values(result)
      }).catch(err => {
        this.InfoTip.errorTip(this, err)
      }).finally(() => {
        this.templateLoading = false
      })
    },

    /**
     * @Description  : getAllTemplateList1
     * @author       : ls
     * @date         : 2020/12/4 11:12
     * @param        :
     * @return       :
     */
    getTemplateList1 () {
      EdTemplateService.getAllTemplateCollection().then(result => {
        this.templateList = Object.values(result)
      }).catch(err => {
        this.InfoTip.errorTip(this, err)
      })
    },

    /**
     * @description 点击发现按钮进行网元发现
     * @author weixin
     * @date 2020/7/14 23:15
     */
    async discover () {
      // 如果未选择网元发现模板，则提示选择一个网元发现模板
      if (this.selectedTemplateKey === null) {
        this.InfoTip.warningTip(this, HelperUtil.getCheckStatusCodeObjectByCode(this.successCode.DISCOVER_ELEMENT_CODE))
        return
      }
      this.discoveryCollection = null
      // 清空已选网元及链路集合
      this.selectDevicesList = []
      this.selectLinksList = []
      this.loadingInstance = this.Loading.openLoading()
      // 用已选择的网元发现模板执行网元发现，将获取的数据存到discoveryCollection，以传给DiscoverDisplay组件
      // this._fakeWebsocket(this.selectedTemplateKey)
      // 用真正的接口
      const result = await ElementDiscoverService.getSpeedAndProgressMessage(this.selectedTemplateKey)
      if (result === true) {

      }
    },

    /**
     * （模拟接口）将模板key发送给后台通过websocket获取网元发现的数据
     */
    _fakeWebsocket (templateKey) {
      EventBus.$emit('fake-discovery', templateKey)
    },

    /**
     * @description 更新selectDevicesSet或selectLinksSet的值
     * @param {string} which 指定是'device'还是'link'
     * @param {List} newVal 更新的List
     * @author weixi
     * @date 2020/08/19
     */
    updateSelectList (which, newVal) {
      if (which === 'device') this.selectDevicesList = newVal
      else if (which === 'link') this.selectLinksList = newVal
    },

    /**
     * @description 保存拓扑图
     * @author weixin
     * @date 2020/08/26
     */
    async saveTopology () {
      // 获取与已有网元IP冲突的新发现的网元集合
      const conflictDevices = this._getConflictDevices()
      // 如果有冲突网元，则询问是否要替换
      if (conflictDevices.length > 0) {
        const isReplaced = await this._whetherReplaceDevices(conflictDevices)
        if (!isReplaced) return
      }
      // 保存拓扑图
      await this.InfoTip.conformTip(this, HelperUtil.getCheckStatusCodeObjectByCode(this.successCode.SAVE_TOPOLOGY))
        .then(() => this.addDevicesAndLinks())
        .catch(err => console.log('取消保存拓扑图'))
    },
    // 从已选的网元中找出IP冲突的网元
    _getConflictDevices () {
      const conflictDevicesList = []
      this.selectDevicesList.forEach(deviceKey => {
        if (Reflect.has(this.ipConflictDevicesMap, deviceKey)) conflictDevicesList.push(this.ipConflictDevicesMap[deviceKey])
      })
      return conflictDevicesList
    },
    // 询问是否替换网元
    async _whetherReplaceDevices (devicesList) {
      // 冲突的新发现的网元名称列表
      const displayNamesList = devicesList.map(device => device.displayName)
      // 用顿号组合成字符串
      const displayNameStr = displayNamesList.join('、')
      const dialogContainObject = {
        message: `${displayNameStr} ${HelperUtil.getCheckStatusCodeObjectByCode(this.successCode.ELEMENT_REPLACE_CODE).message}`
      }
      let isReplaced = false
      await this.InfoTip.conformTip(this, dialogContainObject)
        .then(() => {
          this.replaceConflictDevices(devicesList)
          isReplaced = true
        })
        .catch(err => console.log('放弃替换冲突网元'))
      return isReplaced
    },

    /**
     * @description 替换IP冲突的网元们
     * @param {Array} devicesList 冲突的网元集合
     * @author weixin
     * @date 2020/08/27
     */
    replaceConflictDevices (devicesList) {
      console.log('开始替换')
      // 需要被替换的网元
      const targetDevicesList = devicesList.map(device => device.targetDevice)
      console.log(targetDevicesList)
      // websocket空位
      this.deleteList = targetDevicesList
      this.deleteDevicePro()
      console.log('调用删除网元的接口，将targetDevicesList传过去')
    },

    /** 删除网元
     *
     *
     */
    // 删除设备
    deleteDevicePro () {
      let _this = this
      let loadingInstance = _this.Loading.openLoading()
      DeviceService.batchDeleteDevice(this.deleteList).then(result => {
        // _this.Loading.closeLoading(loadingInstance);
        // _this.InfoTip.successTip(_this, HelperUtil.getStatusCodeObjectByCode(_this.successCode.DELETE_CODE));
        // _this.close();
      }).catch(err => {
        _this.Loading.closeLoading(loadingInstance)
        _this.InfoTip.errorTip(_this, err)
        _this.close()
      })
    },

    /**
     * @Description  ：获取全部link信息
     * @author       :
     * @param        :
     * @return       :
     * @exception    :
     * @date         :
     */
    getAllLinkInit: function (mutation = () => {}) {
      let _this = this

      LinkService.getAllLinkCollection().then(result => {
        // 成功
        _this.linkList = Object.values(result)
        mutation()
      }).catch(err => {
        _this.InfoTip.errorTip(_this, err)
      })
    },

    /**
     * @Description  ：获取全部port信息
     * @author       :
     * @param        :
     * @return       :
     * @exception    :
     * @date         :
     */
    getAllPort: function (mutator = () => {}) {
      let _this = this
      PortService.getAllPortList().then(result => {
        _this.portList = Object.values(result)
        mutator()
      }).catch(err => {
        _this.InfoTip.errorTip(_this, err)
      })
    },

    getAllDevice: function (mutator = () => {}) {
      let _this = this
      DeviceService.getAllDeviceCollection().then(result => {
        _this.deviceList = result
        mutator()
      }).catch(err => {
        _this.InfoTip.errorTip(_this, err)
      })
    },

    /**
     * @description 先把选中的设备添加到后台，结束后再把选中的链路添加到后台
     * @author weixin
     * @date 2020/08/27
     */
    addDevicesAndLinks () {
      console.log('开始添加设备和链路')
      const websocketAddDevicesApi = (elementList) => {
        console.log('websocket接口，传入了', elementList)
      }
      const websocketAddLinksApi = (elementList) => {
        console.log('websocket接口，传入了', elementList)
      }
      // 先添加设备们，websocketAddDevicesApi为添加设备的接口空位
      DeviceService.batchAddDevice(this.selectDevicesList).then(result => {
        // 添加成功

      }).catch(err => {
        // 添加失败

      })
      this._addElement(this.discoveredDeviceMap, this.selectDevicesList, websocketAddDevicesApi)
      // 再添加链路们，websocketAddLinksApi为添加链路的接口空位
      LinkService.addLink(this.selectLinksList).then(result => {
        // 成功

      }).catch(err => {
        // 失败

        //            this.close();
      })
      this._addElement(this.discoveredLinkMap, this.selectLinksList, websocketAddLinksApi)
    },
    _addElement (elementMap, selectList, websocketApi) {
      // 选择的物品中把属于新发现的物品放进来，老的不用再添加了（如果他选择了老物品的话）
      const elementList = []
      selectList.forEach(elementKey => {
        if (Reflect.has(elementMap, elementKey)) {
          const element = elementMap[elementKey]
          elementList.push(element)
        }
      })
      // websocket接口，将elementList传参进去
      // this.deleteDevice()
      websocketApi(elementList)
    }

    // deleteDevice() {
    //   let _this = this;
    //   let loadingInstance = _this.Loading.openLoading();
    //   _this.getAllLinkInit(() =>{
    //     _this.getAllPort(() =>{
    //       _this.getAllDevice(() =>{
    //         DeviceService.deleteDeviceAndLinks(_this.deleteList,_this.deviceList,_this.linkList,_this.portList).then(result =>{
    //           _this.Loading.closeLoading(loadingInstance);
    //           _this.InfoTip.successTip(_this, HelperUtil.getStatusCodeObjectByCode(_this.successCode.DELETE_CODE));
    //           _this.close();
    //         }).catch(err =>{
    //           //   console.log("删除失败");
    //           _this.Loading.closeLoading(loadingInstance);
    //           _this.InfoTip.errorTip(_this,err);
    //           _this.close();
    //         });
    //       });
    //     });
    //   });
    // },
  },
  watch: {
    discoverDone (val) {
      if (val) this.Loading.closeLoading(this.loadingInstance)
    }
  },
  beforeDestroy () {
    this.discoveryCollection = null
  }
}
</script>

<style scoped>
/* 外层布局容器样式 */
.el-footer {
  background-color: #f9fafc;
  color: #333;
}
/* D3控件样式 */
#ContentBox{
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}
#EleDiscTopo {
  height: calc(70% - 5px);
  width: 100%;
  float: left;
  overflow: hidden;
}
#Resizer {
  position: relative;
  height: 5px;
  width: 100%;
  cursor: s-resize;
  float: left;
}
#DiscoverElementAndLink {
  height: 30%;
  width: 100%;
  float: left;
  overflow: hidden;
}
</style>
