<template>
  <div class="g-p20 g-mb-40 content">
    <base-head :titles="titles.arr" @onTabChange="change" bottom="20"></base-head>
    <div class="g-card g-p20 g-fx main" v-loading="dataSource.loading">
      <div class="left">
        <div class="left__head">
          <div class="info">
            <div class="info1">基本信息</div>
            <div class="info2">{{ equipmentInfo.name }}</div>
            <div class="info3">
              <span>设备序列号 </span> <span class="g-ml-20">{{ equipmentInfo.code }}</span>
            </div>
            <div class="info3">
              <span>监控编号</span>
              <span class="g-ml-20">
                {{ equipmentInfo.productNo }}
              </span>
            </div>
            <div class="info3">
              <span>设备型号</span> <span class="g-ml-20">{{ equipmentInfo.model }}</span>
            </div>
          </div>
          <div class="info__img" :class="{ isOnLine: !equipmentInfo?.isOnline }"></div>
          <div class="head__second">
            <div class="second-info">
              <div class="second-name">
                {{ '报警 ' + alarmList.array.length }}
              </div>
              <div class="second-alarm"><live-message :list="alarmList.array"></live-message></div>
            </div>

            <div class="second-info">
              <div class="second-name bg2">
                {{ '预警 ' + warningList.array.length }}
              </div>
              <div class="second-warning"><live-message :list="warningList.array"></live-message></div>
            </div>
          </div>
        </div>
        <div class="left__footer g-p20">
          <div class="footer__info g-fx">
            <div class="item" v-if="currentData?.stroke">
              <div>
                <div class="text1">
                  {{ formatValue(currentData?.stroke.value, currentData?.stroke.translate) }}
                  <span style="font-weight: 400; font-size: 16px">{{ currentData?.stroke.unit }}</span>
                </div>
                <div class="text2">
                  {{ currentData?.isHoist ? '高度' : '行程' }}
                </div>
              </div>
            </div>
            <div class="item" v-if="currentData?.gear">
              <div>
                <div class="text1">
                  {{ formatGears(currentData?.gear) }}
                  <span style="font-weight: 400; font-size: 16px">{{ currentData?.gear.unit }}</span>
                </div>
                <div class="text2">
                  {{ '档位' }}
                </div>
              </div>
            </div>
            <div class="item" v-if="currentData?.weight">
              <div>
                <div class="text1">
                  {{ formatValue(currentData?.weight.value, currentData?.weight.translate) }}
                  <span style="font-weight: 400; font-size: 16px">{{ currentData?.weight.unit }}</span>
                </div>
                <div class="text2">
                  {{ '载荷' }}
                  <div class="weight-color" :style="{ backgroundColor: formatWeightLight(currentData?.weight.light) }">
                  </div>
                </div>
              </div>
            </div>
          </div>
          <!-- 中间六个指示灯 -->
          <div class="g-fx footer__info2">
            <div class="item2" v-for="el in currentData?.middleLightList" :key="el.variableId">
              <div class="text1" :style="{ backgroundColor: getBgColor(el) }"></div>
              <div class="text2">{{ el.variableName }}</div>
            </div>
          </div>
        </div>
      </div>
      <div class="right">
        <div class="g-fx-j right__item" v-for="(el, i) in currentData?.switchVariables" :key="i">
          <div class="text">{{ el.variableName }}</div>
          <div class="text2">
            <div :style="{ backgroundColor: getBgColor(el) }"></div>
          </div>
        </div>

        <div class="g-fx-j right__item" v-for="(el, i) in currentData?.matchVariables" :key="i">
          <div class="text">{{ el.name }}</div>
          <div class="text2">
            {{ formatValue(el.vValue, el.translate) + el.unitName }}
            <div :style="{ backgroundColor: getMatchBgColor(el) }"></div>
          </div>
        </div>

        <div class="g-fx-j right__item" v-for="(el, i) in currentData?.valueVariables" :key="i">
          <div class="text">{{ el.variableName }}</div>
          <div class="text2">
            {{ formatValue(el.value, el.translate) + el.unitName }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { getGroupAndVariables } from '@/api'
import { fetchDeviceInfoAll } from '@/api/deviceAuthorize'
import { useSidebarStore } from '@/store/sidebar'
import { formatGears, formatValue, formatWeightLight } from '@/utils/tools'
import LiveMessage from './live-message.vue'

/** 警告数组 */
const warningList: any = reactive({ array: [] })
/** 报警数组 */
const alarmList: any = reactive({ array: [] })
let titles = reactive({
  arr: []
})
const sidebar = useSidebarStore()
let equipmentInfo: any = ref({})
let deviceId: any = ref('')
let currentData: any = ref({})
let dataSource: any = reactive({
  data: []
})

onUnmounted(() => {
  onUnsubscribe(`Byte/${equipmentInfo.value.code}`)
})

onMounted(async () => {
  const eId = useQuery('id')
  sidebar.setEquipmentId(eId)
  deviceId.value = useQuery('id') as string
  getDeviceInfo()
  getDataSource()
})

const getDeviceInfo = async () => {
  const data = await fetchDeviceInfoAll(deviceId.value)
  equipmentInfo.value = data
  onSubscribe([`Byte/${equipmentInfo.value.code}`],(topic: any, payload: any) => {
    parseData(payload)
  })
}

const getDataSource = async () => {
  const data = await getGroupAndVariables({ deviceId: deviceId.value })
  dataSource.data = data

  titles.arr = dataSource.data.map((item: { groupName: any }) => item.groupName)

  dataSource.data.forEach((group: any) => {
    group.middleLightList = group.switchVariables.slice(0, 6)
    group.switchVariables = group.switchVariables.slice(6)

    var light = group.weight?.light
    if (light != null) {
      updateAlarm('red', group.groupName + '超载', light.value)
    }
    group.middleLightList.forEach((g: any) => {
      updateAlarm(g.trueLight, group.groupName + g.variableName, g.value)
    })

    group.switchVariables.forEach((g: any) => {
      updateAlarm(g.trueLight, group.groupName + g.variableName, g.value)
    })
  })

  currentData.value = dataSource.data[0]
}
const change = (v: any, position: any) => {
  currentData.value = dataSource.data[position]
}

const parseData = (payload: any) => {
  const obj = JSON.parse(payload)
  //设备号
  const station = obj.Station
  //数据
  const byteArray = base64ToArray(obj.Data);
  for (var index = 0; index < dataSource.data.length; index++) {
    const item = dataSource.data[index]

    if (station != item.station) {
      continue
    }

    //载荷
    var weight = item.weight
    if (weight != null) {
      weight.value = toData(byteArray, weight.dataType, weight.address)
      var light = weight.light
      if (light != null) {
        light.value = light.isReverse != toData(byteArray, 1, light.address)
        updateAlarm('red', item.groupName + '超载', light.value)
      }
    }

    //高度或者 行程
    var stroke = item.stroke
    if (stroke != null) {
      var value = toData(byteArray, stroke.dataType, stroke.address)
      stroke.value = value < 0 ? '0' : value
    }

    //档位
    var gear = item.gear
    if (gear != null) {
      var array: any = []
      gear.options.forEach((option: any) => {
        var gearName = option.displayName
        var address = option.address
        var b = toData(byteArray, option.dataType, address)
        if (b) {
          array.push(gearName)
        }
      })
      gear.gears = array
    }

    item.middleLightList.forEach((m: any) => {
      m.value = m.isReverse != toData(byteArray, 1, m.address)
      updateAlarm(m.trueLight, item.groupName + m.variableName, m.value)
    })

    item.switchVariables.forEach((s: any) => {
      s.value = s.isReverse != toData(byteArray, 1, s.address)
      updateAlarm(s.trueLight, item.groupName + s.variableName, s.value)
    })

    item.valueVariables.forEach((e: any) => {
      const value = toData(byteArray, e.dataType, e.address)
      e.value = evaluateFormula(formatValue(value, e.translate), e.formula)
    })

    item.matchVariables.forEach((m: any) => {
      m.vValue = toData(byteArray, m.dataType, m.vAddress)

      var sAddress = m.sAddress
      if (sAddress.indexOf(',') > 0) {
        var addressArray = sAddress.split(',')
        for (var index = 0; index < addressArray.length; index++) {
          const addr = addressArray[index]
          var b = m.isReverse != toData(byteArray, 1, addr)
          if (b) {
            m.sValue = true
            updateAlarm(m.trueLight, item.groupName + m.sName, true)
            break
          }
        }
        m.sValue = false
      } else {
        m.sValue = m.isReverse != toData(byteArray, 1, sAddress)
        updateAlarm(m.trueLight, item.groupName + m.sName, m.sValue)
      }
    })
  }
}

const evaluateFormula = (value: any, formula: any) => {
  if (formula == null || formula == undefined || formula === '') {
    return value
  }
  //函数模板
  const array = formula.split(",")
  //字符串模本
  var templete = array[0]
  const formulaArray = array.slice(1)
  formulaArray.forEach((item: any, index: number) => {
    const func = item.replace("{Value}", value)
    const result = eval(func)
    templete = templete.replace(`{${index}}`, Math.floor(parseFloat(result)))
  })
  return templete
}


const base64ToArray = (str: string) => {
  const base64Str = window.atob(str);
  const len = base64Str.length;
  const bytes = new Uint8Array(len)
  for (var i = 0; i < len; i++) {
    bytes[i] = base64Str.charCodeAt(i)
  }
  return bytes;
}

const toData = (bytes: any, dataType: number, address: string) => {
  switch (dataType) {
    case 1: //布尔值
      var positionArray = address.split('.')
      if (positionArray.length > 0) {
        //字节位置
        var groupPosition = parseInt(positionArray[0])
        //值
        var childPosition = parseInt(positionArray[1])

        if (groupPosition <= bytes.length - 1) {
          return byte2Boolen(bytes[groupPosition])[childPosition]
        }
      }
      return ''

    case 2: //16-bit Unsigned
      var position = parseInt(address)
      return toUInt16(bytes, position)

    case 3: //16-bit Signed
      var position = parseInt(address)
      return toInt16(bytes, position)

    case 4: //32-bit Unsigned
    case 5:
      var position = parseInt(address)
      return toUInt32(bytes, position)

    case 6: //32-bit Float
      var position = parseInt(address)
      return toUInt32(bytes, position) << 0

    default:
      return ''
  }
}

const byte2Boolen = (byte: any) => {
  var bin: any = []
  byte
    .toString(2)
    .padStart(8, '0')
    .split('')
    .reverse()
    .forEach((c: any) => {
      bin.push(c == '1' ? true : false)
    })
  return bin
}

const toUInt16 = (bytes: any, offset: number) => {
  if (bytes.length < 2) return 0
  return parseInt(bytes[offset + 1].toString(16) + bytes[offset].toString(16), 16)
}

const toInt16 = (bytes: any, offset: number) => {
  var num = toUInt16(bytes, offset)
  return num > 32767 ? num - 65536 : num
}

const toUInt32 = (bytes: any, offset: number) => {
  if (bytes.length < 4) return 0
  var num = parseInt(
    bytes[offset + 1].toString(16) +
    bytes[offset + 0].toString(16) +
    bytes[offset + 3].toString(16) +
    bytes[offset + 2].toString(16),
    16
  )
  return num
}

const updateAlarm = (trueLight: string, name: string, value: any) => {
  if (value == true || value == 'true') {
    if (trueLight == 'red') {
      var alarm = alarmList.array.find((f: any) => f == name)
      if (alarm == null) {
        alarmList.array.push(name)
      }
    }
    if (trueLight == 'yellow') {
      var warn = warningList.array.find((f: any) => f == name)
      if (warn == null) {
        warningList.array.push(name)
      }
    }
  } else {
    alarmList.array = alarmList.array.filter((f: any) => f != name)
    warningList.array = warningList.array.filter((f: any) => f != name)
  }
}

/**
 *
 * @param el 传入的元素
 * @param isFirst  判断是不是 单独的三个
 */
const getBgColor = (el: any) => {
  const obj: any = {
    green: '#6AD28C',
    red: '#FE5656',
    yellow: '#F49F51',
    gray: '#999999'
  }
  if (el.value || el.value === 'true') {
    return obj[el.trueLight]
  } else {
    return obj[el.falseLight]
  }
}
/**
 *
 * @param el 传入的元素
 * @param isFirst  判断是不是 单独的三个
 */
const getMatchBgColor = (el: any) => {
  const obj: any = {
    green: '#6AD28C',
    red: '#FE5656',
    yellow: '#F49F51',
    gray: '#999999'
  }
  // 是否翻转 true 翻转, false 不翻转
  if (el.sValue || el.sValue === 'true') {
    return obj[el.trueLight]
  } else {
    return obj[el.falseLight]
  }
}
</script>

<style lang="less" scoped>
.content {
  background-color: #c8cfdf;
  height: 100%;
}



.left {
  width: 100%;
  border-right: 1px solid #e5e7ee;
  display: flex;
  flex-direction: column;

  &__head {
    width: calc(100% - 20px);
    display: flex;
    flex-direction: row;
    height: 260px;
    padding: 0px 30px;
    align-items: center;
    background: linear-gradient(36deg, #86b0e9, #5f7cd6);
    border-radius: 15px;
    justify-content: space-between;

    .info {
      color: #fff;
    }

    .info__img {
      background-image: url('../../../assets/img/equipment2.png');
      background-size: 100% 100%;
      width: 300px;
      height: 300px;
    }

    .isOnLine {
      filter: grayscale(100%);
    }

    .info1 {
      background-color: rgba(42, 55, 110, 0.4);
      font-weight: bold;
      font-size: 16px;
      width: 87px;
      padding: 5px;
      text-align: center;
      border-radius: 5px;
    }

    .info2 {
      margin: 15px 0;
      font-weight: bold;
      font-size: 24px;
    }

    .info3 {
      margin: 5px 0;
      font-size: 12px;

      span:first-child {
        display: inline-block;
        width: 60px;
      }
    }
  }

  .head__second {
    width: 260px;
    min-width: 260px;
    margin-left: 20px;
    border-radius: 10px;

    .second-info {
      height: 75px;
      display: flex;
      border-radius: 15px;
      background: RGBA(229, 193, 164, 0.5);
      border: 1px solid #c49159;
      align-items: center;
      padding-left: 20px;
    }

    ::v-deep(.second-info) {
      .el-carousel__indicator {
        display: none;
      }
    }

    .second-info:first-child {
      margin-bottom: 20px;
      background: RGBA(229, 163, 169, 0.5);
      border: 1px solid #cd524a;
    }

    .second-name {
      width: 70px;
      height: 45px;
      background: #cd524a;
      border-radius: 10px;
      color: #fff;
      text-align: center;
      line-height: 45px;
      font-size: 12px;
      margin-right: 10px;
    }

    .second-alarm {
      color: #c44b44;
      font-size: 12px;
      width: 120px;
    }

    .second-warning {
      color: #c57d31;
      font-size: 12px;
      width: 120px;
    }

    .bg2 {
      background: #d79146;
    }

    .second-time {
      font-size: 12px;
      margin: 3px;
      text-align: center;
    }

    .color2 {
      color: #c57d31;
    }

    .second-text {
      align-items: center;
      justify-content: center;
      margin: 3px;
    }

    .icon-right {
      display: flex;
      align-items: center;

      .el-icon {
        font-size: 12px;
        transform: scale(0.9);
      }
    }

    .second-text {
      font-size: 12px;
    }
  }

  &__footer {
    display: flex;
    flex-direction: column;
    margin-right: 20px;
    border: 3px solid #e5e7ee;
    border-radius: 15px;
    margin-top: 20px;
    margin-bottom: 20px;

    .footer__info {
      min-height: 170px;
      align-items: center;
    }

    .item {
      flex: 1;
      height: 100%;
      text-align: center;
      display: flex;
      flex-direction: column;
      justify-content: center;
      border-right: 2px solid #e5e7ee;

      &:last-child {
        border: none;
      }

      .text1 {
        font-size: 36px;
        font-weight: bold;
      }

      .weight-color {
        position: absolute;
        width: 20px;
        height: 4px;
        border-radius: 2px;
        position: absolute;
        left: calc(50% + 20px);
        top: 50%;
        transform: translateY(-50%);
      }

      .text2 {
        color: #4a5373;
        margin-top: 8px;
        position: relative;
      }
    }

    .footer__info2 {
      margin-top: 60px;
      margin-bottom: 30px;
    }

    .item2 {
      flex: 1;
      text-align: center;

      .text1 {
        width: 80px;
        height: 7px;
        background: #6ad28c;
        border-radius: 3px;
        margin: 0 auto;
      }

      .text2 {
        color: #4a5373;
        font-size: 14px;
        margin-top: 10px;
      }
    }
  }
}

.right {
  width: 490px;
  height: 100%;
  padding-left: 16px;

  &__item {
    height: 40px;
    margin: 0 30px;
    line-height: 40px;
    border-bottom: 1px solid #dcddde;
    margin-bottom: 5px;

    .text {
      color: #4a5373;
      font-size: 14px;
    }

    .text2 {
      display: flex;
      align-items: center;
      justify-content: center;

      div {
        width: 30px;
        height: 5px;
        background: #6ad28c;
        border-radius: 3px;
        margin-left: 10px;
      }
    }
  }
}
</style>
