<template>
  <div class="app-container">
    <div ref="topContainerRef">
      <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
        <el-form-item label="地图名称" prop="corpusName">
          <el-input v-model="queryParams.corpusName" placeholder="请输入地图名称" clearable @keyup.enter="handleQuery" />
        </el-form-item>
        <el-form-item label="地图描述" prop="voiceType">
          <el-input v-model="queryParams.voiceType" placeholder="请输入地图描述" clearable @keyup.enter="handleQuery" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
          <el-button icon="Refresh" @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>

      <el-row :gutter="10" class="mb8">
        <el-col :span="1.5">
          <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
        </el-col>
        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
      </el-row>
    </div>

    <div :style="containerHeight">
      <el-table v-loading="loading" height="100%" style="width: 100%" :data="tableDataList">
        <el-table-column label="地图名称" align="center" prop="corpusName" />
        <el-table-column label="地图描述" align="center" prop="textContent" min-width="160" show-overflow-tooltip />
        <el-table-column label="创建人" align="center" prop="status" />
        <el-table-column label="创建时间" align="center" prop="status" />
        <el-table-column label="操作" class-name="small-padding fixed-width" width="200" fixed="right">
          <template #default="scope">
            <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
            <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize" @pagination="getList" />
    </div>

    <!-- 添加或修改语料库对话框 -->
    <el-dialog :title="title" v-model="open" width="580px" append-to-body>
      <el-form ref="corpusRef" :model="form" :rules="rules" label-width="120px">
        <el-form-item label="地图名称" prop="corpusName">
          <el-input v-model="form.corpusName" placeholder="请输入地图名称" />
        </el-form-item>
        <el-form-item label="地图描述" prop="textContent">
          <el-input v-model="form.textContent" type="textarea" placeholder="请输入地图描述" />
        </el-form-item>
        <el-form-item label="选择机器人地图" prop="dialect">
          <el-col :span="11">
            <el-form-item prop="date1">
              <el-select v-model="form.robotId" placeholder="请选择机器人" clearable style="width: 100%">
                <el-option label="机器人1" value="zh"></el-option>
                <el-option label="机器人2" value="en"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col class="text-center" :span="2">
            <span class="text-gray-500">-</span>
          </el-col>
          <el-col :span="11">
            <el-form-item prop="date2">
              <el-select v-model="form.mapId" placeholder="请选择地图" clearable style="width: 100%" @change="mapChange">
                <el-option label="地图1" value="zh"></el-option>
                <el-option label="地图2" value="en"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-form-item>
        <div class="map-container">
          <canvas id="mapCanvas"></canvas>
        </div>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="Corpus">

import { useContainerHeight } from "@/hooks/tableHeight";

import { onMounted } from "vue";

import {
    worldToScreen,
    screenToWorld,
    drawGrid,
    drawGridlines,
    drawAdvancedAreaList,
    drawAdvancedLineList,
    drawNormalLines,
    drawAdvancedCurveList,
    drawAdvancedPointList,
    drawMapBoundary,
    buildOccupancyGridImage,
    MobileRobot
} from '../cockpit/canvasUtils';

const topContainerRef = ref();
const containerHeight = useContainerHeight(topContainerRef);


const tableDataList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);

const total = ref(0);
const title = ref("");

const data = reactive({
  form: {
    type: "WAKEUP",
  },
  queryParams: {
    pageNum: 1,
    pageSize: 10,
  },
  rules: {
    corpusName: [
      { required: true, message: "请输入语料名称", trigger: "change" },
    ],
    textContent: [
      { required: true, message: "请输入语音文本", trigger: "blur" },
    ],
    voiceType: [{ required: true, message: "请选择音色", trigger: "blur" }],
    dialect: [{ required: true, message: "请选择语种", trigger: "blur" }],
  },
});

const { queryParams, form, rules } = toRefs(data);

/** 查询列表 */
function getList() {
  loading.value = true;

  tableDataList.value = [];
  total.value = 0;
  loading.value = false;

}

// 取消按钮
function cancel() {
  open.value = false;
  reset();
  if (animationId) {
      cancelAnimationFrame(animationId);
      animationId = null;
  }

  window.removeEventListener('resize', resizeCanvasToContainer)
  canvasCtx = null
}

// 表单重置
function reset() {
  form.value = {
  };

}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  handleQuery();
}


/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加地图";
  setTimeout(() => {
    init();
  }, 300);     
}

/** 修改按钮操作 */
function handleUpdate(row) {

}

/** 提交按钮 */
function submitForm() {

}

/** 删除按钮操作 */
function handleDelete(row) {

}

