<template>
  <div id="HeatMap">
    <div class="container">
      <!-- 控制区：自定义阈值和差值选择框 -->
      <div class="controls" style="margin-bottom: 20px;">
        <label>
          停顿阈值：
          <select v-model="customThreshold">
            <option v-for="v in [1000,2000,3000,4000,5000]" :key="v" :value="v">{{ v }}ms</option>
          </select>
        </label>
        <label style="margin-left: 20px;">
          区间差值：
          <select v-model="customStep">
            <option v-for="v in [500,1000,2000]" :key="v" :value="v">{{ v }}ms</option>
          </select>
        </label>
      </div>
      <!-- 文本和热度图显示区域 -->
      <div class="text-container">
        <div
            v-for="(line, lineIndex) in formattedLines"
            :key="lineIndex"
            class="text-line"
        >
          <!-- 显示文本行 -->
          <span
              v-for="(char, charIndex) in line.chars"
              :key="charIndex"
              class="char"
          >
            {{ char }}
          </span>
          <!-- 显示热度图 -->
          <div
              class="heatmap"
              :style="{ width: `${line.width}px` }"
          >
            <div
                v-for="(item, itemIndex) in line.pauses"
                :key="itemIndex"
                class="heatmap-rect"
                :style="{
                backgroundColor: getColor(item.totalPauseTime),
                left: `${item.position}px`,
                width: `${heatmapRectWidth}px`,
                height: `${heatmapRectHeight}px`
              }"
                :title="`totalPauseTime = ${item.totalPauseTime}ms`"
                @mouseover="showTooltip(item.totalPauseTime, $event)"
                @mouseout="hideTooltip"
            />
          </div>
        </div>
      </div>

      <!-- 颜色图例 -->
      <div class="legend">
        <div
            v-for="(item, index) in colorLegend"
            :key="index"
            class="legend-item"
        >
          <div
              class="legend-color"
              :style="{ backgroundColor: item.color }"
          />
          <span>{{ item.label }}</span>
        </div>
      </div>

      <!-- 提示框 -->
<!--      <div-->
<!--          v-if="tooltipVisible"-->
<!--          class="tooltip"-->
<!--          :style="{ left: `${tooltipX}px`, top: `${tooltipY}px` }"-->
<!--      >-->
<!--        totalPauseTime = {{ tooltipText }}ms-->
<!--      </div>-->
    </div>
  </div>
</template>

<script setup lang="ts">
import {ref, computed, onMounted,type Ref, watch} from 'vue'
import bevaviorApis from '@/apis/behavior'
import {inject} from "vue-demi";
import {ElMessage} from "element-plus";

// 响应式数据 - 控制UI元素尺寸
const charWidth = ref(12) // 普通字符宽度（像素）
const spaceWidth = ref(8) // 空格字符宽度（像素）
const heatmapRectWidth = ref(8) // 热度图矩形宽度（像素）
const heatmapRectHeight = ref(12) // 热度图矩形高度（像素）
const heatmapOffset = ref(5) // 热度图与文本的垂直偏移（像素）
const lineHeight = ref(30) // 文本行高（像素）

// 提示框相关数据
const tooltipVisible = ref(false)
const tooltipText = ref('')
const tooltipX = ref(0)
const tooltipY = ref(0)

// 自定义停顿阈值和区间差值
const customThreshold = ref(2000)
const customStep = ref(1000)

// 动态生成 colorLegend
const colorLegend = computed(() => {
  const arr = []
  let start = customThreshold.value
  let colorArr = ['#FFF6CC', '#FFD699', '#FFA64D', '#FF7519', '#CC2900']
  for (let i = 0; i < colorArr.length - 1; i++) {
    arr.push({
      time: start + i * customStep.value,
      color: colorArr[i],
      label: i === 0
          ? `≤${start}ms`
          : `${start + (i - 1) * customStep.value}-${start + i * customStep.value}ms`
    })
  }
  arr.push({
    time: Infinity,
    color: colorArr[colorArr.length - 1],
    label: `≥${start + (colorArr.length - 2) * customStep.value}ms`
  })
  return arr
})

// 用于存储 events 数据
const actionData = ref([]);
// 这里 studentId 和 assignmentId 可根据实际情况传递

const engagement = inject('currentEngagement') as Ref<any>;
watch(engagement,async () => {
  try {
    studentId = engagement.value.studentId;
    assignmentId = engagement.value.assignmentId;
    const res = await bevaviorApis.getBehaviorRecordAll(studentId, assignmentId)
    if (res.data && res.data.data && Array.isArray(res.data.data.events)) {
      actionData.value = res.data.data.events
    } else {
      actionData.value = []
    }
  } catch (e) {
    actionData.value = []
    // 可加错误提示
  }
})

let studentId = 16
let assignmentId = 7

onMounted(async () => {
  try {
    studentId = engagement.value.studentId;
    assignmentId = engagement.value.assignmentId;
    const res = await bevaviorApis.getBehaviorRecordAll(studentId, assignmentId)
    if (res.data && res.data.data && Array.isArray(res.data.data.events)) {
      actionData.value = res.data.data.events
    } else {
      actionData.value = []
    }
  } catch (e) {
    actionData.value = []
    // 可加错误提示
  }
})

