<template>
  <el-dialog v-dialogDrag
             style="font-size: 10px;"
             :width='devicePanelDialogWidth'
             :title="devicePanelDialogName"
             :visible.sync="devicePanelDialogShow"
             @close="close"
             @opened="devicePanelDialogInit">
    <el-row :gutter="8">
      <el-col :span="6" style="padding-top: 3px; float: left">
        <div><label style="font-size: 10px; float: left">{{$t('devicePanel.deviceName') + "：" + device.displayName}}</label></div>
      </el-col>
      <el-col :span="6" style="padding-top: 3px">
        <div><label style="font-size: 10px; float: left">{{$t('devicePanel.deviceType') + "：" + device.deviceTypeName}}</label></div>
      </el-col>
      <el-col :span="6">
        <el-col :span="12" style="padding-top: 3px">
          <div><label style="font-size: 10px; float: left">{{$t('devicePanel.deviceModer') + "：" + device.deviceModel}}</label></div>
        </el-col>
      </el-col>
      <el-col :span="6">
        <el-col :span="4" style="padding-top: 3px">
          <div><label style="font-size: 10px; float: left">{{$t('devicePanel.rate') + "："}}</label></div>
        </el-col>
        <el-col :span="20" style="padding-top: -1px">
          <el-select
            v-model="refreshRateValue"
            size="mini"
            style="width: 80px; margin-right: 20px"
            @change="rateChange"
            :placeholder="$t('common.selectOption')">
            <el-option
              v-for="item in refreshRate"
              :key="item.value"
              :label="item.label"
              :value="item.value">
            </el-option>
          </el-select>
          <el-button size = 'mini' type="primary" style="margin-left: -10px" :disabled="refreshDisabled" @click="refreshInfo">{{$t('devicePanel.refresh')}}</el-button>
        </el-col>
<!--        <el-col :span="8" style="padding-right: 0px; padding-top: 1px">-->
<!--          <el-button size = 'mini' type="primary" :disabled="refreshDisabled" @click="refreshInfo">{{$t('devicePanel.refresh')}}</el-button>-->
<!--&lt;!&ndash;          <el-button size = 'mini' type="primary" :disabled="refreshDisabled" @click="devicePanelDialogInit">{{$t('devicePanel.refresh')}}</el-button>&ndash;&gt;-->
<!--        </el-col>-->
      </el-col>
    </el-row>
    <el-row>
      <div style="width: 100%; margin: 0 auto; padding: 0px 50px;">
        <el-row v-for="(item,index) in resourcesList" :key="index" :gutter="20">
          <el-col :span="2">
            <label style="font-size: 12px; padding-top: 1px; float: left;">{{infoLabels[item['resourcesName']]}}</label>
          </el-col>
          <el-col :span="22">
            <el-col :span="6" v-for="(element,index) in item.values" :key="index" style="padding-left: 0px; padding-right: 0px;">
              <div style="float: left;">
                <div style="float:left">
                  <icon :name="infoIcons[item['resourcesName']]" :w="18" :h="18" :id="element.resourceKey" :style="{fill: element.fill}"/>
                </div>
                <label style="font-size: 12px; text-align: start; float: right; padding-left: 2px; padding-top: 3px;">{{element.valueLabel}}</label>
              </div>
            </el-col>
          </el-col>
        </el-row>
      </div>
    </el-row>

    <el-main style="padding: 0">
      <div id="first">
        <svg :width="deviceSvgWidth" :height="deviceSvgHeight" id="deviceSVG"></svg>
      </div>
    </el-main>

    <el-row v-if="flag">
      <el-col v-for="(item,index) in portLegend" :key="index" style="float: left">
        <el-col :span="1.7" class="col-new" style="padding-left: 0px;padding-right: 0px;"><icon :name="portType[item]" :w="20" :h="20" :style="{fill:alarmLevelConfig[-1].alarmColor}"/></el-col>
        <el-col :span="1.7" class="col-new" style="padding-left: 0px;padding-right: 10px;"><label style="font-size: 10px; margin-bottom: 0px; margin-top: 5px;">{{portLabel[portType[item]] + $t('devicePanel.online')}}</label></el-col>
        <el-col :span="1.7" class="col-new" style="padding-left: 30px;padding-right: 0px;"><icon :name="portType[item]" :w="20" :h="20" :style="{fill:alarmLevelConfig[-2].alarmColor}"/></el-col>
        <el-col :span="1.7" class="col-new" style="padding-left: 23px;padding-right: 0px;"><label style="font-size: 10px; margin-bottom: 0px; margin-top: 5px;">{{portLabel[portType[item]] + $t('devicePanel.offline')}}</label></el-col>
      </el-col>
    </el-row>

    <div slot="footer" class="dialog-footer">
      <!--<el-button size = 'mini' type="primary" :disabled="refreshDisabled" @click="refreshInfo">{{$t('devicePanel.refresh')}}</el-button>-->
      <!--<el-button size = 'mini' type="primary" @click="restartDevice">{{$t('devicePanel.restart')}}</el-button>-->
      <!--<el-button size = 'mini' @click="ok">{{$t('common.ok')}}</el-button>-->
    </div>

    <!-- 右键单击端口 菜单栏-->
    <v-contextmenu ref="portContextmenu" id="portMenu">
      <v-contextmenu-item v-for="command in contextCommands" :key="command.key" @click="command.execute" :disabled="command.disabled">{{command.name}}</v-contextmenu-item>
    </v-contextmenu>
    <CommandExecuteContext v-bind:commands="commandContext"></CommandExecuteContext>

    <!-- 浮动显示信息 -->
    <div id="chartTooltipID" :class="portTipClass">
      <p>
        <strong class="name" style="display: block">{{$t('hoverPort.port')+': '+ hoverPortMessage.port}}<br/></strong>
<!--        <strong class="name" style="display: block">{{$t('hoverPort.fibreOpticalPort')+': '+ hoverPortMessage.fibreOpticalPort}}<br/></strong>-->
        <strong class="name" style="display: block">{{$t('hoverPort.state')+': '+ hoverPortMessage.state}}<br/></strong>
        <strong class="name" style="display: block">{{$t('hoverPort.model')+': '+ hoverPortMessage.model}}<br/></strong>