const loadSourceMap = async (url) => {
    const response = await fetch(url);
    if (!response.ok) throw new Error(`加载失败：${response.status}`);
    return response.text();
};

function parseSmapJson(rawJson) {
    // ── 解析 header ──
    const header = rawJson.header || rawJson;                    // 兼容 header 嵌套或平铺
    const minimumPos = header.minPos || { x: 0, y: 0 };         // 地图左下角（世界坐标）
    const maximumPos = header.maxPos || { x: 1, y: 1 };         // 地图右上角（世界坐标）
    const resolution = header.resolution || 0.05;                // 每像素代表的世界长度（米）

    // ── 计算栅格尺寸 ──
    const worldWidth = maximumPos.x - minimumPos.x;            // 地图世界宽度（米）
    const worldHeight = maximumPos.y - minimumPos.y;            // 地图世界高度（米）
    const gridWidthPx = Math.ceil(worldWidth / resolution) + 1; // 栅格像素宽度
    const gridHeightPx = Math.ceil(worldHeight / resolution) + 1;// 栅格像素高度

    // ── 构建统一数据结构 ──
    const parsedMap = {
        name: header.mapName || 'Untitled',             // 地图名称
        version: header.version || '',                      // 版本号
        mapType: header.mapType || '',                      // 地图类型（如 "2D-Map"）
        resolution: resolution,                                // 分辨率（米/像素）
        originX: minimumPos.x,                              // 地图左下角 X
        originY: minimumPos.y,                              // 地图左下角 Y
        maxX: maximumPos.x,                              // 地图右上角 X
        maxY: maximumPos.y,                              // 地图右上角 Y
        gridWidth: gridWidthPx,                               // 栅格宽度（像素）
        gridHeight: gridHeightPx,                              // 栅格高度（像素）
        // normalPosList: 自由空间点，直接拷贝
        normalPositions: rawJson.normalPosList || [],
        // normalLineList: 直接拷贝，每项含 {startPos:{x,y}, endPos:{x,y}}
        normalLines: rawJson.normalLineList || [],
        // advancedPointList: 直接拷贝，每项含 {className, instanceName, pos:{x,y}, dir, desc, property:[]}
        advancedPoints: rawJson.advancedPointList || [],
        // advancedLineList: 直接拷贝，每项含 {className, instanceName, line:{startPos, endPos}}
        advancedLines: rawJson.advancedLineList || [],
        // advancedCurveList: 直接拷贝，每项含 {className, instanceName, controlPos1, controlPos2, startPos, endPos}
        advancedCurves: rawJson.advancedCurveList || [],
        // advancedAreaList: 直接拷贝，每项含 {className, instanceName, dir, posGroup:[], attribute:{}}
        advancedAreas: rawJson.advancedAreaList || [],
    };

    return parsedMap;
}

const applicationState = {
    parsedMap: null,                                      // 解析后的完整地图数据
    gridOffscreen: null,                                      // 栅格图像（离屏Canvas）
        hoveredElement: null,                                     // 当前悬停的元素 {kind, index}
        animationTimeSeconds: 0,                                  // 全局动画时间戳（秒），用于脉冲动画效果
        camera: {                                                 // 相机参数
            centerX: 0,                                                // 相机中心的世界坐标 X
            centerY: 0,                                                // 相机中心的世界坐标 Y
            pixelsPerMeter: 40,                                        // 缩放：每米对应的屏幕像素数
        },
        canvasWidthPx: 0,                                         // Canvas CSS 逻辑宽度（像素）
        canvasHeightPx: 0,                                        // Canvas CSS 逻辑高度（像素）
        devicePixelRatio: 1,                                      // 设备像素比（高DPI屏幕 > 1）
    mouseState: {                                                 // 鼠标交互状态
        screenX: 0,                                                // 鼠标在 Canvas 上的像素 X
        screenY: 0,                                                // 鼠标在 Canvas 上的像素 Y
        worldX: 0,                                                // 鼠标对应的世界坐标 X
        worldY: 0,                                                // 鼠标对应的世界坐标 Y
        isDragging: false,                                         // 是否正在拖拽平移
    },
    isMapLoaded: false,                                           // 地图加载完成标志,
    layerVisibility: {                                            // 各图层是否可见
        grid: true,                                       // 占据栅格底图
        edges: true,                                       // 墙壁边缘发光
        gridlines: true,                                       // 1米网格辅助线
        normalLines: true,                                       // normalLineList
        advLines: true,                                       // advancedLineList
        curves: true,                                       // advancedCurveList
        points: true,                                       // advancedPointList
        areas: true,                                       // advancedAreaList
    }
};

