<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">
            <el-select
              size="mini"
              v-model="device"
              @change="onSelectChange"
              placeholder="请选择设备"
            >
              <el-option
                v-for="(item, index) in deviceList"
                :key="index"
                :label="item"
                :value="item"
              ></el-option>
            </el-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>
          <el-table
            element-loading-text="Loading"
            :data="systemList"
            size="mini"
            border
            stripe
            fit
            highlight-current-row
          >
            <el-table-column
              prop="host"
              label="host"
              min-width="150"
              show-overflow-tooltip
            ></el-table-column>
            <el-table-column
              prop="path"
              label="path"
              min-width="150"
              show-overflow-tooltip
            ></el-table-column>
            <el-table-column
              prop="timestamp"
              label="timestamp"
              min-width="150"
              show-overflow-tooltip
            ></el-table-column>
            <el-table-column label="imei" min-width="150" show-overflow-tooltip>
              <template slot-scope="scope">{{ scope.row.imei }}</template>
            </el-table-column>
            <el-table-column
              label="free_size"
              min-width="100"
              show-overflow-tooltip
            >
              <template slot-scope="scope"
                >{{ scope.row.free_size }}(KB)</template
              >
            </el-table-column>
          </el-table>
        </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>
          <el-table
            element-loading-text="Loading"
            :data="evmList"
            size="mini"
            border
            stripe
            fit
            highlight-current-row
          >
            <el-table-column
              label="heap_map_size"
              min-width="150"
              show-overflow-tooltip
            >
              <template slot-scope="scope"
                >{{ scope.row.heap_map_size }}(KB)</template
              >
            </el-table-column>
            <el-table-column
              label="heap_total_size"
              min-width="150"
              show-overflow-tooltip
            >
              <template slot-scope="scope"
                >{{ scope.row.heap_total_size }}(KB)</template
              >
            </el-table-column>
            <el-table-column
              label="heap_used_size"
              min-width="150"
              show-overflow-tooltip
            >
              <template slot-scope="scope"
                >{{ scope.row.heap_used_size }}(KB)</template
              >
            </el-table-column>
            <el-table-column
              label="stack_total_size"
              min-width="150"
              show-overflow-tooltip
            >
              <template slot-scope="scope"
                >{{ scope.row.stack_total_size }}(KB)</template
              >
            </el-table-column>
            <el-table-column
              label="stack_used_size"
              min-width="150"
              show-overflow-tooltip
            >
              <template slot-scope="scope"
                >{{ scope.row.stack_used_size }}(KB)</template
              >
            </el-table-column>
          </el-table>
        </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>
          <el-table
            element-loading-text="Loading"
            :data="lvglList"
            size="mini"
            border
            stripe
            fit
            highlight-current-row
          >
            <el-table-column
              label="total_size"
              min-width="100"
              show-overflow-tooltip
            >
              <template slot-scope="scope"
                >{{ scope.row.total_size }}(KB)</template
              >
            </el-table-column>
            <el-table-column
              prop="free_cnt"
              label="free_cnt"
              min-width="100"
              show-overflow-tooltip
            ></el-table-column>
            <el-table-column
              label="free_size"
              min-width="120"
              show-overflow-tooltip
            >
              <template slot-scope="scope"
                >{{ scope.row.free_size }}(KB)</template
              >
            </el-table-column>
            <el-table-column label="free_biggest_size" min-width="120">
              <template slot-scope="scope"
                >{{ scope.row.free_biggest_size }}(KB)</template
              >
            </el-table-column>
            <el-table-column label="used_cnt" min-width="100">
              <template slot-scope="scope">{{ scope.row.used_cnt }}</template>
            </el-table-column>
            <el-table-column label="used_pct" min-width="100">
              <template slot-scope="scope"
                >{{ scope.row.used_pct }}(%)</template
              >
            </el-table-column>
            <el-table-column label="frag_pct" min-width="100">
              <template slot-scope="scope"
                >{{ scope.row.frag_pct }}(%)</template
              >
            </el-table-column>
          </el-table>
        </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>
            <el-table
              element-loading-text="Loading"
              :data="imageList"
              size="mini"
              border
              stripe
              fit
              highlight-current-row
            >
              <el-table-column
                prop="uri"
                label="uri"
                min-width="150"
                show-overflow-tooltip
              ></el-table-column>
              <el-table-column
                label="length"
                min-width="150"
                show-overflow-tooltip
              >
                <template slot-scope="scope"
                  >{{ scope.row.length }}(KB)</template
                >
              </el-table-column>
              <el-table-column
                label="png_file_size"
                min-width="150"
                show-overflow-tooltip
              >
                <template slot-scope="scope"
                  >{{ scope.row.png_file_size }}(KB)</template
                >
              </el-table-column>
              <el-table-column
                prop="png_total_count"
                label="png_total_count"
                min-width="150"
                show-overflow-tooltip
              ></el-table-column>
              <el-table-column
                label="png_uncompressed_size"
                min-width="150"
                show-overflow-tooltip
              >
                <template slot-scope="scope"
                  >{{ scope.row.png_uncompressed_size }}(KB)</template
                >
              </el-table-column>
            </el-table>
          </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 { getWatchList, getMonitorData } from "@/api/index";
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/eventBus.js";
export default {
  name: "Monitor",
  data() {
    return {
      watchs: [],
      globalData: null,
      device: null,
      devices: {},
      deviceList: null,
      system: {},
      systemList: [],
      evm: {},
      evmList: [],
      lvgl: {},
      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,
  },
  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: this.$store.getters.token,
      });
      this.socket.send(message);
    },
    handleMessage(msg) {
      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, ...this.globalData.request }];

      // 这里需要特殊处理下，先判断uri是否存在，不存在则添加，存在则更新
      let uris = [];
      this.imageList.forEach((img) => {
        uris.push(img.uri);
      });
      this.globalData.image &&
        this.globalData.image.forEach((item) => {
          const target = this.imageList.find(img => img.uri === item.uri)
          if (target) {
            if (item.png_uncompressed_size && item.png_uncompressed_size !== target.png_uncompressed_size)
              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
            target.length = item.length
            target.png_total_count = item.png_total_count
          } 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) => {
      this.$nextTick(() => {
        this.handleMessage(message);
      });
    });
  },
};
</script>
<style lang="scss" scoped>
.app-container {
  & > div.page-wrapper {
    margin: 10px 0px;
  }
}

.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-left: 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>
