<template>
  <div
    draggable="true"
    @dragstart="startDrag"
    @dragend="stopDrag"
    :style="{ left: x + 'px', top: y + 'px' }"
    style="cursor: pointer; position: absolute; z-index: 999"
  >
    <el-badge
      :value="warnLength"
      :class="{ active: warnLength && !displayAlarms ? false : true }"
    >
      <div class="alarmDeligo" @click="displayAlarm" v-if="warnLength">
        <img src="@assets/imgs/ygj.png" class="trans" />
        <img src="@assets/imgs/ygj1.png" />
      </div>
      <div class="alarmDeligo" @dblclick="setting" v-if="!warnLength">
        <img src="@assets/imgs/wgj.png" class="trans" />
        <img src="@assets/imgs/wgj1.png" />
      </div>
    </el-badge>
    <deligo-alarm-list
      :dialogList="warnList.slice(0, 12)"
      @setConfig="displaySetting = true"
      @confirmed="handleConfirm"
      ref="deligoChild"
      @close="displayClose"
      v-if="displayAlarms == true"
    ></deligo-alarm-list>
    <alarmSetting
      v-if="displaySetting"
      @saveConfig="getAlarmConfig"
      @cancleConfig="displaySetting = false"
      :alarmConfigArray="alarmConfigArray"
    />
  </div>
</template>