<!--        <strong class="name" style="display: block">{{$t('hoverPort.MACAddress')+': '+ hoverPortMessage.MACAddress}}<br/></strong>-->
<!--        <strong class="name" style="display: block">{{$t('hoverPort.VLAN')+': '+ hoverPortMessage.VLAN}}<br/></strong>-->
<!--        <strong class="name" style="display: block">{{$t('hoverPort.ipAddress')+': '+ hoverPortMessage.ipAddress}}<br/></strong>-->
<!--        <strong class="name" style="display: block">{{$t('hoverPort.TOpticalPower')+': '+ hoverPortMessage.TOpticalPower}}<br/></strong>-->
<!--        <strong class="name" style="display: block">{{$t('hoverPort.ROpticalPower')+': '+ hoverPortMessage.ROpticalPower}}<br/></strong>-->
      </p>
      <div>
        <div class="icon-circle-subnet" style="background-color:#0000FF;float: left"></div><label style="float: left">{{hoverPortMessage.alarmCount}}</label>
        <div class="icon-circle-subnet" style="background-color:#FF0000;float: left"></div><label style="float: left">{{hoverPortMessage.urgentAlarm}}</label>
        <div class="icon-circle-subnet" style="background-color:#FFA500;float: left"></div><label style="float: left">{{hoverPortMessage.seriousAlarm}}</label>
        <div class="icon-circle-subnet" style="background-color:#FFFF00;float: left"></div><label style="float: left">{{hoverPortMessage.waringAlarm}}</label>
      </div>
    </div>
  </el-dialog>
</template>

<script>
import ControllService from '../../../domain/services/DeviceControllService'
import DeviceService from '../../../domain/services/DeviceService'
import AlarmService from '../../../domain/services/AlarmService'
import AlarmManager from '../../../domain/models/AlarmManager'
import DeviceCommands from '../../../commands/DeviceCommands'
import CommandExecuteContext from '../../../commands/CommandExecuteContext'
import HelperUtil from '../../../utils/HelperUtil'
import ElCol from 'element-ui/packages/col/src/col'
import loading from '@/utils/Loading'

// svg绘制设备面板图
let d3 = require('d3')
let curThis = null
let deviceSVG = ''

