<template>
  <div class="app-container">
    <div style="margin-top: 10px">
      <grid-layout
        :layout.sync="layout"
        :col-num="12"
        :row-height="30"
        :is-draggable="draggable"
        :is-resizable="resizable"
        :vertical-compact="true"
        :use-css-transforms="true"
        @layout-created="layoutCreatedEvent"
        @layout-before-mount="layoutBeforeMountEvent"
        @layout-mounted="layoutMountedEvent"
        @layout-ready="layoutReadyEvent"
        @layout-updated="layoutUpdatedEvent"
      >
        <grid-item
          :x="0"
          :y="0"
          :w="6"
          :h="5"
          i="1"
          @resize="resizeEvent"
          @move="moveEvent"
          @resized="resizedEvent"
          @container-resized="containerResizedEvent"
          @moved="movedEvent"
        >
          <p class="item-title">DEVICE</p>
          <div style="padding: 15px">
            <a-select
              style="width: 200px;"
              size="large"
              v-model="device"
              @change="onSelectChange"
              placeholder="请选择设备"
            >
              <a-option
                v-for="(item, index) in deviceList"
                :key="index"
                :value="item"
              >{{ item }}</a-option>
            </a-select>
          </div>
        </grid-item>
        <grid-item
          :x="6"
          :y="0"
          :w="6"
          :h="5"
          i="2"
          @resize="resizeEvent"
          @move="moveEvent"
          @resized="resizedEvent"
          @container-resized="containerResizedEvent"
          @moved="movedEvent"
        >
          <p class="item-title">SYSTEM</p>
          <div class="grid-container">
            <div class="grid-node">
              <h3>host</h3>
              <p>{{ system.host }}</p>
            </div>
            <div class="grid-node">
              <h3>timestamp</h3>
              <p>{{ system.timestamp }}</p>
            </div>
            <div class="grid-node">
              <h3>imei</h3>
              <p>{{ system.imei }}</p>
            </div>
            <div class="grid-node">
              <h3>free_size</h3>
              <p>{{ system.free_size }}</p>
            </div>
          </div>
        </grid-item>
        <grid-item
          :x="0"
          :y="5"
          :w="6"
          :h="5"
          i="3"
          @resize="resizeEvent"
          @move="moveEvent"
          @resized="resizedEvent"
          @container-resized="containerResizedEvent"
          @moved="movedEvent"
        >
          <p class="item-title">EVM</p>
          <div class="grid-container">
            <div class="grid-node">
              <h3>heap_map_size</h3>
              <p>{{ evm.heap_map_size }}</p>
            </div>
            <div class="grid-node">
              <h3>heap_total_size</h3>
              <p>{{ evm.heap_total_size }}</p>
            </div>
            <div class="grid-node">
              <h3>heap_used_size</h3>
              <p>{{ evm.heap_used_size }}</p>
            </div>
            <div class="grid-node">
              <h3>stack_total_size</h3>
              <p>{{ evm.stack_total_size }}</p>
            </div>
            <div class="grid-node">
              <h3>stack_used_size</h3>
              <p>{{ evm.stack_used_size }}</p>
            </div>
          </div>
        </grid-item>
        <grid-item
          :x="6"
          :y="5"
          :w="6"
          :h="5"
          i="4"
          @resize="resizeEvent"
          @move="moveEvent"
          @resized="resizedEvent"
          @container-resized="containerResizedEvent"
          @moved="movedEvent"
        >
          <p class="item-title">LVGL</p>
          <div class="grid-container">
            <div class="grid-node">
              <h3>total_size</h3>
              <p>{{ lvgl.total_size }}</p>
            </div>
            <div class="grid-node">
              <h3>free_cnt</h3>
              <p>{{ lvgl.free_cnt }}</p>
            </div>
            <div class="grid-node">
              <h3>free_size</h3>
              <p>{{ lvgl.free_size }}</p>
            </div>
            <div class="grid-node">
              <h3>free_biggest_size</h3>
              <p>{{ lvgl.free_biggest_size }}</p>
            </div>
            <div class="grid-node">
              <h3>used_cnt</h3>
              <p>{{ lvgl.used_cnt }}</p>
            </div>
            <div class="grid-node">
              <h3>used_pct</h3>
              <p>{{ lvgl.used_pct }}</p>
            </div>
            <div class="grid-node">
              <h3>frag_pct</h3>
              <p>{{ lvgl.frag_pct }}</p>
            </div>
          </div>
        </grid-item>
        <grid-item
          :x="0"
          :y="10"
          :w="12"
          :h="10"
          i="5"
          @resize="resizeEvent"
          @move="moveEvent"
          @resized="resizedEvent"
          @container-resized="containerResizedEvent"
          @moved="movedEvent"
        >
          <div style="width: 100%; height: 100%; overflow-y: auto">
            <p class="item-title">APP</p>
            <div class="grid-container">
              <div class="grid-node">
                <h3>uri</h3>
              </div>
              <div class="grid-node">
                <h3>length</h3>
              </div>
              <div class="grid-node">
                <h3>png_file_size</h3>
              </div>
              <div class="grid-node">
                <h3>png_total_count</h3>
              </div>
              <div class="grid-node">
                <h3>png_uncompressed_size</h3>
              </div>
            </div>
            <div :class="['grid-container', item.highlight ? 'active' : '']" v-for="(item, index) in imageList" :key="index">
              <div class="grid-node"><p>{{ item.uri }}</p></div>
              <div class="grid-node"><p>{{ item.length }}</p></div>
              <div class="grid-node"><p>{{ item.png_file_size }}</p></div>
              <div class="grid-node"><p>{{ item.png_total_count }}</p></div>
              <div class="grid-node"><p>{{ item.png_uncompressed_size }}</p></div>
            </div>
          </div>
        </grid-item>
        <grid-item
          :x="0"
          :y="20"
          :w="12"
          :h="7"
          i="6"
          @resize="resizeEvent"
          @move="moveEvent"
          @resized="resizedEvent"
          @container-resized="containerResizedEvent"
          @moved="movedEvent"
        >
          <SystemChart :chartData="system"></SystemChart>
        </grid-item>
        <grid-item
          :x="0"
          :y="27"
          :w="12"
          :h="7"
          i="7"
          @resize="resizeEvent"
          @move="moveEvent"
          @resized="resizedEvent"
          @container-resized="containerResizedEvent"
          @moved="movedEvent"
        >
          <EvmChart :chartData="evm"></EvmChart>
        </grid-item>
        <grid-item
          :x="0"
          :y="34"
          :w="12"
          :h="7"
          i="8"
          @resize="resizeEvent"
          @move="moveEvent"
          @resized="resizedEvent"
          @container-resized="containerResizedEvent"
          @moved="movedEvent"
        >
          <LvglChart :chartData="lvgl"></LvglChart>
        </grid-item>
      </grid-layout>
    </div>
  </div>