<script>
import deligoAlarmList from "@/components/deligoAlarmList";
import alarmSetting from "@/components/alarm-badge/alarm-setting.vue";
import { ElNotification } from "element-plus";
import { GetDeviceTableData } from "@/api/zhbj/index.js";
import dayjs from "dayjs";
export default {
  name: "alarmBadge",
  components: {
    deligoAlarmList,
    alarmSetting,
  },

  data() {
    return {
      //实时报警弹窗ws
      socketObj1: "", // websocket实例对象
      //心跳检测
      heartCheck1: {
        vueThis1: this, // vue实例
        timeout1: 30000, // 超时时间
        timeoutObj1: null, // 计时器对象——向后端发送心跳检测
        serverTimeoutObj1: null, // 计时器对象——等待后端心跳检测的回复
        // 心跳检测重置
        reset: function () {
          clearTimeout(this.timeoutObj1);
          clearTimeout(this.serverTimeoutObj1);
          return this;
        },
        // 心跳检测启动
        start: function () {
          this.timeoutObj1 && clearTimeout(this.timeoutObj1);
          this.serverTimeoutObj1 && clearTimeout(this.serverTimeoutObj1);
          this.timeoutObj1 = setTimeout(() => {
            // 这里向后端发送一个心跳检测，后端收到后，会返回一个心跳回复
            this.vueThis1.socketObj1.send("HeartBeat");
            console.log("发送心跳检测1");
            this.serverTimeoutObj1 = setTimeout(() => {
              // 如果超过一定时间还没重置计时器，说明websocket与后端断开了
              console.log("未收到心跳检测回复1");
              // 关闭WebSocket
              this.vueThis1.socketObj1.close();
            }, this.timeout1);
          }, this.timeout1);
        },
      },
      socketReconnectTimer1: null, // 计时器对象——重连
      socketReconnectLock1: false, // WebSocket重连的锁
      socketLeaveFlag1: false, // 离开标记（解决 退出登录再登录 时出现的 多次相同推送 问题，出现的本质是多次建立了WebSocket连接）
      alarmList: [],
      dialogList: [],
      //实时报警图标相关
      x: null,
      y: null,
      currentX: 0,
      currentY: 0,
      displayAlarms: false,
      indexNum: 0,
      data1: 0,
      dragging: false,

      initialX: 0,
      initialY: 0,
      timer: null,
      firstTime: null,
      lastTime: null,
      key: false,
      //请求参数
      requestAlarmHistoryParams: [
        {
          alarmType: "booststation",
          deviceType: "",
        },
        {
          alarmType: "inverter",
          deviceType: "",
        },
        {
          alarmType: "windturbine",
          deviceType: "",
        },
      ],
      alarmConfigArray: [],
      displaySetting: false,
      seriousWarning: false,
      audioElement: null,
    };
  },
  computed: {
    warnLength() {
      return this.$store.state.warnList.length;
    },
    warnList() {
      return this.$store.state.warnList;
    },
    isLogined() {
      return this.$store.state.user?.loginState;
    },
  },
  created() {
    this.getAlarmConfig();
    this.x = window.innerWidth - 82;
    this.y = window.innerHeight - 32;
    let requestResult = [];
    this.requestAlarmHistoryParams.forEach(({ alarmType }) => {
      requestResult.push(this.getAlarmHistory(alarmType));
    });

    Promise.all(requestResult)
      .then((promiseResult) => {
        promiseResult.forEach(({ data }) => {
          data?.records?.forEach((ele) => {
            this.pushALarmItem(ele);
          });
        });
        this.dialogList.sort((a, b) => {
          return b.lv - a.lv;
        });
        this.$store.commit("changeAlarmlist", this.alarmList);
        this.$store.commit("setWarning", this.dialogList);
        if (!this.socketLeaveFlag) {
          // 没有离开——重连
          // websocket重连
          this.socketReconnect1();
        }
      })
      .catch(() => {
        requestResult.forEach((ele, index) => {
          ele
            .then(({ data }) => {
              data?.ls?.forEach((ele) => {
                this.pushALarmItem(ele);
              });
            })
            .catch((error) => {
              ElNotification({
                type: "error",
                title: "查询历史未处理报警请求出错！",
                dangerouslyUseHTMLString: true,
                message: `<div class="currentRequestErrorNotification">
                                <p><span>主要参数：</p>
                                <p style="color:var(--el-color-primary)"><span class="errorTitle">alarmType:</span><span class="errorDesc">"${this.requestAlarmHistoryParams[index].alarmType}"</span></p>
                                <p style="color:var(--el-color-primary)"><span class="errorTitle">deviceType:</span><span class="errorDesc">"${this.requestAlarmHistoryParams[index].deviceType}"</span></p>
                                <p style="color:var(--el-color-danger)"><span class="errorTitle">错误正文:</span><span class="errorDesc">${error}</span></p>
                             </div>`,
              });
            });
        });
      });
  },
  mounted() {},
  unmounted() {
    console.log("离开标记", this.socketLeaveFlag);
  },
  methods: {
    setting() {
      this.displaySetting = true;
    },

    handleConfirm(flag) {
      this.playAudioEffect();
      if (flag) {
        this.dialogList = [];
        this.$store.commit("setWarning", this.dialogList);
        setTimeout(() => {
          this.$refs.deligoChild && this.$refs.deligoChild.init(this.warnList);
        }, 0);
      }
    },
    playAudioEffect() {
      const lv1Config = this.getConfigItem(1);
      let lv1Play = false;
      if (lv1Config.isAlarmSound) {
        lv1Play = this.dialogList.some((ele) => {
          return ele.lv === 1 && !ele.confirm;
        });
      }

      const lv2Config = this.getConfigItem(2);
      let lv2Play = false;
      if (lv2Config.isAlarmSound) {
        lv2Play = this.dialogList.some((ele) => {
          return ele.lv === 2 && !ele.confirm;
        });
      }

      const lv3Config = this.getConfigItem(3);
      let lv3Play = false;
      if (lv3Config.isAlarmSound) {
        lv3Play = this.dialogList.some((ele) => {
          return ele.lv === 3 && !ele.confirm;
        });
      }

      const lv4Config = this.getConfigItem(4);
      let lv4Play = false;
      if (lv4Config.isAlarmSound) {
        lv4Play = this.dialogList.some((ele) => {
          return ele.lv === 4 && !ele.confirm;
        });
      }

      const lv5Config = this.getConfigItem(5);
      let lv5Play = false;
      if (lv5Config.isAlarmSound) {
        lv5Play = this.dialogList.some((ele) => {
          return ele.lv === 5 && !ele.confirm;
        });
      }
      //   console.log(lv1Play, lv2Play, lv3Play, lv4Play, lv5Play);
      if (lv5Play && !this.seriousWarning) {
        this.seriousWarning = true;
        this.audioElement = new Audio();
        this.audioElement.src = "./static/sound/lv5.mp3";
        this.audioElement.loop = true;
        this.audioElement?.play();
      } else if (
        (lv1Play || lv2Play || lv3Play || lv4Play) &&
        !this.seriousWarning
      ) {
        this.audioElement = new Audio();
        this.audioElement.src = "./static/sound/lv4.mp3";
        this.audioElement.addEventListener("ended", () => {
          this.audioElement?.removeEventListener(
            "ended",
            this.stopPlayAudioEffect
          );
        });
        this.audioElement?.play();
      } else {
        if (!this.seriousWarning) {
          this.stopPlayAudioEffect();
        }
      }
    },

    stopPlayAudioEffect() {
      this.seriousWarning = false;
      if (this.audioElement) {
        this.audioElement.pause();
        this.audioElement.currentTime = 0;
        this.audioElement.loop = false;
      }
      this.audioElement = null;
    },
    //获取报警配置
    getAlarmConfig() {
      if (localStorage.getItem("alarmConfigArray")) {
        this.alarmConfigArray = JSON.parse(
          localStorage.getItem("alarmConfigArray")
        );
      } else {
        this.alarmConfigArray = [
          {
            id: "1",
            alarmLevel: 1,
            isAlart: false,
            isAlarmSound: false,
            isContinuousAlarm: false,
          },
          {
            id: "2",
            alarmLevel: 2,
            isAlart: false,
            isAlarmSound: false,
            isContinuousAlarm: false,
          },
          {
            id: "3",
            alarmLevel: 3,
            isAlart: true,
            isAlarmSound: false,
            isContinuousAlarm: false,
          },
          {
            id: "4",
            alarmLevel: 4,
            isAlart: true,
            isAlarmSound: true,
            isContinuousAlarm: false,
          },
          {
            id: "5",
            alarmLevel: 5,
            isAlart: true,
            isAlarmSound: true,
            isContinuousAlarm: true,
          },
        ];
        localStorage.setItem(
          "alarmConfigArray",
          JSON.stringify(this.alarmConfigArray)
        );
      }
    },
    getAlarmName(alarmItem) {
      let alarmName = "";
      if (alarmItem.deviceType === "booststation") {
        alarmName = "升压站报警";
      } else if (alarmItem.deviceType === "inverter") {
        alarmName = "光伏报警";
      } else if (alarmItem.deviceType === "windturbine") {
        alarmName = "设备报警";
      } else if (alarmItem.deviceType === "station") {
        alarmName = "场站";
      }

      if (alarmItem.alarmType === "custom") {
        alarmName = "自定义报警";
      }
      return alarmName;
    },

    getLvName(alarmItem) {
      if (alarmItem.rank === 1) {
        return "低级";
      } else if (alarmItem.rank === 2) {
        return "低中级";
      } else if (alarmItem.rank === 3) {
        return "中级";
      } else if (alarmItem.rank === 4) {
        return "中高级";
      } else if (alarmItem.rank === 5) {
        return "高级";
      }
    },
    //查历史报警
    getAlarmHistory(alarmType) {
      let params = {
        pageNum: 1,
        pageSize: 5000,
        alarmId: "",
        alarmType,
        stationid: "",
        deviceid: "",
        modelId: "",
        components: "",
        description: "",
        isclose: false,
        begin: "",
        end: "",
      };
      if (params.alarmType == "windturbine") {
        params.stationid = "SXJ_KGDL_DJY_FDC_STA";
      } else if (params.alarmType == "inverter") {
        params.stationid = "SXJ_KGDL_JR_GDC_STA";
      }
      return GetDeviceTableData(params, 12000);
    },
    pushALarmItem(alarmItem, type) {
      const configItem = this.getConfigItem(alarmItem.rank);
      const alarmOption = {
        id: alarmItem.id ? alarmItem.id : alarmItem.tbname,
        lv: alarmItem.rank,
        lvName: this.getLvName(alarmItem),
        rank: alarmItem.rank,
        class: `animate__bounceInRight lv${alarmItem.rank}`,
        deviceId: alarmItem.deviceId,
        faultCause: alarmItem.faultCause,
        resolvent: alarmItem.resolvent,
        characteristic: alarmItem.characteristic,
        code: alarmItem.code,
        wpName: alarmItem.stationName
          ? alarmItem.stationName
          : alarmItem.wpName,
        stationId: alarmItem.stationId ? alarmItem.stationId : alarmItem.wpId,
        isClose: alarmItem.closeTime ? true : alarmItem.endts ? true : false,
        isCloseName: alarmItem.closeTime
          ? "已解除"
          : alarmItem.endts
          ? "已解除"
          : "未解除",
        alarmId: alarmItem.alarmId,
        alarmType: alarmItem.alarmType,
        alarmName: this.getAlarmName(alarmItem),
        description: alarmItem.description,
        deviceType: alarmItem.deviceType,
        oval: alarmItem.oval,
        triggerType: alarmItem.triggerType,
        ts: alarmItem.ts
          ? dayjs(alarmItem.ts).valueOf()
          : dayjs(alarmItem.updateTime).valueOf(),
        endts: alarmItem.endts
          ? dayjs(alarmItem.endts).format("YYYY-MM-DD HH:mm:ss")
          : null,
        closeTime: alarmItem.closeTime
          ? dayjs(alarmItem.closeTime).format("YYYY-MM-DD HH:mm:ss")
          : null,
        deviceName: alarmItem.deviceName
          ? alarmItem.deviceName
          : alarmItem.code,
        tsName: alarmItem.ts
          ? new Date(alarmItem.ts).formatDate("MM-dd hh:mm:ss")
          : new Date(alarmItem.updateTime).formatDate("MM-dd hh:mm:ss"),
        fullTsName: alarmItem.ts
          ? new Date(alarmItem.ts).formatDate("yyyy-MM-dd hh:mm:ss")
          : new Date(alarmItem.updateTime).formatDate("yyyy-MM-dd hh:mm:ss"),
      };
      if (
        alarmItem.alarmType == "booststation" &&
        alarmItem.deviceType != "custom"
      ) {
        if (
          configItem.isAlarmSound ||
          configItem.isAlart ||
          configItem.isContinuousAlarm
        ) {
          let a = {};
          a[`${alarmItem.stationId}`] = alarmItem.closeTime ? false : true;
          this.alarmList.push(a);
          this.alarmList = [
            ...new Set(this.alarmList.map((t) => JSON.stringify(t))),
          ].map((s) => JSON.parse(s));
        }
      }
      if (
        (configItem.isAlarmSound ||
          configItem.isAlart ||
          configItem.isContinuousAlarm) &&
        alarmItem.deviceType != "custom"
      ) {
        if (type && type == "ws") {
          this.dialogList.unshift(alarmOption);
        } else {
          this.dialogList.push(alarmOption);
        }
      }
      this.playAudioEffect();
    },
    getConfigItem(lv) {
      return (
        this.alarmConfigArray.find((ele) => {
          return ele.alarmLevel === lv;
        }) || {}
      );
    },

    // 拖拽相关
    startDrag(event) {
      this.currentX = event.clientX;
      this.currentY = event.clientY;
    },
    stopDrag(event) {
      let x = event.clientX - this.currentX;
      let y = event.clientY - this.currentY;
      this.x += x;
      if (this.x < 60) {
        this.x = 60;
      } else if (this.x > window.innerWidth - 20) {
        this.x = window.innerWidth - 82;
      }
      this.y += y;
      if (this.y > window.innerHeight - 20) {
        this.y = window.innerHeight - 32;
      } else if (this.y < 0) {
        this.y = 0;
      }
    },
    //开关列表
    displayAlarm(val) {
      this.displayAlarms = !this.displayAlarms;
      if (this.displayAlarms == true) {
        setTimeout(() => {
          this.$refs.deligoChild && this.$refs.deligoChild.init(this.warnList);
        }, 0);
      }
    },
    displayClose() {
      this.displayAlarms = false;
    },

    // websocket启动
    createWebSocket1() {
      //   let webSocketLink = `ws://192.168.1.102:6014/websocket/${this.$store.state.user.userId}_${this.$store.state.user.authToken}`;
      let webSocketLink1 = `ws://10.81.3.154:6014/websocket/${this.$store.state.user.userId}_${this.$store.state.user.authToken}`; // webSocket地址
      try {
        if ("WebSocket" in window) {
          this.socketObj1 = new WebSocket(webSocketLink1);
        }
        // websocket事件绑定
        this.socketEventBind1();
      } catch (e) {
        console.log("catch" + e);
        // websocket重连
        this.socketReconnect1();
      }
    },
    // websocket事件绑定
    socketEventBind1() {
      // 连接成功建立的回调
      this.socketObj1.onopen = this.onopenCallback1;
      // 连接发生错误的回调
      this.socketObj1.onerror = this.onerrorCallback1;
      // 连接关闭的回调
      this.socketObj1.onclose = this.oncloseCallback1;
      // 向后端发送数据的回调
      this.socketObj1.onsend = this.onsendCallback1;
      // 接收到消息的回调
      this.socketObj1.onmessage = this.getMessageCallback1;

      //监听窗口关闭事件，当窗口关闭时，主动去关闭websocket连接，防止连接还没断开就关闭窗口，server端会抛异常。
      window.onbeforeunload = () => {
        this.socketObj1.close();
      };
    },
    // websocket重连
    socketReconnect1() {
      if (this.socketReconnectLock1) {
        return;
      }
      this.socketReconnectLock1 = true;
      this.socketReconnectTimer1 && clearTimeout(this.socketReconnectTimer1);
      this.socketReconnectTimer1 = setTimeout(() => {
        console.log("WebSocket1:重连中...");
        this.socketReconnectLock1 = false;
        // websocket启动
        this.createWebSocket1();
      }, 4000);
    },
    // 连接成功建立的回调
    onopenCallback1: function (event) {
      console.log("WebSocket1:已连接");
      // 心跳检测重置
      this.heartCheck1.reset().start();
    },
    // 连接发生错误的回调
    onerrorCallback1: function (event) {
      console.log("WebSocket1:发生错误");
      // websocket重连
      this.socketReconnect1();
    },
    // 连接关闭的回调
    oncloseCallback1: function (event) {
      console.log("WebSocket1:已关闭");
      // 心跳检测重置
      this.heartCheck1.reset();
      if (!this.socketLeaveFlag1) {
        // 没有离开——重连
        // websocket重连
        this.socketReconnect1();
      }
    },
    // 向后端发送数据的回调
    onsendCallback1: function () {
      console.log("WebSocket1:发送信息给后端");
    },
    // 接收到消息的回调
    getMessageCallback1: function (msg) {
      //   console.log(msg);
      if (Object.keys(msg) && msg.data == "ok") {
        // 心跳回复——心跳检测重置
        // 收到心跳检测回复就说明连接正常
        console.log("收到心跳检测回复1");
        // 心跳检测重置
        this.heartCheck1.reset().start();
      } else {
        // 普通推送——正常处理
        console.log("收到推送消息1");

        let data = JSON.parse(msg.data);
        // 相关处理
        if (data) {
          this.pushALarmItem(data, "ws");
          //   this.dialogList.sort((a, b) => {
          //     return b.lv - a.lv;
          //   });
          this.$store.commit("changeAlarmlist", this.alarmList);
          this.$store.commit("setWarning", this.dialogList);
        }
      }
    },
  },

  watch: {
    isLogined: {
      handler(res) {
        if (!res && this.socketObj1) {
          // 离开标记
          this.socketLeaveFlag1 = true;
          // 关闭WebSocket
          this.socketObj1.close();
        }
      },
      immediate: true,
    },
  },
};
</script>

<style lang="less" scoped>
.alarmDeligo {
  z-index: 2003;
  position: relative;

  img {
    width: 43px;
    max-width: 43px;
    height: 43px;
    z-index: 3;
  }

  img:first-child {
    width: 53px;
    height: 57px;
    max-width: 53px;
    top: -7px;
    left: -5px;
    position: absolute;
    z-index: 3;
  }
}

.el-badge {
  &.active {
    .el-badge__content--danger {
      opacity: 0 !important;
    }
  }
}
.el-badge__content--danger {
  background: #ff4e00 !important;
  border: none !important;
}
.el-badge__content.is-fixed {
  top: 7px !important;
  right: 14px !important;
  z-index: 2003 !important;
}

.trans {
  animation: circleProgess 3s linear infinite;
}

@keyframes circleProgess {
  0% {
    transform: rotateZ(360deg);
  }

  25% {
    transform: rotateZ(270deg);
  }

  50% {
    transform: rotateZ(180deg);
  }

  75% {
    transform: rotateZ(90deg);
  }

  100% {
    transform: rotateZ(0deg);
  }
}
</style>