let mapCanvas;     // 主渲染画布 DOM 元素
let canvasCtx;                 // 2D 渲染上下文

const init = () => {
  mapCanvas = document.getElementById('mapCanvas');
  canvasCtx = mapCanvas.getContext('2d');
}

/**
 * 根据容器尺寸和设备像素比调整 Canvas 大小
 * 在窗口 resize 时自动调用
 */
function resizeCanvasToContainer() {
    const containerRect = mapCanvas.parentElement.getBoundingClientRect(); // 获取容器实际尺寸
    console.log('Container size:', containerRect.width, 'x', containerRect.height);
    devicePixelRatio = window.devicePixelRatio || 1;             // 获取设备像素比
    applicationState.canvasWidthPx = containerRect.width;                        // 更新逻辑宽度
    applicationState.canvasHeightPx = containerRect.height;                  // 逻辑高度 = 容器高度 - 状态栏高度
    mapCanvas.width = applicationState.canvasWidthPx * devicePixelRatio;         // Canvas 物理像素宽
    mapCanvas.height = applicationState.canvasHeightPx * devicePixelRatio;        // Canvas 物理像素高
    mapCanvas.style.width = applicationState.canvasWidthPx + 'px';               // CSS 显示宽度
    mapCanvas.style.height = applicationState.canvasHeightPx + 'px';              // CSS 显示高度
}

async function loadMapIntoApplication(parsedMap) {
    await new Promise(resolve => setTimeout(resolve, 30));       // 短暂等待让 UI 有机会刷新

    // 保存地图数据到全局状态
    applicationState.parsedMap = parsedMap;
    // 构建栅格图像（带边缘高亮）
    applicationState.gridOffscreen = buildOccupancyGridImage(parsedMap, applicationState.layerVisibility.edges);

    // ── 设置相机初始位置（地图中心）──
    applicationState.camera.centerX = (parsedMap.originX + parsedMap.maxX) / 2; // 水平居中
    applicationState.camera.centerY = (parsedMap.originY + parsedMap.maxY) / 2; // 垂直居中
    // 计算合适的缩放级别，使地图完整显示在画布内
    const worldWidthMeters = parsedMap.maxX - parsedMap.originX; // 地图世界宽度
    const worldHeightMeters = parsedMap.maxY - parsedMap.originY; // 地图世界高度
    const fitScaleX = applicationState.canvasWidthPx / worldWidthMeters;           // 水平方向恰好填满的缩放
    const fitScaleY = applicationState.canvasHeightPx / worldHeightMeters;         // 垂直方向恰好填满的缩放
    applicationState.camera.pixelsPerMeter = Math.max(1, Math.min(fitScaleX, fitScaleY) * 0.88); // 取较小值并留12%边距

    // 标记加载完成并更新UI
    applicationState.isMapLoaded = true;
}

const bindEvent = () => {
    // ── 鼠标移动：更新坐标、拖拽平移、悬停检测 ──
    mapCanvas.addEventListener('mousemove', (mouseEvent) => {
        const canvasRect = mapCanvas.getBoundingClientRect();        // Canvas 在页面中的位置
        applicationState.mouseState.screenX = mouseEvent.clientX - canvasRect.left; // 鼠标在 Canvas 上的 X
        applicationState.mouseState.screenY = mouseEvent.clientY - canvasRect.top;  // 鼠标在 Canvas 上的 Y
        // 反算世界坐标
        const worldPos = screenToWorld(applicationState.mouseState.screenX, applicationState.mouseState.screenY, applicationState);
        applicationState.mouseState.worldX = worldPos.x;
        applicationState.mouseState.worldY = worldPos.y;

        // 如果正在拖拽，平移相机
        if (applicationState.mouseState.isDragging) {
            applicationState.camera.centerX -= mouseEvent.movementX / applicationState.camera.pixelsPerMeter; // 水平平移
            applicationState.camera.centerY += mouseEvent.movementY / applicationState.camera.pixelsPerMeter; // 垂直平移（Y翻转）
        }
    });

    // ── 鼠标按下：开始拖拽 ──
    mapCanvas.addEventListener('mousedown', () => {
        applicationState.mouseState.isDragging = true;               // 标记拖拽开始
    });

    // ── 鼠标抬起：结束拖拽 ──
    mapCanvas.addEventListener('mouseup', () => {
        applicationState.mouseState.isDragging = false;              // 标记拖拽结束
    });

    // ── 鼠标离开画布：结束拖拽并隐藏 Tooltip ──
    mapCanvas.addEventListener('mouseleave', () => {
        applicationState.mouseState.isDragging = false;
    });

    // ── 滚轮：缩放（向鼠标位置缩放）──
    mapCanvas.addEventListener('wheel', (wheelEvent) => {
        wheelEvent.preventDefault();                                  // 阻止页面滚动
        const zoomFactor = wheelEvent.deltaY > 0 ? 0.88 : 1.12;     // 向下滚动=缩小，向上滚动=放大
        const mouseWorldBefore = screenToWorld(applicationState.mouseState.screenX, applicationState.mouseState.screenY, applicationState); // 缩放前鼠标世界坐标
        applicationState.camera.pixelsPerMeter = Math.max(0.5, Math.min(2000, applicationState.camera.pixelsPerMeter * zoomFactor)); // 应用缩放并钳制范围
        const mouseWorldAfter = screenToWorld(applicationState.mouseState.screenX, applicationState.mouseState.screenY, applicationState);   // 缩放后鼠标世界坐标
        // 调整相机中心，使鼠标指向的世界坐标保持不变
        applicationState.camera.centerX += mouseWorldBefore.x - mouseWorldAfter.x;
        applicationState.camera.centerY += mouseWorldBefore.y - mouseWorldAfter.y;
    }, { passive: false });                                          // passive:false 允许 preventDefault
}