export default {
  name: 'DevicePanelDialog',

  components: {
    ElCol,
    CommandExecuteContext
  },

  props: ['command'],
  data () {
    // 实现部分
    return {
      timer: '',
      commandContext: {},
      contextCommands: [],
      devicePanelDialogShow: false,

      devicePanelDialogName: '' + this.command.target.displayName + ' ' + this.command.title,
      devicePanelDialogWidth: '830px',
      deviceSvgWidth: 770,
      deviceSvgHeight: 100,
      deviceHeight: 1,
      portTipClass: 'chartTooltip hidden',
      legendSpan: 7,

      device: this.command.target,
      deviceKey: this.command.target.deviceKey,
      panelsDeviceModel: this.command.target.deviceModel,
      alarmLevelConfig: this.$store.state.alarmLevelConfig,

      // 图例
      electricalPort: './static/electricalPort.svg',
      opticalPort: './static/opticalPort.svg',
      lightPort40G: './static/opticalPort.svg',
      LightPort40GShow: false,
      portType: ['electricalPort', 'opticalPort', 'opticalPortPlus', 'opticalPort40', 'opticalPort100', 'trace'],
      portIcons: {
        'electricalPort': './static/electricalPort.svg',
        'opticalPort': './static/opticalPort.svg'
      },
      portLegend: [],
      portLabel: {
        'electricalPort': this.$t('devicePanel.electricalPort'),
        'opticalPort': this.$t('devicePanel.opticalPort')
      },
      info: ['FAN_STATUS', 'POWER_STATUS', 'TEMPERATURE', 'MEMORY', 'CPU', 'CHIP', 'DISK', 'OTHER'],
      infoIcons: {
        'FAN_RATE': 'fan',
        'FAN_STATUS': 'fan',
        'POWER_STATUS': 'power',
        'TEMPERATURE': 'temperature',
        'MEMORY': 'memory',
        'CPU': 'cpu',
        'DISK': 'disk',
        'CHIP': 'chip',
        'OTHER': 'other'
      },
      infoLabels: {
        'FAN_STATUS': this.$t('devicePanel.fan') + '：',
        'POWER_STATUS': this.$t('devicePanel.power') + '：',
        'TEMPERATURE': this.$t('devicePanel.temperature') + '：',
        'MEMORY': this.$t('devicePanel.memory') + '：',
        'CPU': this.$t('devicePanel.cpu') + '：',
        'CHIP': this.$t('devicePanel.chip') + '：',
        'DISK': this.$t('devicePanel.disk') + '：',
        'FAN_RATE': this.$t('devicePanel.fan') + '：',
        'OTHER': this.$t('devicePanel.other') + '：'
      },
      infoValue: {
        'FAN_STATUS': {
          '1': ['正常', '#1296db'],
          '0': ['异常', 'red']
        },
        'POWER_STATUS': {
          '1': ['正常', '#1296db'],
          '0': ['异常', 'red']
        },
        'COMMON': '#1296db'
      },

      panelsDeviceModelKey: '',
      devicePortsConfigList: [],
      devicePortsStatus: {},
      alarmCollection: {},
      devicePortsList: [],
      alarmPortName: '',
      alarmInfoList: [],
      devicePortObject: {},
      resources: [],
      resourcesList: [],

      hoverPortMessage: {
        port: '',
        fibreOpticalPort: '',
        state: '',
        model: '',
        MACAddress: '',
        VLAN: '',
        ipAddress: '',
        TOpticalPower: '',
        ROpticalPower: '',
        elementAlarmList: [],
        alarmCount: 0,
        urgentAlarm: 0,
        seriousAlarm: 0,
        waringAlarm: 0
      },

      selectPortID: [], // 选中端口Key

      refreshRate: [
        {
          value: 3000,
          label: '3s'
        },
        {
          value: 5000,
          label: '5s'
        },
        {
          value: 10000,
          label: '10s'
        },
      ],
      refreshRateValue: 3000,
      refreshDisabled: false,
      deviceSVG: null,
      g: null,
      topologyNodeShowList: [],
      first: 0,
      second: 0,
      third: 0,
      timeOut: null,
      number: 0,
      total: 0,
      initList: null,
      alarmList: [],
      alarmCollectionList: [],
      flag: false
    }
  },
  methods: {
    /**
     * @Description  : rateChange
     * @author       : ls
     * @date         : 2021/3/25 18:13
     * @param        :
     * @return       :
     */
    rateChange: function () {
      if (this.timer !== null) {
        clearInterval(this.timer)
        this.timer = ''
      }
      this.timer = setInterval(this.refreshInfo, this.refreshRateValue)
    },
    /**
     * @Description  : devicePanelDialogInit
     * @author       : ls
     * @date         : 2020/11/7 11:39
     * @param        :
     * @return       :
     */
    devicePanelDialogInit: async function () {
      this.getDeviceModelKey()
      this.getDevicePanPorts()
    },
    /**
     * @Description  : refreshInfo
     * @author       : ls
     * @date         : 2020/11/7 14:13
     * @param        :
     * @return       :
     */
    refreshInfo: function () {
      // this.getDeviceModelKey()
      // this.getResourceStatus()
      // this.refreshDisabled = true
      // let _this = this
      // _this.InfoTip.successTip(_this, HelperUtil.getStatusCodeObjectByCode(_this.successCode.OTHERS_CODE))
      //
      // // 10秒后启用点击事件
      // setTimeout(function () {
      //   _this.refreshDisabled = false
      // }, 10000)
      for (let i = 0; i < this.number; i++) {
        this.deviceSVG.selectAll('#back'.concat(i.toString())).remove()
      }
      if (this.g !== null) {
        this.g.selectAll('.node').remove()
        this.g.selectAll('.port').remove()
      }
      this.first = 0
      this.second = 0
      this.third = 0
      this.number = 0
      this.total = 0
      this.flag = false
      this.topologyNodeShowList = []
      this.devicePortsList = []
      this.getDeviceModelKey()
      this.getDevicePanPorts()
    },
    getDevicePanPorts: function () {
      let _this = this
      // let loadingInstance = loading.openLoading()
      return DeviceService.getDevicePortService(_this.deviceKey).then(result => {
        // 成功
        // _this.resources = result
        // let resourcesSort = _this.splitResources(_this.resources, 'PORT_STATUS')
        // _this.devicePortsConfigList = resourcesSort[0]
        // let resourceRemain = resourcesSort[1]
        // let resourceSplit = _this.sortResource(resourceRemain, _this.info)
        // _this.resourcesList = _this.addResourceInfoValue(resourceSplit, _this.infoValue)
        if (result.length === 0) {
          _this.InfoTip.warningTip_alarm(_this, HelperUtil.getCheckStatusCodeObjectByCode(_this.successCode.QUERY_NULL_CODE))
        } else {
          _this.number = result.length
          _this.initList = result
          _this.handleInitList()
          // _this.Loading.closeLoading(loadingInstance)
          _this.InfoTip.successTip(_this, HelperUtil.getStatusCodeObjectByCode(_this.successCode.QUERY_CODE))
        }
      }).catch(err => {
        // 失败
        this.devicePanelDialogShow = false
        // _this.Loading.closeLoading(loadingInstance)
        _this.InfoTip.errorTip(_this, err)
      })
    },
    /**
     * @Description  : handleInitList
     * @author       : ls
     * @date         : 2020/11/5 19:29
     * @param        :
     * @return       :
     */
    handleInitList: function () {
      for (let i = 0; i < this.initList.length; i++) {
        if (this.initList[i].FAN_RATE !== undefined && this.initList[i].FAN_RATE.length !== 0) {
          this.addI(i)
          this.handleData(this.initList[i].FAN_RATE, 'FAN_RATE', i)
        }
        if (this.initList[i].TEMPERATURE !== undefined && this.initList[i].TEMPERATURE.length !== 0) {
          this.addI(i)
          this.handleData(this.initList[i].TEMPERATURE, 'TEMPERATURE', i)
        }
        if (this.initList[i].FAN_STATUS !== undefined && this.initList[i].FAN_STATUS.length !== 0) {
          this.addI(i)
          this.handleData(this.initList[i].FAN_STATUS, 'FAN_STATUS', i)
        }
        if (this.initList[i].CPU !== undefined && this.initList[i].CPU.length !== 0) {
          this.addI(i)
          this.handleData(this.initList[i].CPU, 'CPU', i)
        }
        if (this.initList[i].MEMORY !== undefined && this.initList[i].MEMORY.length !== 0) {
          this.addI(i)
          this.handleData(this.initList[i].MEMORY, 'MEMORY', i)
        }
        if (this.initList[i].POWER_STATUS !== undefined && this.initList[i].POWER_STATUS.length !== 0) {
          this.addI(i)
          this.handleData(this.initList[i].POWER_STATUS, 'POWER_STATUS', i)
        }
        if (this.initList[i].PORT_STATUS !== undefined && this.initList[i].PORT_STATUS.length !== 0) {
          for (let t2 in this.initList[i].PORT_STATUS) {
            for (var m = 0; m < this.devicePortsConfigList.length; m++) {
              if (this.initList[i].PORT_STATUS[t2].confName === this.devicePortsConfigList[m].resourceName) {
                var objPort = {
                  alarmLevel: this.addAlarmLevel(this.initList[i].PORT_STATUS[t2].value, this.devicePortsConfigList[m].resourceName),
                  deviceModelKey: this.devicePortsConfigList[m].deviceModelKey,
                  deviceModelPortKey: this.devicePortsConfigList[m].deviceModelPortKey,
                  horizontalAxis: this.devicePortsConfigList[m].horizontalAxis,
                  verticalAxis: this.handleVerticalAxis(this.devicePortsConfigList[m].verticalAxis, i),
                  portName: this.initList[i].PORT_STATUS[t2].portName,
                  portType: this.devicePortsConfigList[m].portType,
                  resourceName: this.devicePortsConfigList[m].resourceName,
                  resourceType: this.devicePortsConfigList[m].resourceType,
                  status: this.addStatus(this.initList[i].PORT_STATUS[t2].value),
                  confName: this.initList[i].PORT_STATUS[t2].confName
                }
                this.devicePortsList.push(objPort)
              }
            }
          }
        }
      }
      this.topologyNodeShowList.push()
      this.second = this.second + this.first
      this.third = this.third + this.second
      this.createDeviceSVG()
      // for (let k = 0; k < 4; k++) {
      //   var oj = {
      //     horizontalAxis: 15 + k * 80,
      //     verticalAxis: this.deviceSvgHeight - 40,
      //     picType: this.infoIcons['MEMORY'],
      //     picKey: 'pickey',
      //     status: '-1',
      //     picName: '光'
      //   }
      //   this.topologyNodeShowList.push(oj)
      // }
      this.createBack()
      this.drawPic()
      this.drawDeviceSVG()
      this.flag = true
    },
    /**
     * @Description  : addStatus
     * @author       : ls
     * @date         : 2020/11/7 15:15
     * @param        :
     * @return       :
     */
    addStatus: function (v) {
      var a
      if (v === '2') {
        a = -2
      } else {
        a = -1
      }
      return a
    },
    /**
     * @Description  : handleParam
     * @author       : ls
     * @date         : 2020/11/8 11:17
     * @param        :
     * @return       :
     */
    handleData: function (v1, v2, v3) {
      // for (let t in this.initList[i].FAN_RATE) {
      //   var obj = {
      //     horizontalAxis: 45 + t * 65,
      //     verticalAxis: this.handleNomVertical(i),
      //     picType: this.infoIcons['FAN_RATE'],
      //     picKey: '2',
      //     status: '-1',
      //     picName: this.initList[i].FAN_RATE[t].value
      //   }
      //   this.topologyNodeShowList.push(obj)
      // }
      // this.topologyNodeShowList.push(
      //   {
      //     horizontalAxis: -16,
      //     verticalAxis: this.handleNomVertical(i),
      //     picType: this.infoIcons['FAN_RATE'],
      //     picKey: '2',
      //     status: '-3',
      //     picName: this.infoLabels['FAN_RATE']
      //   }
      // )
      for (let j in v1) {
        var obj = {
          horizontalAxis: 45 + j * 65,
          verticalAxis: this.handleNomVertical(v3),
          picType: this.infoIcons[v2],
          picKey: '2',
          status: '-1',
          picName: v1[j].value.substring(0, 5)
        }
        this.topologyNodeShowList.push(obj)
      }
      this.topologyNodeShowList.push(
        {
          horizontalAxis: -16,
          verticalAxis: this.handleNomVertical(v3),
          picType: this.infoIcons[v2],
          picKey: '2',
          status: '-3',
          picName: this.infoLabels[v2]
        }
      )
      this.total += 1
    },
    /**
     * @Description  : addI
     * @author       : ls
     * @date         : 2020/11/7 11:35
     * @param        :
     * @return       :
     */
    addI: function (i) {
      if (i === 0) {
        this.first += 1
      }
      if (i === 1) {
        this.second += 1
      }
      if (i === 2) {
        this.third += 1
      }
    },
    /**
     * @Description  : addAlarmLevel
     * @author       : ls
     * @date         : 2020/11/6 9:58
     * @param        :
     * @return       :
     */
    addAlarmLevel: function (v, m) {
      var a = -1
      if (v === '2') {
        a = -2
        return a
      } else {
        for (var i = 0; i < this.alarmList.length; i++) {
          if (this.alarmList[i].resourceName === m) {
            a = this.alarmList[i].alarmLevel
            return a
          }
        }
        return a
      }
    },
    /**
     * @Description  : handleNomVertical
     * @author       : ls
     * @date         : 2020/11/6 16:36
     * @param        :
     * @return       :
     */
    handleNomVertical: function (v) {
      var a
      a = 6.5 + this.total * 38 + 100 * v * curThis.deviceHeight
      return a
    },

    /**
     * @Description  : handleVerticalAxis
     * @author       : ls
     * @date         : 2020/11/6 16:09
     * @param        :
     * @return       :
     */
    handleVerticalAxis: function (v, i) {
      var a
      if (i === 0) {
        a = 38 * this.first + v
      }
      if (i === 1) {
        a = 38 * (this.second + this.first) + 100 * i * curThis.deviceHeight + v
      }
      if (i === 2) {
        a = 38 * (this.third + this.second + this.first) + 100 * i * curThis.deviceHeight + v
      }
      return a
    },
    /***
       * @Description  :点击关闭/确认按钮
       * @author       : zf
       * @date         : 2019/04/19 14:50
       */
    close () {
      this.command.done()
    },
    ok () {
      this.command.done()
    },

    /***
       * @Description  : 0.获取资源信息
       * @author       : zf
       * @date         : 2020/07/31 14:05
       */
    getResourceStatus: function () {
      let _this = this
      let selectList = []
      selectList.push(
        {
          quaryAttribute: 'deviceKey',
          compareSymbol: '=',
          compareValue: this.deviceKey
        }
      )
      return DeviceService.getDevicePortStatus(selectList).then(result => {
        // 成功
        _this.resources = result
        let resourcesSort = _this.splitResources(_this.resources, 'PORT_STATUS')
        _this.devicePortsConfigList = resourcesSort[0]
        let resourceRemain = resourcesSort[1]
        let resourceSplit = _this.sortResource(resourceRemain, _this.info)
        _this.resourcesList = _this.addResourceInfoValue(resourceSplit, _this.infoValue)
      }).catch(err => {
        // 失败
        _this.InfoTip.errorTip(_this, err)
      })
    },
    /**
     * @Description  : createDeviceSVG
     * @author       : ls
     * @date         : 2020/11/7 13:46
     * @param        :
     * @return       :
     */
    createDeviceSVG: function () {
      // this.getDeviceModelKey()
      curThis.deviceSvgHeight = this.third * 38 + this.number * 100 * curThis.deviceHeight
      curThis.selectPortID = []
      this.deviceSVG = d3.select('#deviceSVG')
      this.g = this.deviceSVG.append('g')
    },
    /**
     * @Description  : createBack
     * @author       : ls
     * @date         : 2020/10/29 9:39
     * @param        :
     * @return       :
     */
    createBack: function () {
      for (let i = 0; i < this.number; i++) {
        this.g.append('g')
          .attr('id', 'back'.concat(i.toString()))
          .attr('transform', 'translate(0,0)')
          .append('rect')
          .attr('width', '100%')
          .attr('height', 100 * curThis.deviceHeight)
          .attr('x', 0)
          // .attr('y', 100 * i * curThis.deviceHeight + 70 * (i + 1))
          .attr('y', function () {
            if (i === 0) {
              return 100 * i * curThis.deviceHeight + 38 * curThis.first
            }
            if (i === 1) {
              return 100 * i * curThis.deviceHeight + 38 * curThis.second
            }
            if (i === 2) {
              return 100 * i * curThis.deviceHeight + 38 * curThis.third
            }
          })
          .attr('fill', '#ffffff')
          .attr('stroke', '#000000')
          .attr('stroke-width', 1)
      }
      for (let j = 0; j < this.number; j++) {
        var a = d3.select(`#back${j}`)
        console.log(a)
      }
    },
    drawPic: function () {
      this.g.selectAll('.node').remove()
      let g1Update = this.g.selectAll('.node').data(this.topologyNodeShowList)
      g1Update.exit().remove()
      let g1Enter = g1Update.enter().append('g')
        .style('cursor', 'pointer')
        .classed('node', true)// 注意，此处就是之前一直创建图标准的病因，并未给g1一个类，以至于，选择集为空，每次都是enter()一个新的集合。和上面g.selectAll一一对应。
        .on('tick', this.tick())
      g1Enter.append('g').attr('class', 'node-image')
      // 为多出的数据集合添加网元名称
      g1Enter.append('text').attr('class', 'node-text')
      // g1Enter.call(this.addDragEvent())
      g1Update = g1Update.merge(g1Enter)
      // 更新网元名称
      g1Update.select('.node-text')
        .attr('dx', function (d) {
          return 45
        })
        .attr('dy', function (d) {
          return 15
        })
        .style('font-size', '12px')
        .style('text-anchor', 'middle')
        .style('font-family', 'SimSun')
        .text(function (d) {
          return d.picName
        })
      g1Update.selectAll('.node-image').nodes().forEach(n => {
        d3.xml(this.selectDeviceImagePth(n.__data__)).mimeType('image/svg+xml').get((error, xml) => {
          if (error) throw error
          for (let i = 0; i < n.childNodes.length; i++) {
            n.removeChild(n.childNodes[i])
          }
          n.append(xml.documentElement)
          n.childNodes[0].setAttribute('width', 25)
          n.childNodes[0].setAttribute('height', 25)
          n.childNodes[0].style.fill = this.getTopoColor(n.__data__.status)
        })
      })
    },
    tick: function () {
      curThis.g.selectAll('.node')
        .attr('transform', function (d) {
          return 'translate(' + d.horizontalAxis + ',' + d.verticalAxis + ')'
        })
    },
    selectDeviceImagePth (d) {
      var name = d.picType
      return `./static/${name}.svg`
    },
    selectDeviceImagePth1 (d) {
    // ./static/electricalPort.svg',
    //   'opticalPort': './static/opticalPort.svg'
      var name = d.portType
      return `./static/${name}.svg`
    },
    /**
     * @Description  : getTopoColor
     * @author       : ls
     * @date         : 2020/11/6 10:25
     * @param        :
     * @return       :
     */
    getTopoColor (d) {
      if (d === '-3') {
        return '#ffffff'
      }
      return this.alarmLevelConfig[d].alarmColor
    },
    addDragEvent () {
      let dragEvent = d3.drag()
        .on('start', curThis.$options.methods.dragStart)
        .on('drag', curThis.$options.methods.dragMove)
        .on('end', curThis.$options.methods.dragEnd)
      return dragEvent
    },
    dragMove: function (d) {
      // d3.select(".topologyTooltip").classed("hidden", true);
      curThis.currentDragKey = d.picKey // 记录下当前拖拽的设备的id
      d3.select(curThis.$el)
        .attr('transform', function () {
          d.horizontalAxis += d3.event.dx
          d.verticalAxis += d3.event.dy
          return 'translate(' + d.horizontalAxis + ',' + d.verticalAxis + ')'
        })
      d3.select(curThis.$el).on('tick', curThis.tick())
      d3.select(curThis.$el).on('rend', curThis.onRend())
      // curThis.tick()
      // curThis.drawDeviceSVG()
    },
    dragStart (d) {
      // d3.select(".topologyTooltip").classed("hidden", true);
      // document.getElementById("checkPath").style.display = "none";
      document.getElementById('nodeMenu').style.display = 'none'
      document.getElementById('linkMenu').style.display = 'none'
    },

    dragEnd (d) {
      // d3.select(".topologyTooltip").classed("hidden", true);
      curThis.currentDragKey = '' // 置空拖拽设备记录变量
    },
    /**
     * @Description  : drawDeviceSVG
     * @author       : ls
     * @date         : 2020/11/7 15:24
     * @param        :
     * @return       :
     */
    drawDeviceSVG: function () {
      let portImageWidth = 27
      let portImageHeight = 25
      // 返回数据和dom元素的交集
      this.g.selectAll('.port').remove()
      var portUpdate = this.g.selectAll('.port').data(curThis.devicePortsList)
      // 返回多出的dom集合并处理
      portUpdate.exit().remove()
      // 返回多出的数据集合并处理
      var portEnter = portUpdate.enter().append('g')
        .style('cursor', 'pointer')
        .classed('port', true)// 注意，此处就是之前一直创建图标准的病因，并未给g1一个类，以至于，选择集为空，每次都是enter()一个新的集合。和上面g.selectAll一一对应。
        // .attr('transform', function (d, i) {
        //   let horizontalAxis = d.horizontalAxis, verticalAxis = d.verticalAxis
        //   return 'translate(' + horizontalAxis + ',' + verticalAxis + ')'
        // })
        .on('rend', this.onRend())
        // .on('contextmenu', d => {
        //   // 关闭浮动窗
        //   d3.select('.chartTooltip').classed('hidden', true)
        //   // 单选
        //   d3.select(curThis.selectPortID[0]).attr('display', 'none')
        //   curThis.selectPortID = []
        //
        //   curThis.selectPortID.push('#port-background' + d.portName)
        //   d3.select('#port-background' + d.portName).attr('display', 'block')
        //   //            todo：右键菜单
        //   let target = []
        //   target.push(curThis.device)
        //   target.push(d)
        //   curThis.contextCommands = DeviceCommands.generateCommandsForPort(target, curThis.commandContext)
        //   d3.select('#portMenu')
        //     .style('left', (d3.event.x) + 'px')
        //     .style('top', (d3.event.y) + 'px')
        //     .style('display', 'block')
        // })
        .on('click', function (d) {
          d3.select('.chartTooltip').classed('hidden', true)
          if (d3.select('#portMenu').attr('display') === 'block') {
            d3.select('#portMenu').attr('display', 'none')
            d3.select(curThis.selectPortID[0].attr('display', 'none'))
          }
          if (d3.select('#port-background' + d.portName).attr('display') === 'none') {
            //              if(curThis.selectPortID.length >= 2){
            //                curThis.$message({
            //                  type: 'warning',
            //                  message: '只能选择两个端口！ ',
            //                  duration: 1000,
            //                  showClose: true,
            //                })
            //              }
            //              else{
            // 单选
            d3.select(curThis.selectPortID[0]).attr('display', 'none')
            curThis.selectPortID = []

            curThis.selectPortID.push('#port-background' + d.portName)
            d3.select('#port-background' + d.portName).attr('display', 'block')
            //              }
          } else {
            // 单选
            curThis.selectPortID = []
            curThis.selectPortID.push('#port-background' + d.portName)
            d3.select('#port-background' + d.portName).attr('display', 'none')
            // curThis.selectPortID.splice(curThis.contains('#port-background' + d.deviceModelPortKey, curThis.selectPortID), 1)
          }
        })
        .on('mouseover', d => {
          clearTimeout(curThis.timeOut)
          curThis.timeOut = setTimeout(() => {
            if (document.getElementById('portMenu').style.display !== 'block') {
              curThis.alarmPortName = ''
              curThis.alarmInfoList = []
              curThis.hoverPortMessage.port = d.portName
              curThis.hoverPortMessage.state = d.status === -1 ? '上电' : '未上电'
              curThis.hoverPortMessage.model = d.portType === 1 ? '光口' : '电口'
              // curThis.hoverPortMessage.fibreOpticalPort = d.resourceName
              curThis.hoverPortMessage.waringAlarm = 0
              curThis.hoverPortMessage.seriousAlarm = 0
              curThis.hoverPortMessage.urgentAlarm = 0
              curThis.hoverPortMessage.alarmCount = 0
              var yPosition = d.verticalAxis + 120
              var xPosition = d.horizontalAxis + 35
              var chartTooltip = d3
                .select('.chartTooltip')
                .style('left', xPosition + 'px')
                .style('top', yPosition + 'px')
              // chartTooltip.select('.name').html(curThis.alarmPortName)
              // 移除浮层hidden样式，展示浮层
              if (d.alarmLevel === 0) {
                curThis.hoverPortMessage.waringAlarm = 1
              } else if (d.alarmLevel === 1) {
                curThis.hoverPortMessage.seriousAlarm = 1
              } else if (d.alarmLevel === 2) {
                curThis.hoverPortMessage.urgentAlarm = 1
              };
              curThis.hoverPortMessage.alarmCount = curThis.hoverPortMessage.waringAlarm + curThis.hoverPortMessage.seriousAlarm +
                curThis.hoverPortMessage.urgentAlarm
              chartTooltip.classed('hidden', false)
            }
          }, 400)
        })
        .on('mouseout', () => {
          clearTimeout(curThis.timeOut)
          d3.select('.chartTooltip').classed('hidden', true)
        })

        // 添加覆盖的div
      // portEnter.append('rect').attr('class', 'shade')
      //   .attr('fill', 'red')
      //   .style('opacity', 0.5)
      //   .attr('display', 'block')

      portEnter.append('rect').attr('class', 'port-rect').attr('id', function (d) {
        return 'port-rect' + d.portName
      })
      // 添加端口背景框
      portEnter.append('rect')
        .attr('class', 'port-background')
        .attr('id', function (d) {
          return 'port-background' + d.portName
        })

        // 为多出数据集合添加端口图标
      portEnter.append('g')
        .attr('class', 'port-huizhi')
        // .attr('class', function (d) {
        //   return 'port-image' + curThis.portType[d.portType]
        // })
        .attr('id', function (d) {
          return d.portName
        })

      // portEnter.call(this.addDragEvent())
      // 此处是d3最牛逼的代码，v4新特性，将portEnter合并到portUpdate，使得第一次创建也属于更新里面。
      portUpdate = portUpdate.merge(portEnter)

      // 更新端口背景
      portUpdate.select('.port-background')
        .style('width', function (d) {
          if (d.portType !== 3) {
            portImageWidth = 27
          } else {
            portImageWidth = 36
          }
          return portImageWidth - 3
        })
        .style('height', (portImageHeight - 2))
        .attr('x', 1)
        .attr('y', 1)
        .attr('fill', '#c0c0c0')
        .style('opacity', 0.5)
        .attr('display', 'none')
        .attr('stroke', '#000000')
        .attr('stroke-width', 1.5)
      portUpdate.select('.port-rect')
        .style('width', function (d) {
          if (d.portType !== 3) {
            portImageWidth = 25
          } else {
            portImageWidth = 36
          }
          return portImageWidth - 2
        })
        .style('height', (portImageHeight - 2))
        .attr('x', 1)
        .attr('y', 1)
        .attr('fill', '#ffffff')
        .attr('display', 'block')
        .attr('stroke', d => {
          let colorValue = '#ffffff'
          if (curThis.alarmLevelConfig[d.alarmLevel]['alarmColor'] !== undefined) {
            if (d.alarmLevel === 0 || d.alarmLevel === 1 || d.alarmLevel === 2) {
              colorValue = curThis.alarmLevelConfig[d.alarmLevel]['alarmColor']
            }
          }
          return colorValue
        })
        .attr('stroke-width', 1.5)
      portUpdate.selectAll('.port-huizhi').nodes().forEach(n => {
        d3.xml(this.selectDeviceImagePth1(n.__data__)).mimeType('image/svg+xml').get((error, xml) => {
          if (error) throw error
          for (let i = 0; i < n.childNodes.length; i++) {
            n.removeChild(n.childNodes[i])
          }
          n.append(xml.documentElement)
          n.childNodes[0].setAttribute('width', 25)
          n.childNodes[0].setAttribute('height', 25)
          n.childNodes[0].style.fill = this.getTopoColor(n.__data__.status)
        })
      })

      // 更新端口图标
      // Promise.all([
      //   d3.xml(curThis.portIcons[curThis.portType[0]]).mimeType('image/svg+xml'),
      //   d3.xml(curThis.portIcons[curThis.portType[1]]).mimeType('image/svg+xml')
      // ])
      //   .then(([electricalPort, opticalPort]) => {
      //     electricalPort.get((error, data) => {
      //       portUpdate.selectAll('.port-image' + curThis.portType[0]).nodes()
      //         .forEach(n => {
      //           if (n.childNodes.length === 0) {
      //             n.append(data.documentElement.cloneNode(true))
      //             n.childNodes[0].setAttribute('width', portImageWidth)
      //             n.childNodes[0].setAttribute('height', portImageHeight)
      //             n.childNodes[0].style.fill = curThis.alarmLevelConfig[curThis.devicePortObject[n.getAttribute('id')].alarmLevel].alarmColor
      //           }
      //         })
      //     })
      //     opticalPort.get((error, data) => {
      //       portUpdate.selectAll('.port-image' + curThis.portType[1]).nodes()
      //         .forEach(n => {
      //           if (n.childNodes.length === 0) {
      //             n.append(data.documentElement.cloneNode(true))
      //             n.childNodes[0].setAttribute('width', portImageWidth)
      //             n.childNodes[0].setAttribute('height', portImageHeight)
      //             n.childNodes[0].style.fill = curThis.alarmLevelConfig[curThis.devicePortObject[n.getAttribute('id')].alarmLevel].alarmColor
      //             console.log('面板图颜色')
      //             console.log(curThis.alarmLevelConfig[curThis.devicePortObject[n.getAttribute('id')].alarmLevel].alarmColor)
      //           }
      //         })
      //     })
      //   })
    },
    onRend: function () {
      curThis.g.selectAll('.port')
        .attr('transform', function (d) {
          return 'translate(' + d.horizontalAxis + ',' + d.verticalAxis + ')'
        })
    },

    /***
       * @Description  : 2.获取设备型号Key——根据获取的设备型号调用接口查询设备型号主键
       * @author       : zf
       * @date         : 2019/03/27 19:28
       */
    getDeviceModelKey: function () {
      this.devicePortsList = []
      let selectList = []
      selectList.push({ quaryAttribute: 'deviceModel',
        compareSymbol: '=',
        compareValue: this.panelsDeviceModel})
      let _this = this
      // return DeviceService.getDeviceTypeKey(selectList).then(result => {
      var a = DeviceService.getDeviceTypeKey(selectList).then(result => {
        // 成功
        if (result.length > 0) {
          if (result[0].deviceModelKey !== undefined) {
            _this.panelsDeviceModelKey = result[0].deviceModelKey
            _this.deviceHeight = result[0].height
          }
        } else {
          _this.panelsDeviceModelKey = ''
        }
        _this.getDevicePorts() // 通过获取的设备型号Key获取端口配置
      }).catch(err => {
        // 失败
        _this.InfoTip.errorTip(_this, err)
      })
      return a
    },

    /***
       * @Description  : 3.获取设备端口配置——根据设备型号主键获取设备端口配置
       * @author       : zf
       * @date         : 2019/03/27 19:29
       */
    getDevicePorts: function () {
      let selectList = []
      selectList.push(
        {
          quaryAttribute: 'deviceModelKey',
          compareSymbol: '=',
          compareValue: this.panelsDeviceModelKey
        }
      )
      let _this = this
      DeviceService.getDevicePortConfig(selectList).then(result => {
        // 成功
        _this.devicePortsConfigList = result
        _this.portTypeShow() // 添加图例
        // _this.getAlarmCollection() // 获取端口状态
      }).catch(err => {
        // 失败
        _this.InfoTip.errorTip(_this, err)
      })
    },

    /***
       * @Description  : 3.5判断设备端口显示种类
       * @author       : zf
       * @date         : 2019/07/15 11:45
       */
    portTypeShow: function () {
      let portLegendSet = new Set()
      for (let i = 0; i < this.devicePortsConfigList.length; i++) {
        portLegendSet = portLegendSet.add(this.devicePortsConfigList[i].portType)
      }
      this.portLegend = Array.from(portLegendSet)
      this.portLegend.sort()
    },

    /***
       * @Description  : 4.获取设备各端口状态——获取各端口状态
       * @author       : zf
       * @date         : 2019/1/3 14:02
       */
    getDevicePortStatus: function () {
      let _this = this
      let selectList = []
      selectList.push(
        {
          quaryAttribute: 'deviceKey',
          compareSymbol: '=',
          compareValue: this.deviceKey
        },
        {
          quaryAttribute: 'deviceParam',
          compareSymbol: '=',
          compareValue: 'PORT_STATUS'
        }
      )
      DeviceService.getDevicePortStatus(selectList).then(result => {
        // 成功
        _this.devicePortsStatus = result
        _this.getAlarmCollection() // 获取端口告警状态
      }).catch(err => {
        // 失败
        _this.InfoTip.errorTip(_this, err)
      })
    },

    /***
       * @Description  : 5.获取告警列表
       * @author       : zf
       * @date         : 2019/1/3 14:02
       */
    getAlarmCollection: function () {
      let _this = this
      AlarmService.getAllAlarmCollection().then(result => {
        this.alarmCollectionList = Object.values(result)
        this.alarmList = this.alarmCollectionList.filter(item => {
          return (item.elementKey === this.deviceKey && item.isLink === 0)
        })
        // _this.addPortsStatus() // 获取端口状态
      }).catch(err => {
        // 失败
        _this.InfoTip.errorTip(_this, err)
      })
    },

    /***
       * @Description  : 6.将端口状态添加至设备端口List中
       * @author       : zf
       * @date         : 2019/03/27 19:34
       */
    addPortsStatus: function () {
      let AlarmMgr = AlarmManager(this.alarmCollection)
      this.devicePortsList = AlarmMgr.getDeviceListByAlarmCollection(this.devicePortsConfigList, this.deviceKey, this.devicePortsStatus)
      this.devicePortObject = HelperUtil.arrayToObject(this.devicePortsList, 'deviceModelPortKey')
      this.drawDeviceSVG() // 数据获取到之后调用SVG画图
    },
    /***
       * @Description  : 重启设备
       * @author       : zf
       * @date         : 2019/05/14 18:45
       */
    restartDevice: function () {
      let _this = this
      ControllService.getRestartDevice(this.deviceKey).then(result => {
        // 成功
        _this.InfoTip.successTip(_this, HelperUtil.getStatusCodeObjectByCode(_this.successCode.OTHERS_CODE))
      }).catch(err => {
        // 失败
        _this.InfoTip.errorTip(_this, err)
      })
    },

    /***
       * @Description  : util: 提取包含指定值的资源结果
       * @author       : zf
       * @date         : 2020/08/06 22:42
       */
    splitResources: function (resources, splitKey) {
      let res = []
      let splitTarget = []
      let splitRemain = []
      resources.forEach(function (item) {
        if (item.deviceParam === splitKey) splitTarget.push(item)
        else splitRemain.push(item)
      })
      res.push(splitTarget)
      res.push(splitRemain)
      return res
    },
    /***
       * @Description  : util: 将资源结果按指定类别分类
       * @author       : zf
       * @date         : 2020/08/06 23:02
       */
    sortResource: function (resources, sortKeys) {
      let res = []
      let sortKeysSet = new Set(sortKeys)
      let tempSet = new Set()
      resources.forEach(function (item) {
        if (!sortKeysSet.has(item.deviceParam)) { // 前端没有相应图标显示
          // if(!tempSet.has("OTHER")){ //如果结果中不存在OTHER分类
          //   tempSet.add("OTHER")
          //   let temp = {
          //     resourcesName: "OTHER",
          //     values:[item],
          //   }
          //   res.push(temp)
          // } else {
          //   res.forEach(function (e) { //结果中已有OTHER分类
          //     if(e.resourcesName === "OTHER") e.values.push(item)
          //   })
          // }
        } else { // 前端有相应图标显示
          if (!tempSet.has(item.deviceParam)) { // 如果结果中不存在item.deviceParam分类
            tempSet.add(item.deviceParam)
            let temp = {
              resourcesName: item.deviceParam,
              values: [item]
            }
            res.push(temp)
          } else {
            res.forEach(function (e) { // 结果中已有OTHER分类
              if (e.resourcesName === item.deviceParam) e.values.push(item)
            })
          }
        }
      })
      return res
    },
    /***
       * @Description  : util: 为相应图标添加颜色和显示文字
       * @author       : zf
       * @date         : 2020/08/07 01:44
       */
    addResourceInfoValue: function (resources, infoValue) {
      let infoKeys = []
      for (let key in infoValue) infoKeys.push(key)
      let infoSet = new Set(infoKeys)
      let flag = false
      let pos = -1
      resources.forEach(function (item, index) {
        if (infoSet.has(item.resourceName)) {
          item.values.forEach(function (e) {
            e['valueLabel'] = infoValue[item.resourceName][e.value][0]
            e['fill'] = infoValue[item.resourceName][e.value][1]
          })
        } else {
          item.values.forEach(function (e) {
            e['valueLabel'] = e.value
            e['fill'] = infoValue['COMMON']
          })
        }
        if (item.resourcesName === 'OTHER') {
          flag = true
          pos = index
        }
      })
      if (flag) {
        let temp = resources[pos]
        resources.splice(pos, 1)
        resources.push(temp)
      }
      return resources
    },
    /**
     * @Description  : clearTimer
     * @author       : ls
     * @date         : 2021/3/25 19:01
     * @param        :
     * @return       :
     */
    clearTimer: function () {
      clearInterval(this.timer)
      this.timer = null
    }
  },
  destroyed () {
    this.clearTimer()
  },
  created: function () {
    this.getAlarmCollection()
    curThis = this
    if (window.localStorage.getItem('user-language') === 'en') {
      this.legendSpan = 8.5
      this.portTipClass = 'chartTooltip hidden en'
    } else {
      this.legendSpan = 4
    }
  },
  mounted: function () {
    this.devicePanelDialogShow = true
    this.timer = setInterval(this.refreshInfo, 2000)
    /**
       * 设置点击监听事件，实现左键点击，菜单/选择框消失。
       * 1.获取到所有网元节点集合的长度
       * 2.监听鼠标左键，
       * 3.循环所有网元节点集合，判断当前右键点击的元素是否是网元节点中的一个，是将flag置为true。
       * 4.当遍历结束所有的网元节点，flag均为false的时候，隐藏菜单/选择框。
       */
    document.addEventListener('click', function (event) {
      if (document.getElementById('portMenu')) {
        document.getElementById('portMenu').style.display = 'none'
      }
      // alert(event.target.nodeName)
      if (event.target.nodeName === 'svg' || event.target.nodeName === 'rect') {
        d3.select(curThis.selectPortID[0]).attr('display', 'none')
      }
      //        多选
      // let portImageLength = document.getElementsByClassName('port-huizhi').length
      // let portImageFlag = false
      // for (let i = 0; i < portImageLength; i++) {
      //   portImageFlag = event.target.contains(document.getElementsByClassName('port-huizhi')[i])
      //   if (event.target.id === 'deviceSVG') {
      //     portImageFlag = false
      //   }
      //   if (portImageFlag) {
      //     break
      //   }
      // }
      // if (!portImageFlag) {
      //   for (let j = 0; j < curThis.selectPortID.length; j++) {
      //     // d3.select(curThis.selectPortID[j]).attr('display', 'none')
      //   }
      //   curThis.selectPortID = []
      // }
    })
  }
}
</script>

<style scoped>
  /deep/ .el-new {
    padding-left: 0px!important;
    padding-right: 0px!important;
  }

  /deep/ .el-column-padding{
    padding-bottom: 10px!important;
    padding-top: 0px!important;
  }
  /deep/ .el-main{
    padding-bottom: 0px!important;
    padding-top: 0px!important;
    padding-left: 0px!important;
    padding-right: 0px!important;
  }
  /*/deep/ .el-dialog__header {*/
  /*background: #EFF3F9*/
  /*}*/

  /*告警信息悬浮提示*/
  .chartTooltip {
    position: absolute;
    width: 200px;
    height: auto;
    padding-left: 10px;
    padding-top: 10px;
    padding-bottom: 10px;
    box-sizing: border-box;
    background-color: white;
    border-radius: 5px;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
    pointer-events: none;
  }
  .chartTooltip.hidden {
    display: none;
  }
  .chartTooltip p {
    margin: 0;
    font-size: 14px;
    text-align: left;
  }
  .chartTooltip.en {
    min-width: 265px;
  }
</style>