</template>
<script>

import {
  Avatar,
  Row,
  Col,
  Card,
  List,
  Button,
  Form,
  Icon,
  Table,
  Divider,
  Dropdown,
  Input,
  Select,
  DatePicker,
  message,
} from "ant-design-vue";
import PageHeaderWrapper from "@/components/PageHeaderWrapper";
import DescriptionItem from "@/components/DescriptionItem";

import { getWatchList, getMonitorData } from "@/api/openapi";
import EvmChart from "./components/EvmChart";
import LvglChart from "./components/LvglChart";
import SystemChart from "./components/SystemChart";
import { GridLayout, GridItem } from "vue-grid-layout";
import { wsNotify } from "@/utils/notify.js";
export default {
  name: "Monitor",
  data() {
    return {
      watchs: [],
      globalData: null,
      device: null,
      devices: {},
      deviceList: [],
      systemList: [],
      system: {
        host: null,
        imei: null,
        timestamp: null,
      },
      evm: {
        heap_map_size: null,
        heap_total_size: null,
        heap_used_size: null,
        stack_total_size: null,
        stack_used_size: null,
      },
      evmList: [],
      lvgl: {
        total_size: null,
        free_cnt: null,
        free_size: null,
        free_biggest_size: null,
        used_cnt: null,
        used_pct: null,
        frag_pct: null
      },
      lvglList: [],
      image: {},
      imageList: [],
      socket: null,
      form: {
        system: ["free_size", "free_space_size", "used_space_size"],
        lvgl: ["total_size", "free_size", "free_biggest_size"],
        evm: [
          "total_size",
          "free_size",
          "heap_map_size",
          "heap_total_size",
          "heap_used_size",
          "stack_total_size",
          "stack_used_size",
        ],
        image: ["png_uncompressed_size", "png_file_size", "length"],
      },
      layout: [
        { x: 0, y: 0, w: 6, h: 5, i: "1", static: false },
        { x: 6, y: 0, w: 6, h: 5, i: "2", static: true },
        { x: 0, y: 5, w: 6, h: 5, i: "3", static: false },
        { x: 6, y: 5, w: 6, h: 5, i: "4", static: false },
        { x: 0, y: 10, w: 12, h: 10, i: "5", static: false },
        { x: 0, y: 20, w: 12, h: 7, i: "6", static: false },
        { x: 0, y: 27, w: 12, h: 7, i: "7", static: false },
        { x: 0, y: 34, w: 12, h: 7, i: "8", static: false },
      ],
      draggable: true,
      resizable: true,
    };
  },
  components: {
    GridLayout,
    GridItem,
    EvmChart,
    LvglChart,
    SystemChart,
    APageHeaderWrapper: PageHeaderWrapper,
    AAvatar: Avatar,
    ARow: Row,
    ACol: Col,
    ACard: Card,
    ACardGrid: Card.Grid,
    ACardMeta: Card.Meta,
    AList: List,
    AButton: Button,
    AForm: Form,
    AFormItem: Form.Item,
    AIcon: Icon,
    ATable: Table,
    ADescriptionItem: DescriptionItem,
    ADivider: Divider,
    ADropdown: Dropdown,
    AInput: Input,
    ASelect: Select,
    AOption: Select.Option,
    ARangePicker: DatePicker.RangePicker,
  },
  methods: {
    moveEvent(i, newX, newY) {
      const msg = "MOVE i=" + i + ", X=" + newX + ", Y=" + newY;
      console.log(msg);
    },
    movedEvent(i, newX, newY) {
      const msg = "MOVED i=" + i + ", X=" + newX + ", Y=" + newY;
      console.log(msg);
    },
    resizeEvent(i, newH, newW, newHPx, newWPx) {
      const msg =
        "RESIZE i=" +
        i +
        ", H=" +
        newH +
        ", W=" +
        newW +
        ", H(px)=" +
        newHPx +
        ", W(px)=" +
        newWPx;
      console.log(msg);
    },
    resizedEvent(i, newX, newY, newHPx, newWPx) {
      const msg =
        "RESIZED i=" +
        i +
        ", X=" +
        newX +
        ", Y=" +
        newY +
        ", H(px)=" +
        newHPx +
        ", W(px)=" +
        newWPx;
      console.log(msg);
    },
    containerResizedEvent(i, newH, newW, newHPx, newWPx) {
      const msg =
        "CONTAINER RESIZED i=" +
        i +
        ", H=" +
        newH +
        ", W=" +
        newW +
        ", H(px)=" +
        newHPx +
        ", W(px)=" +
        newWPx;
      console.log(msg);
    },
    layoutCreatedEvent(newLayout) {
      console.log("Created layout: ", newLayout);
    },
    layoutBeforeMountEvent(newLayout) {
      console.log("beforeMount layout: ", newLayout);
    },
    layoutMountedEvent(newLayout) {
      console.log("Mounted layout: ", newLayout);
    },
    layoutReadyEvent(newLayout) {
      console.log("Ready layout: ", newLayout);
    },
    layoutUpdatedEvent(newLayout) {
      console.log("Updated layout: ", newLayout);
    },
    fetchData() {
      this.isLoading = true;
      getWatchList()
        .then((res) => {
          if (res.code == 200) this.watchs = res.data;
        })
        .catch((err) => {
          this.$message.warning(err.msg);
        })
        .finally(() => {
          this.isLoading = false;
        });
    },
    queryData() {
      getMonitorData({
        watch: this.device,
      })
        .then((res) => {
          if (res.type == "object") {
            this.evmList = res.data.evm;
            this.lvglList = res.data.lvgl;
            this.imageList = res.data.image;
          }
        })
        .catch((err) => {
          this.$message.warning(err.msg);
        });
    },
    onChange(res) {
      if (!res) return null;

      var t = this.watchs.find((item) => {
        return item.id == res;
      });
      if (t) this.device = t.imei;

      // 清空之前数据
      this.resetData();
    },
    onSubmit() {
      this.queryData();
    },
    onReset(formName) {
      this.$refs[formName].resetFields();
      this.fetchData();
    },
    sendMsg() {
      let message = JSON.stringify({
        type: "auth",
        token: window.sessionStorage.getItem("Authorization"),
      });
      this.socket.send(message);
    },
    handleMessage(msg) {
      if (msg.code == 401) {
        window.sessionStorage.removeItem("Authorization")
        this.$router.push({ path: "/user/login" })
        message.error(msg.msg)
        return null;
      }

      if (msg.type !== "report" || !msg.imei) return null;
      // 如果接收到的数据不是当前选中的设备，那么则直接丢弃
      // 这里可以优化，将所有数据，保存到indexed datebase中
      if (this.device && msg.imei != this.device) return null;

      if (!this.deviceList) {
        this.deviceList = [];
      }
      if (!this.deviceList.includes(msg.imei)) {
        this.deviceList.push(msg.imei);
      }
      if (!this.device) {
        if (this.deviceList && this.deviceList.length)
          this.device = this.deviceList[0];
        else this.device = msg.imei;
      }

      // 处理单位
      this.processData(msg);
      // this.devices[msg.imei] = msg;
      this.globalData = msg;
      this.resetData();
    },
    processData(msg) {
      if (!msg) return null;
      Object.keys(msg).forEach((item) => {
        if (this.form[item]) {
          var keys = this.form[item];
          for (var i = 0; i < keys.length; i++) {
            var k = keys[i];
            if (item == "image") {
              for (var j = 0; j < msg[item].length; j++) {
                msg[item][j][k] = Math.ceil(msg[item][j][k] / 1024);
              }
            } else {
              msg[item][k] = Math.ceil(msg[item][k] / 1024);
            }
          }
        }
      });
    },
    onSelectChange(res) {
      this.device = res;
      // this.processData(this.devices[this.device]);
      // this.resetData();
      console.log(res);
    },
    resetData() {
      wsNotify.eventBus.$emit("resize");

      this.evmList = [{ ...this.globalData.evm }];
      this.lvglList = [{ ...this.globalData.lvgl }];
      this.systemList = [
        {
          imei: this.globalData.imei,
          ...this.globalData.system,
        },
      ];

      // 这里需要特殊处理下，先判断uri是否存在，不存在则添加，存在则更新
      let uris = [];
      this.imageList.forEach((item) => {
        item.highlight = false;
        uris.push(item.uri);
      });
      this.globalData.image &&
        this.globalData.image.forEach((item) => {
          if (item.png_uncompressed_size > 0) {
            item.highlight = true;
          } else {
            item.highlight = false;
          }

          const target = this.imageList.find((img) => img.uri === item.uri);
          if (target) {
            target.length = item.length;
            target.png_total_count = item.png_total_count;
            target.highlight = false;
            if (
              item.png_uncompressed_size &&
              item.png_uncompressed_size !== target.png_uncompressed_size
            )
              {
                target.highlight = true;
                target.png_uncompressed_size = item.png_uncompressed_size;
              }
            if (
              item.png_file_size &&
              item.png_file_size !== target.png_file_size
            )
              target.png_file_size = item.png_file_size;

          } else {
            this.imageList.push(item);
          }
        });

      if (this.globalData) {
        if (this.globalData.evm) this.evm = this.globalData.evm;
        if (this.globalData.lvgl) this.lvgl = this.globalData.lvgl;
        if (this.globalData.image) this.image = this.globalData.image;
        if (this.globalData.system) this.system = this.globalData.system;
      }
    },
  },
  mounted() {},
  created() {
    this.socket = wsNotify;
    wsNotify.eventBus.$on("open", (message) => {
      this.sendMsg();
      this.$nextTick(() => {
        console.log(message);
      });
      // 这里启动一个定时器，10秒钟后，如果没有消息进来，说明当前没有在线设备
    });
    wsNotify.eventBus.$on("close", (message) => {
      this.$nextTick(() => {
        console.log(message);
      });
    });
    wsNotify.eventBus.$on("message", (message) => {
      console.log(message)
      this.$nextTick(() => {
        this.handleMessage(message);
      });
    });
  },
};
</script>
<style lang="scss" scoped>
.app-container {
  & > div.page-wrapper {
    margin: 10px 0px;
  }
}