/**
 * 加载 smap JSON 文件
 */
const loadUserFile = async () => {
    try {
        const fileTextContent = await loadSourceMap('/3.smap');
        const rawJsonObject = JSON.parse(fileTextContent);        // 解析 JSON
        const parsedMap = parseSmapJson(rawJsonObject);        // 转换为内部结构
        await loadMapIntoApplication(parsedMap);                     // 加载到应用
    } catch (parseError) {
        alert('Parse error: ' + parseError.message);                 // 显示错误信息
    }
}

// 声明一个变量保存 requestAnimationFrame 的 ID
let animationId = null;

function renderFrame(timestamp) {
  console.log("渲染中")
    // 更新动画时间
    applicationState.animationTimeSeconds = (timestamp || 0) / 1000;

    // 设置 Canvas 变换矩阵（考虑设备像素比）
    canvasCtx.setTransform(applicationState.devicePixelRatio, 0, 0, applicationState.devicePixelRatio, 0, 0);
    canvasCtx.clearRect(0, 0, applicationState.canvasWidthPx, applicationState.canvasHeightPx);    // 清空画布

    // 如果地图未加载，跳过绘制
    if (!applicationState.isMapLoaded) {
        animationId = requestAnimationFrame(renderFrame);                         // 继续请求下一帧
        return;
    }

    const map = applicationState.parsedMap;                       // 当前地图数据
    const layers = applicationState.layerVisibility;              // 图层可见性

    // 图层1: 占据栅格底图
    if (layers.grid && applicationState.gridOffscreen) {
        drawGrid(canvasCtx, map, applicationState);
    }

    // 图层2: 网格辅助线（每1米一条）
    if (layers.gridlines) {
        drawGridlines(canvasCtx, applicationState)
    }

    // 图层3: advancedAreaList（半透明多边形区域）
    if (layers.areas) {
        drawAdvancedAreaList(canvasCtx, map, applicationState)
    }

    // 图层4: normalLineList（基础直线，青色 #00e5ff）
    if (layers.normalLines) {
        drawNormalLines(canvasCtx, map, applicationState);
    }

    // 图层5: advancedLineList（高级线，如 ForbiddenLine）
    if (layers.advLines) {
        drawAdvancedLineList(canvasCtx, map, applicationState);
    }

    // 图层6: advancedCurveList（贝塞尔曲线路径，酸绿色 #76ff03）
    if (layers.curves) {
        drawAdvancedCurveList(canvasCtx, map, applicationState);
    }

    // 图层7: advancedPointList（高级点标记，菱形）
    if (layers.points) {
        drawAdvancedPointList(canvasCtx, map, applicationState);
    }


    // 地图边界虚线框
    drawMapBoundary(canvasCtx, map, applicationState);

    // 请求下一帧渲染
    animationId = requestAnimationFrame(renderFrame);
}

const mapChange = () => {
    loadUserFile();
    window.addEventListener('resize', resizeCanvasToContainer);    // 监听窗口大小变化
    resizeCanvasToContainer();  
    if (animationId) {
        cancelAnimationFrame(animationId);
    }
    animationId = requestAnimationFrame(renderFrame);

    setTimeout(() => {
        bindEvent()
    }, 100)
  }

onMounted(() => {
  getList();          
});

</script>
<style lang="scss" scoped>
.map-container {
  width: 100%;
  height: 300px;
  border: 1px solid #ccc;
}
</style>