<template>
    <div class="container">
        <canvas id="map-canvas"></canvas>
    </div>
</template>

<script setup>
import { onMounted, onUnmounted } from 'vue';

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

import { useInspectionStore } from "@/store/modules/inspection";
const inspectionStore = useInspectionStore();



/**
 * 应用全局状态对象，集中管理所有可变数据
 * - parsedMap:      解析后的地图数据结构
 * - layerVisibility: 各图层的可见性开关
 * - mouseState:     鼠标位置与拖拽状态
 * - isMapLoaded:    地图是否已加载完成
 */
const applicationState = {
    parsedMap: null,                                      // 解析后的完整地图数据
    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
        robots: true,                                       // 机器人位置和朝向
    },
    robots: []      // 存储机器人实例
};

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

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

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


/**
 * 解析 SEER smap JSON 文件为内部地图数据结构
 *
 * @param {Object} rawJson - 原始 JSON 解析后的对象
 * @returns {Object} 解析后的统一地图数据结构
 */
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;
}

/**
 * 加载地图到应用：构建栅格图像、设置相机、更新UI
 * @param {Object} parsedMap - parseSmapJson 的输出
 */
async function loadMapIntoApplication(parsedMap) {
    await new Promise(resolve => setTimeout(resolve, 30));       // 短暂等待让 UI 有机会刷新

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

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

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



/**
 * 主渲染函数，由 requestAnimationFrame 循环调用
 * 按层顺序绘制：栅格 → 网格线 → 区域 → 基础线 → 高级线 → 曲线 → 点 → 边界
 *
 * @param {number} timestamp - requestAnimationFrame 提供的时间戳（毫秒）
 */
function renderFrame(timestamp) {
    // 更新动画时间
    inspectionStore.animationTimeSeconds = (timestamp || 0) / 1000;

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

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

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

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

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

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

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

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

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

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

    if (layers.robots) {
        drawAllRobots(canvasCtx)
    }

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

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

const drawAllRobots = (ctx) => {
    if (!applicationState.layerVisibility.robots) return;
    for (const robot of applicationState.robots) {
        console.log(1222)
        const screenPos = worldToScreen(robot.x, robot.y);
        // 裁剪超出画布简易跳过
        if (screenPos.x + 20 < 0 || screenPos.x - 20 > inspectionStore.canvasWidthPx || screenPos.y + 20 < 0 || screenPos.y - 20 > inspectionStore.canvasHeightPx) {
            continue;
        }
        robot.draw(ctx, screenPos.x, screenPos.y);
    }
}

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.mouseState.worldX = worldPos.x;
        applicationState.mouseState.worldY = worldPos.y;

        // 如果正在拖拽，平移相机
        if (applicationState.mouseState.isDragging) {
            inspectionStore.camera.centerX -= mouseEvent.movementX / inspectionStore.camera.pixelsPerMeter; // 水平平移
            inspectionStore.camera.centerY += mouseEvent.movementY / inspectionStore.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); // 缩放前鼠标世界坐标
        inspectionStore.camera.pixelsPerMeter = Math.max(0.5, Math.min(2000, inspectionStore.camera.pixelsPerMeter * zoomFactor)); // 应用缩放并钳制范围
        const mouseWorldAfter = screenToWorld(applicationState.mouseState.screenX, applicationState.mouseState.screenY);   // 缩放后鼠标世界坐标
        // 调整相机中心，使鼠标指向的世界坐标保持不变
        inspectionStore.camera.centerX += mouseWorldBefore.x - mouseWorldAfter.x;
        inspectionStore.camera.centerY += mouseWorldBefore.y - mouseWorldAfter.y;
    }, { passive: false });                                          // passive:false 允许 preventDefault
}

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

/**
 * 加载 smap JSON 文件
 */
async function loadUserFile() {
    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);                 // 显示错误信息
    }
}

const addRobot = () => {
    const map = applicationState.parsedMap;
    console.log('map', map)
    // 放置于地图中央附近
    const centerX = (map.originX + map.maxX) / 2;
    const centerY = (map.originY + map.maxY) / 2;
    const id = 0;
    const robot = new MobileRobot(id, `Robot${id}`, centerX + (Math.random() - 0.5) * 3, centerY + (Math.random() - 0.5) * 3, 0);
    applicationState.robots.push(robot);
}

const moveRobot = (robot, dx, dy, dtheta = 0) => {
    robot.x += dx;
    robot.y += dy;
    robot.angle += dtheta;
}

onMounted(() => {
    init()
    // 启动渲染循环
    loadUserFile()
    requestAnimationFrame(renderFrame);
    window.addEventListener('resize', resizeCanvasToContainer);    // 监听窗口大小变化
    resizeCanvasToContainer();                                     // 初始调用一次
    setTimeout(() => {
        bindEvent()
        addRobot()
    }, 100)
})

onUnmounted(() => {
    window.removeEventListener('resize', resizeCanvasToContainer)
    canvasCtx = null
})
</script>

<style lang="scss" scoped>
.container {
    width: 100%;
    height: 100%;
}
</style>