import { _decorator, Component, Node, TiledMap, TiledLayer, Vec2, Vec3, Size } from 'cc';
import { AStarPathfinding } from './AStarPathfinding';

const { ccclass, property } = _decorator;

@ccclass('TiledMapPathfinder')
export class TiledMapPathfinder extends Component {

    @property(TiledMap)
    tiledMap: TiledMap | null = null;

    @property({ displayName: '可行走图层名称' })
    walkableLayerName: string = 'WalkableLayer';

    @property({ displayName: '瓦片尺寸' })
    tileSize: number = 32;

    private pathfinding: AStarPathfinding | null = null;
    private mapSize: Size = new Size(0, 0);
    private walkableData: number[][] = [];

    onLoad() {
        // 获取或创建寻路组件
        this.pathfinding = this.getComponent(AStarPathfinding);
        if (!this.pathfinding) {
            this.pathfinding = this.addComponent(AStarPathfinding);
        }
    }

    start() {
        if (this.tiledMap) {
            this.initializePathfinding();
        } else {
            console.error('TiledMapPathfinder: TiledMap组件未设置');
        }
    }

    /**
     * 初始化寻路系统
     */
    private initializePathfinding() {
        if (!this.tiledMap) {
            console.error('TiledMap未设置');
            return;
        }

        // 获取地图尺寸
        this.mapSize = this.tiledMap.getMapSize();
        console.log(`地图尺寸: ${this.mapSize.width}x${this.mapSize.height}`);

        // 获取可行走图层
        const walkableLayer = this.tiledMap.getLayer(this.walkableLayerName);
        if (!walkableLayer) {
            console.error(`找不到图层: ${this.walkableLayerName}`);
            return;
        }

        // 读取可行走数据
        this.extractWalkableData(walkableLayer);

        // 初始化A*寻路算法
        if (this.pathfinding) {
            this.pathfinding.initializeGrid(this.mapSize.width, this.mapSize.height, this.walkableData);
            console.log('寻路系统初始化完成');
        }
    }

    /**
     * 从TiledLayer提取可行走数据
     */
    private extractWalkableData(layer: TiledLayer) {
        this.walkableData = [];

        for (let y = 0; y < this.mapSize.height; y++) {
            this.walkableData[y] = [];
            for (let x = 0; x < this.mapSize.width; x++) {
                // 获取指定位置的瓦片GID
                const gid = layer.getTileGIDAt(x, y);

                // GID > 0 表示有瓦片，表示可行走
                // GID = 0 表示没有瓦片，表示不可行走
                this.walkableData[y][x] = gid > 0 ? 1 : 0;
            }
        }

        console.log('可行走数据提取完成');
        this.debugPrintWalkableData();
    }

    /**
     * 调试打印可行走数据（仅打印部分数据以避免日志过长）
     */
    private debugPrintWalkableData() {
        console.log('可行走数据示例（前10行）:');
        for (let y = 0; y < Math.min(10, this.walkableData.length); y++) {
            const row = this.walkableData[y].slice(0, Math.min(10, this.walkableData[y].length));
            console.log(`第${y}行: [${row.join(', ')}]`);
        }
    }

    /**
     * 寻找路径
     * @param startWorldPos 起点世界坐标
     * @param targetWorldPos 终点世界坐标
     * @returns 路径的世界坐标数组
     */
    findPath(startWorldPos: Vec3, targetWorldPos: Vec3): Vec3[] {
        if (!this.pathfinding || !this.tiledMap) {
            console.warn('寻路系统未初始化');
            return [];
        }

        // 将世界坐标转换为瓦片坐标
        const startTilePos = this.worldToTileCoordinate(startWorldPos);
        const targetTilePos = this.worldToTileCoordinate(targetWorldPos);

        console.log(`寻路: 起点瓦片坐标(${startTilePos.x}, ${startTilePos.y}) -> 终点瓦片坐标(${targetTilePos.x}, ${targetTilePos.y})`);

        // 使用A*算法寻找路径
        const tilePath = this.pathfinding.findPath(
            startTilePos.x, startTilePos.y,
            targetTilePos.x, targetTilePos.y
        );

        if (tilePath.length === 0) {
            console.warn('未找到路径');
            return [];
        }

        // 将瓦片坐标路径转换为世界坐标路径
        const worldPath: Vec3[] = [];
        for (const tilePos of tilePath) {
            const worldPos = this.tileToWorldCoordinate(tilePos);
            worldPath.push(worldPos);
        }

        console.log(`找到路径，包含${worldPath.length}个点`);
        return worldPath;
    }