.grid-container {
  display: flex;
  flex-direction: row;
  & > .grid-node {
    flex: 1;
    & > h3 {
      font-weight: bold;
      font-size: 17px;
    }
    & > h3, p {
      display: flex;
      justify-content: center;
      flex-direction: row;
      align-items: center;
      text-align: center;
      height: 100%;
    }
  }
  &.active {
    color: #fff;
    background-color: #2ECCCD;
  }
}

.vue-grid-layout {
  background: none;
}
.vue-grid-item:not(.vue-grid-placeholder) {
  background: #fff;
  border: 0px solid #eee;
}
.vue-grid-item .resizing {
  opacity: 0.9;
}
.vue-grid-item .static {
  background: #cce;
}
.vue-grid-item .text {
  font-size: 24px;
  text-align: center;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  height: 100%;
  width: 100%;
}
.vue-grid-item .item-title {
  margin: 15px;
}
.vue-grid-item .no-drag {
  height: 100%;
  width: 100%;
}
.vue-grid-item .minMax {
  font-size: 12px;
}
.vue-grid-item .add {
  cursor: pointer;
}
.vue-draggable-handle {
  position: absolute;
  width: 20px;
  height: 20px;
  top: 0;
  left: 0;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><circle cx='5' cy='5' r='5' fill='#999999'/></svg>")
    no-repeat;
  background-position: bottom right;
  padding: 0 8px 8px 0;
  background-repeat: no-repeat;
  background-origin: content-box;
  box-sizing: border-box;
  cursor: pointer;
}
</style>
