<script lang="ts" setup>
import {useMainLayoutStore} from "~/strores/UseMainLayoutStore";
import VChart from "vue-echarts";
import dayjs from "dayjs";
import {useDataStore} from "~/strores/DataStore";

const mainLayoutStore = useMainLayoutStore()
type MemoryInfo = {
  [key: string]: any
}
const lsMemory = ref<MemoryInfo[]>([])
const dataStore = useDataStore()
const colorMode = useColorMode()
const getSystemInfo = () => {
  $fetch(`/Api/Server/GetServerMemoryInfo`, {
    method: 'GET',
    responseType: "json",
    params: {
      serverId: mainLayoutStore.SelectServer.id
    },
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${useCookie('token').value}`
    },
    baseURL: useRuntimeConfig().public.baseUrl
  }).then((res) => {
    const data = res as any
    //转换json
    lsMemory.value = data
    console.log(data)
  })
}
onMounted(() => {
  getSystemInfo();
})
watch(() => mainLayoutStore.SelectServer, () => {
  getSystemInfo();
})
const values = ref<(number | null)[]>([...Array.from({length: 61}, (_, index) => null)])
const hoursValue = ref<(number | null)[]>([...Array.from({length: 61}, (_, index) => null)])
const dayValue = ref<(number | null)[]>([...Array.from({length: 13}, (_, index) => null)])
const option = computed(() => {
  return {
    animation: false,
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: Array.from({length: values.value.length}, (_, index) => dayjs().add(-index, 's').toString()),
      splitLine: {
        show: true,
        lineStyle: {
          color: ['rgba(0,115,244,0.3)'],
          width: 2,
          type: 'solid'
        }
      }
    },
    grid: {
      left: '0',
      right: '0',
      bottom: '0',
      top: '0',
      show: true,
    },
    yAxis: {
      type: 'value',
      min: 0,
      max: 100,
      splitNumber: 10,
      splitLine: {
        show: true,
        lineStyle: {
          color: ['rgba(0,115,244,0.3)'],
          width: 2,
          type: 'solid'
        }
      }
    },
    series: [
      {
        data: values.value,
        color: ['#5c9be8'],
        type: 'line',
        areaStyle: {}
      }
    ],
  }
})
const optionHours = computed(() => {
  return {
    animation: false,
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: Array.from({length: hoursValue.value.length}, (_, index) => dayjs().add(-index, 'h').toString()),
      splitLine: {
        show: true,
        lineStyle: {
          color: ['rgba(0,115,244,0.3)'],
          width: 2,
          type: 'solid'
        }
      }
    },
    grid: {
      left: '0',
      right: '0',
      bottom: '0',
      top: '0',
      show: true,
    },
    yAxis: {
      type: 'value',
      min: 0,
      max: 100,
      splitNumber: 10,
      splitLine: {
        show: true,
        lineStyle: {
          color: ['rgba(0,115,244,0.3)'],
          width: 2,
          type: 'solid'
        }
      }
    },
    series: [
      {
        data: hoursValue.value,
        color: ['#5c9be8'],
        type: 'line',
        areaStyle: {}
      }
    ],
  }
})
const optionDay = computed(() => {
  return {
    animation: false,
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: Array.from({length: dayValue.value.length}, (_, index) => dayjs().add(-index, 'h').toString()),
      splitLine: {
        show: true,
        lineStyle: {
          color: ['rgba(0,115,244,0.3)'],
          width: 2,
          type: 'solid'
        }
      }
    },
    grid: {
      left: '0',
      right: '0',
      bottom: '0',
      top: '0',
      show: true,
    },
    yAxis: {
      type: 'value',
      min: 0,
      max: 100,
      splitNumber: 10,
      splitLine: {
        show: true,
        lineStyle: {
          color: ['rgba(0,115,244,0.3)'],
          width: 2,
          type: 'solid'
        }
      }
    },
    series: [
      {
        data: dayValue.value,
        color: ['#5c9be8'],
        type: 'line',
        areaStyle: {}
      }
    ],
  }
})
let Interval: NodeJS.Timeout
let IntervalHours: NodeJS.Timeout
let IntervalRefresh: NodeJS.Timeout
let minutesTemp: number[] = []
onMounted(() => {
  nextTick(() => {
    Interval = setInterval(() => {
      let data: number = Number(dataStore.data["MemoryTotalUsage"])
      //随机抖动-5,+5
      const jitter = Math.random() * 2 - 1
      data = Number((data + jitter).toFixed(2))
      values.value.push(data)
      minutesTemp.push(data)
      values.value.shift()
    }, 1000)
    IntervalHours = setInterval(() => {
      //data为minutesTemp的均值
      let data: number = minutesTemp.reduce((a, b) => a + b, 0) / minutesTemp.length
      data = Number((data).toFixed(2))
      hoursValue.value.push(data)
      values.value.shift()
    }, 60000)
    IntervalRefresh = setInterval(() => {
      getHistoryData()
    }, 600000)
  })

})
watch(() => mainLayoutStore.SelectServer.id, () => {
  values.value = [...Array.from({length: 61}, (_, index) => null)]
  getHistoryData()
})
onBeforeUnmount(() => {
  clearInterval(Interval)
  clearInterval(IntervalHours)
  clearInterval(IntervalRefresh)
})
const getHistoryData = () => {
  values.value = dataStore.dataHistory.data["MemoryTotalUsage"].slice(-60).map(x => Number(x))
  setTimeout(() => {
    $fetch('/Api/Server/GetServerHistoryStep', {
      method: 'GET',
      params: {
        ServerId: mainLayoutStore.SelectServer.id,
        DataType: 'MemoryTotalUsage',
        timeRange: '1h'
      },
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${useCookie('token').value}`
      },
      baseURL: useRuntimeConfig().public.baseUrl
    }).then((res: any) => {
      hoursValue.value = res.data
    })
  }, 1000)
  setTimeout(() => {
    $fetch('/Api/Server/GetServerHistoryStep', {
      method: 'GET',
      params: {
        ServerId: mainLayoutStore.SelectServer.id,
        DataType: 'MemoryTotalUsage',
        timeRange: '1d'
      },
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${useCookie('token').value}`
      },
      baseURL: useRuntimeConfig().public.baseUrl
    }).then((res: any) => {
      dayValue.value = res.data
    })
  }, 2000)
}
onBeforeMount(() => {
  getHistoryData()
})

</script>

<template>
  <div class="memory-layout">
    <div class="left-chart">
      <div class="memory-title">
        <h1>CPU</h1>
        <h2>{{ (Number(dataStore.data["MemoryTotal"]) / 1024 / 1024).toFixed(2) }} GB</h2>
      </div>
      <div class="memory-chart-top">
        <p>内存使用率</p>
        <p>100%</p>
      </div>
      <div class="memory-chart">
        <v-chart
            :option="option"
            autoresize
            class="chart"/>
      </div>
      <div class="memory-chat-bottom">
        <p>1分钟</p>
        <p>0</p>
      </div>
      <div class="memory-chart-top">
        <p>内存组成</p>
      </div>
      <div class="memory-composition-chart">
        <div :style="{
          width:`${dataStore.data['MemoryTotalUsage']}%`
        }" class="composition"></div>
        <div :style="{
          width:`${dataStore.data['SwapTotalUsage']}%`
        }" class="composition"></div>
        <div class="composition"></div>
      </div>
      <div class="memory-chart-top">
        <p>内存使用率</p>
        <p>100%</p>
      </div>
      <div class="memory-chart">
        <v-chart
            :option="optionHours"
            autoresize
            class="chart"/>
      </div>
      <div class="memory-chat-bottom">
        <p>1小时</p>
        <p>0</p>
      </div>
      <div class="memory-chart-top">
        <p>内存使用率</p>
        <p>100%</p>
      </div>
      <div class="memory-chart">
        <v-chart
            :option="optionDay"
            autoresize
            class="chart"/>
      </div>
      <div class="memory-chat-bottom">
        <p>1天</p>
        <p>0</p>
      </div>
    </div>
    <div class="right-info">
      <div class="info-title-box">
        <div class="info-title">
          <p>使用中</p>
          <h2>{{ (Number(dataStore.data["MemoryUsed"]) / 1024 / 1024).toFixed(2) }} GB</h2>
        </div>
        <div class="info-title">
          <p>可用</p>
          <h2>{{ (Number(dataStore.data["MemoryFree"]) / 1024 / 1024).toFixed(2) }} GB</h2>
        </div>
        <div class="info-title">
          <p>已提交</p>
          <h2>{{
              ((Number(dataStore.data["MemoryTotal"]) - Number(dataStore.data["MemoryCache"])) / 1024 / 1024).toFixed(2)
            }} GB</h2>
        </div>
        <div class="info-title">
          <p>已缓存</p>
          <h2>{{ (Number(dataStore.data["MemoryCache"]) / 1024 / 1024).toFixed(2) }} GB</h2>
        </div>
        <div class="info-title">
          <p>已使用交换空间</p>
          <h2>{{ (Number(dataStore.data["SwapUsed"]) / 1024).toFixed(2) }} KiB</h2>
        </div>
        <div class="info-title">
          <p>可用交换空间</p>
          <h2>{{ (Number(dataStore.data["SwapFree"]) / 1024 / 1024).toFixed(2) }} GB</h2>
        </div>
      </div>
      <div class="other-info-box">
        <div v-for="info in lsMemory" class="other-info">
          <p>{{ info.description !== '[empty]' ? info.description : info.id }}</p>
          <p>{{ info.size ?? info.handle }}</p>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
@import "base";

.memory-layout {
  padding: $padding*1.5;
  display: grid;
  grid-template-columns: 1fr 300px;
  grid-template-rows: 1fr;
  gap: $gap*2;
}

.left-chart {
  display: flex;
  flex-direction: column;
  gap: $gap;

  .memory-title {
    display: flex;
    justify-content: space-between;
    align-items: center;

    .dark-mode & {
      h1, h2 {
        color: $dark-text-color;
      }
    }

    h1, h2 {
      color: $light-text-color;
    }

    h1 {
      font-size: 32px;
    }
  }
}

.memory-chart-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.memory-chart {
  flex: 1;
  border: 4px solid #5c9be8;
  border-radius: $radius*2;
  height: min-content;
  max-height: 32rem;
  min-height: 24rem;
  overflow: hidden;
}

.memory-composition-chart {
  height: 80px;
  border: 4px solid #5c9be8;
  border-radius: $radius*2;
  display: flex;
  overflow: hidden;

  .composition {
    border-right: 2px solid #5c9be8;
    transition: width 0.3s ease-in-out;
  }

  .composition:first-of-type {
    background: rgba(92, 155, 232, 0.75);
    width: 20px;
  }

  .composition:nth-of-type(2) {
    background: rgba(92, 155, 232, 0.3);
    width: 20px;
  }

  .composition:last-of-type {
    flex: 1;
    border-right: unset;
  }
}

.memory-chat-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.info-title-box {
  display: flex;
  flex-wrap: wrap;
  gap: $gap*2;

  .info-title {
    display: flex;
    flex-direction: column;
    gap: $gap*.5;
  }

  .info-title:nth-of-type(2) {
    width: 60%;
  }
}

.other-info-box {
  display: flex;
  flex-direction: column;
  gap: $gap*.5;

  .other-info {
    display: flex;
    gap: $gap;

    p:first-of-type {
      font-weight: 500;
    }

    p {
      flex: 1;
    }
  }
}

.right-info {
  display: flex;
  flex-direction: column;
  gap: $gap*2;
}
</style>