    /**
     * 世界坐标转换为瓦片坐标
     */
    private worldToTileCoordinate(worldPos: Vec3): Vec2 {
        if (!this.tiledMap) {
            return new Vec2(0, 0);
        }

        // 获取地图节点的位置偏移
        const mapNode = this.tiledMap.node;
        const mapPosition = mapNode.position;

        // 计算相对于地图的坐标
        const relativeX = worldPos.x - mapPosition.x;
        const relativeY = worldPos.y - mapPosition.y;

        // 获取地图尺寸信息
        const mapSize = this.tiledMap.getMapSize();
        const tileSize = this.tiledMap.getTileSize();

        // 计算瓦片坐标
        // 注意：Cocos Creator的Y轴向上为正，但瓦片地图的Y轴向下为正
        const tileX = Math.floor((relativeX + mapSize.width * tileSize.width * 0.5) / tileSize.width);
        const tileY = Math.floor((mapSize.height * tileSize.height * 0.5 - relativeY) / tileSize.height);

        // 确保坐标在地图范围内
        const clampedX = Math.max(0, Math.min(mapSize.width - 1, tileX));
        const clampedY = Math.max(0, Math.min(mapSize.height - 1, tileY));

        return new Vec2(clampedX, clampedY);
    }

    /**
     * 瓦片坐标转换为世界坐标
     */
    private tileToWorldCoordinate(tilePos: Vec2): Vec3 {
        if (!this.tiledMap) {
            return new Vec3(0, 0, 0);
        }

        // 获取地图节点的位置偏移
        const mapNode = this.tiledMap.node;
        const mapPosition = mapNode.position;

        // 获取地图尺寸信息
        const mapSize = this.tiledMap.getMapSize();
        const tileSize = this.tiledMap.getTileSize();

        // 计算世界坐标（瓦片中心点）
        const worldX = (tilePos.x + 0.5) * tileSize.width - mapSize.width * tileSize.width * 0.5 + mapPosition.x;
        const worldY = mapSize.height * tileSize.height * 0.5 - (tilePos.y + 0.5) * tileSize.height + mapPosition.y;

        return new Vec3(worldX, worldY, 0);
    }

    /**
     * 检查指定世界坐标是否可行走
     */
    isWorldPositionWalkable(worldPos: Vec3): boolean {
        if (!this.pathfinding) {
            return false;
        }

        const tilePos = this.worldToTileCoordinate(worldPos);
        return this.pathfinding.isWalkable(tilePos.x, tilePos.y);
    }

    /**
     * 获取最近的可行走位置
     */
    getClosestWalkablePosition(worldPos: Vec3, maxSearchRadius: number = 5): Vec3 | null {
        const centerTilePos = this.worldToTileCoordinate(worldPos);

        // 螺旋搜索最近的可行走位置
        for (let radius = 0; radius <= maxSearchRadius; radius++) {
            for (let x = -radius; x <= radius; x++) {
                for (let y = -radius; y <= radius; y++) {
                    // 只检查当前半径边界上的点
                    if (Math.abs(x) !== radius && Math.abs(y) !== radius && radius > 0) {
                        continue;
                    }

                    const checkX = centerTilePos.x + x;
                    const checkY = centerTilePos.y + y;

                    if (this.pathfinding && this.pathfinding.isWalkable(checkX, checkY)) {
                        return this.tileToWorldCoordinate(new Vec2(checkX, checkY));
                    }
                }
            }
        }

        return null;
    }

    /**
     * 获取地图信息
     */
    getMapInfo() {
        if (!this.tiledMap) {
            return null;
        }

        return {
            mapSize: this.tiledMap.getMapSize(),
            tileSize: this.tiledMap.getTileSize(),
            orientation: this.tiledMap.getMapOrientation()
        };
    }
}