// 计算属性 - 处理原始数据并格式化为多行显示
const formattedLines = computed(() => {
  // 计算每行最大宽度（适应窗口大小）
  const maxLineWidth = Math.min(900, window.innerWidth - 40)
  // 使用Map存储每个位置的字符、第一次操作的startStamp、最后一次操作的startStamp和保留位置
  const positionMap = new Map()
  let lastStartStamp = 0;

  actionData.value.forEach(item => {
    // 只处理 insert、delete、copy 类型的数据条目
    if (["insert", "delete", "copy"].includes(item.type)) {
      const {retain, insert, startStamp} = item
      // 删除操作显示为空格
      const char = item.type === 'delete' ? ' ' : insert

      if (positionMap.has(retain)) {
        // 已有记录，更新字符和最后一次操作的startStamp
        const record = positionMap.get(retain)
        record.char = char
        record.lastStartStamp = startStamp
      } else {
        // 新增记录
        positionMap.set(retain, {
          char,
          firstStartStamp: lastStartStamp,
          lastStartStamp: startStamp,
          retain
        })
      }
      lastStartStamp = startStamp;
    }
  })

  // 计算每个位置的totalPauseTime
  positionMap.forEach(record => {
    record.totalPauseTime = record.lastStartStamp - record.firstStartStamp
  })

  // 将Map转换为数组并按位置排序
  const finalPositions = Array.from(positionMap.values()).sort((a, b) => a.retain - b.retain)
  const lines = []
  // 当前行对象，存储字符、停顿信息和宽度
  let currentLine = {chars: [], pauses: [], width: 0, retainOffset: 0}

  // 处理每个字符，生成多行显示
  finalPositions.forEach(item => {
    // 处理单个字符的函数
    const processCharacter = (char, isFirstChar = false) => {
      // 计算字符宽度（空格和普通字符不同）
      const charWidthVal = char === ' ' ? spaceWidth.value : charWidth.value
      const nextLineWidth = currentLine.width + charWidthVal

      // 如果添加字符后超过最大宽度且当前行已有内容，则换行
      if (nextLineWidth > maxLineWidth && currentLine.chars.length > 0) {
        lines.push(currentLine)
        // 创建新行，计算保留位置偏移量
        currentLine = {
          chars: [],
          pauses: [],
          width: 0,
          retainOffset: lines.reduce((sum, line) => sum + line.chars.length, 0)
        }
      }

      // 添加字符到当前行
      currentLine.chars.push(char)
      currentLine.width += charWidthVal

      // 如果停顿时间超过自定义阈值且是字符的第一个字符，则记录停顿
      if (item.totalPauseTime > customThreshold.value && isFirstChar) {
        // 计算热度图矩形位置（字符中心偏左一点）
        const position = currentLine.chars.length * charWidth.value - (charWidth.value / 1.2)
        currentLine.pauses.push({
          retain: item.retain,
          totalPauseTime: item.totalPauseTime,
          position
        })
      }
    }

    // 处理多字符插入（如复制粘贴的文本）
    if (item.char && item.char.length > 1) {
      item.char.split('').forEach((char, index) => {
        // 只对第一个字符标记停顿
        processCharacter(char, index === 0)
      })
    } else {
      // 处理单字符插入
      processCharacter(item.char, true)
    }
  })

  // 添加最后一行（如果有内容）
  if (currentLine.chars.length > 0) {
    lines.push(currentLine)
  }

  return lines
})

// 根据停顿时间获取对应的颜色
const getColor = (pauseTime) => {
  // 查找第一个满足 pauseTime <= item.time 的颜色项
  const legend = colorLegend.value.find(item => pauseTime <= item.time)
  // 返回找到的颜色，或默认最深的颜色
  return legend?.color || colorLegend.value[colorLegend.value.length - 1].color
}

// 显示提示框
const showTooltip = (totalPauseTime, event) => {
  tooltipVisible.value = true
  tooltipText.value = totalPauseTime
  tooltipX.value = event.clientX
  tooltipY.value = event.clientY
}

// 隐藏提示框
const hideTooltip = () => {
  tooltipVisible.value = false
}
</script>

<style scoped>
#HeatMap {
  display: flex;
  flex-direction: column;
  align-items: center;      /* 垂直居中 */
  height: 500px;            /* 占满整个视口高度 */
  width: 95%;              /* 占满整个宽度 */
}

.container {
  max-width: 1000px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.text-container {
  position: relative;
  margin-bottom: 30px;
}

.text-line {
  position: relative;
  margin-bottom: 25px;
  white-space: nowrap;
}

.char {
  display: inline-block;
  width: v-bind('charWidth + "px"');
  text-align: center;
}

.heatmap {
  position: absolute;
  bottom: -20px;
  left: 0;
  height: v-bind('heatmapRectHeight + "px"');
}

.heatmap-rect {
  position: absolute;
  border-radius: 2px;
  cursor: pointer;
}

.legend {
  display: flex;
  gap: 15px;
  margin-top: 50px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 5px;
}

.legend-color {
  width: 20px;
  height: 20px;
  border-radius: 2px;
}

.tooltip {
  position: absolute;
  background-color: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 5px;
  border-radius: 3px;
  font-size: 12px;
  z-index: 10;
}

.controls {
  font-size: 15px;
  margin-bottom: 20px;
}
.controls label {
  margin-right: 20px;
}
.controls select {
  margin-left: 5px;
  padding: 2px 8px;
}
</style>
