import Gamecfg from "../../common/gameCfg";
import { gameMethod } from "../../common/gameMethod";
import { xlsChapterLayout } from "../../common/xlsConfig";
import Config from "../../Config";
import GameDataCenter from "../../data/GameDataCenter";
import UEBase from "../../frameWork/compment/UEBase";
import EventMng from "../../manager/EventMng";
import { HcInfoGeziInfo, ResHcInfo } from "../../shared/hc/PtlHcInfo";
import { ResHcMerge } from "../../shared/hc/PtlHcMerge";
import AssetMgr from "../../utils/AssetMgr";
import { GridConstant } from "./GridConstant";
import { GridEvent } from "./GridEvent";
import UECell, { I_CellData } from "./UECell";
import UECube from "./UECube";
import UEMergeTip from "./UEMergeTip";

const { ccclass, property } = cc._decorator;
const DRAG_THRESHOLD: number = 10; // 拖动判定阈值（像素）

@ccclass
export default class UEGridMap extends UEBase {
    static readonly BundleKey: string = "gridMap";
    static readonly PrefabUrl: string = "UEGridMap";
    static readonly CLS: string = "UEGridMap";
    @property(cc.Prefab)
    cellPrefab: cc.Prefab = null!;
    @property(cc.Prefab)
    cubePrefab: cc.Prefab = null!;
    @property(cc.Node)
    gridLayer: cc.Node = null;
    @property(cc.Node)
    cellLayer: cc.Node = null;
    @property(cc.Node)
    cubeLayer: cc.Node = null;
    @property(cc.Node)
    tipLayer: cc.Node = null;
    @property(cc.Node)
    effectLayer: cc.Node = null;
    cellMap: { [gid: number]: UECell } = {};
    private isDragging: boolean = false;
    private dragStartPos: cc.Vec2 = cc.v2(0, 0);
    private selectedCell: UECell = null!;
    private lastMoveCell: UECell = null!;
    private clickCnt: number = 0;
    private ueMergeTip: UEMergeTip;
    Init() {
        this.ueMergeTip = AssetMgr.instantiateUE(UEMergeTip);
        this.tipLayer.addChild(this.ueMergeTip.node);
        this.ueMergeTip.node.active = false;
        GameDataCenter.gridMap.Init(this);
        this.gridLayer.setContentSize(GridConstant.CELL_WIDTH * GridConstant.ROW, GridConstant.CELL_WIDTH * GridConstant.COL);
        // 计算缩放比例
        // ratio为0表示屏幕高度等于标准高度1750
        // ratio为1表示屏幕高度等于1334（需要缩放15%）
        const ratio = Math.max(0, (GridConstant.CELL_REAL_WIN_HEIGHT - cc.winSize.height) / (GridConstant.CELL_REAL_WIN_HEIGHT - Config.realHeight));
        // 当ratio为1时，scale = 0.85（缩放15%）
        // 当ratio为0时，scale = 1（不缩放）
        const scale = 1 - (0.15 * ratio);
        this.node.scale = scale;

        this.InitEvent();
        GameDataCenter.gridMap.sendHcInfo({});
    }


    InitEvent(): void {
        this.gridLayer.on(cc.Node.EventType.TOUCH_START, this.OnTouchStart, this);
        this.gridLayer.on(cc.Node.EventType.TOUCH_MOVE, this.OnTouchMove, this);
        this.gridLayer.on(cc.Node.EventType.TOUCH_END, this.OnTouchEnd, this);
        this.gridLayer.on(cc.Node.EventType.TOUCH_CANCEL, this.OnTouchEnd, this);
        this.initEvent(GridEvent.TRIGGER_EMITTER, this.TriggerEmitter);
        this.initEvent(GridEvent.HC_INFO_RSP, this.LoadMapData);
        this.initEvent(GridEvent.HC_MERGE_RSP, this.OnHcMergeRsp);
        this.initEvent(GridEvent.HC_FIGHT_OVER, this.OnHcFightOver);
    }



    /** 加载地图数据 */
    private LoadMapData(data: ResHcInfo) {
        this.cellMap = {};
        for (let i = 0; i < GridConstant.COL; i++) {
            let rowCells = [];
            let rowCubes = [];
            for (let j = 0; j < GridConstant.ROW; j++) {
                let idx = (i + 1) * 10 + (j + 1);
                let cellData = data.list[idx];
                if (cellData) {
                    let cell = this.CreateCell(i, j);
                    rowCells.push(cell);
                    let cube = null;
                    if (cellData.type > 0) {
                        cube = this.CreateCube(i, j);
                        rowCubes.push(cube);
                        cube.Init({
                            type: cellData.type,
                            id: cellData.correlationId,
                            zIndex: idx
                        }, idx)
                    }
                    cell.Init({
                        idx: idx,
                        ueCube: cube,
                        unlock: cellData.unlock
                    });
                    this.cellMap[idx] = cell;
                }
            }

        }
    }

    private OnHcFightOver(data: { gzid: number, list: { [gzid: string]: HcInfoGeziInfo } }) {
        let cell = this.cellMap[data.gzid];
        cell.ClearCube();
        for (let key in data.list) {
            let geziData = data.list[key];
            if (geziData.type != 0) {
                let curCell = this.cellMap[Number(key)];
                if (curCell.IsLock()) {
                    curCell.ChangeLockState(geziData.unlock);
                }
                let vec = GameDataCenter.gridMap.TranIdxToPos(Number(key));
                let mergeCube = this.CreateCube(vec.y, vec.x);
                mergeCube.Init({
                    type: geziData.type,
                    id: geziData.correlationId,
                    idx: Number(key),
                });
                curCell.SetCube(mergeCube);
            }
        }
    }

    private OnHcMergeRsp(data: { cell: UECell, cube: HcInfoGeziInfo }) {
        let vec = GameDataCenter.gridMap.TranIdxToPos(data.cell.GetZIndex());
        let mergeCube = this.CreateCube(vec.y, vec.x);
        mergeCube.Init({
            type: data.cube.type,
            id: data.cube.correlationId,
            idx: data.cell.GetZIndex(),
        });
        data.cell.SetCube(mergeCube);
        //播放经验爆炸飞行动画

    }



    /** 创建格子 */
    private CreateCell(i: number, j: number) {
        let cell = cc.instantiate(this.cellPrefab).getComponent(UECell);
        this.cellLayer.addChild(cell.node);
        cell.node.width = GridConstant.CELL_WIDTH;
        cell.node.height = GridConstant.CELL_WIDTH;
        let pos = GameDataCenter.gridMap.GetPosByVec(i, j);
        cell.node.setPosition(pos);
        return cell;
    }

    /** 创建棋子 */
    private CreateCube(i: number, j: number) {
        let cube = cc.instantiate(this.cubePrefab).getComponent(UECube);
        this.cubeLayer.addChild(cube.node);
        cube.node.width = GridConstant.CELL_WIDTH;
        cube.node.height = GridConstant.CELL_WIDTH;
        let pos = GameDataCenter.gridMap.GetPosByVec(i, j);
        cube.node.setPosition(pos);
        return cube;
    }

    private OnTouchStart(event: cc.Event.EventTouch): void {
        const touchPos = this.gridLayer.convertToNodeSpaceAR(event.getLocation());
        const cell = this.GetCellByPos(touchPos);
        if (cell) {
            if (this.selectedCell) {
                // this.selectedCell.SetSelect(false);
                EventMng.emit(GridEvent.HC_CELL_SELECT, 0);
            }
            if (!cell.IsEmpty() && !cell.IsLock()) {
                if (cell.CanDrag()) {
                    this.dragStartPos = touchPos;
                }

                if (this.selectedCell != cell) {
                    this.clickCnt = 1;
                }
                this.selectedCell = cell;
                // cell.SetSelect(true);
                EventMng.emit(GridEvent.HC_CELL_SELECT, cell.GetZIndex());
                EventMng.emit(GridEvent.HC_MERGE_SELL, { isShow: true, item: cell.GetCube().GetCubeData() });
            } else {
                this.selectedCell = null;
                this.clickCnt = 0;
                EventMng.emit(GridEvent.HC_MERGE_SELL, { isShow: false });
            }
        } else {
            this.clickCnt = 0;
        }
    }

    private OnTouchMove(event: cc.Event.EventTouch): void {
        if (!this.selectedCell || !this.dragStartPos) return;

        const touchPos = this.gridLayer.convertToNodeSpaceAR(event.getLocation());
        const distance = touchPos.sub(this.dragStartPos).mag();

        // 只有当移动距离超过阈值时才开始拖动
        if (!this.isDragging && distance >= DRAG_THRESHOLD) {
            this.isDragging = true;
            this.selectedCell.GetCube().StartDrag();
            // this.selectedCell.SetSelect(false);
            EventMng.emit(GridEvent.HC_CELL_SELECT, 0);
        }

        if (this.isDragging) {
            // 计算移动差值并应用到cube节点
            const deltaPos = touchPos.sub(this.dragStartPos);
            const cube = this.selectedCell.GetCube();
            const originalPos = cube.node.getPosition();
            cube.node.setPosition(originalPos.x + deltaPos.x, originalPos.y + deltaPos.y);
            this.dragStartPos = touchPos;
            const targetCell = this.GetCellByPos(touchPos);
            // this.lastMoveCell?.SetSelect(false);
            EventMng.emit(GridEvent.HC_CELL_SELECT, 0);
            this.lastMoveCell = targetCell;
            if (targetCell && !targetCell.IsLock()) {
                // targetCell.SetSelect(true);
                EventMng.emit(GridEvent.HC_CELL_SELECT, targetCell.GetZIndex());
            }
            if (targetCell && targetCell != this.selectedCell) {
                if (!targetCell.IsEmpty() && GameDataCenter.gridMap.CellCanPut(this.selectedCell, targetCell)) {
                    this.ueMergeTip.node.setPosition(targetCell.node.getPosition());
                    this.ueMergeTip.Init({
                        idx: targetCell.GetZIndex(),
                        ueCube1: this.selectedCell.GetCube(),
                        ueCube2: targetCell.GetCube(),
                        dir: targetCell.GetZIndex() % 10 > 4 ? 2 : 1
                    });
                } else {
                    this.ueMergeTip.Hide();
                }
            } else {
                this.ueMergeTip.Hide();
            }
        }
    }

    private OnTouchEnd(event: cc.Event.EventTouch): void {
        this.dragStartPos = null;
        this.ueMergeTip.Hide();
        if (!this.selectedCell) return;
        const touchPos = this.gridLayer.convertToNodeSpaceAR(event.getLocation());
        const targetCell = this.GetCellByPos(touchPos);
        if (!this.isDragging && this.selectedCell === targetCell) {
            //二次点击同一个格子
            if (!targetCell.IsEmpty()) {
                targetCell.GetCube().PlayJellyAnim();
                if (this.clickCnt >= 2) {
                    console.log("二次点击同一个格子");
                    targetCell.GetCube().TriggerClick();
                } else {
                    this.clickCnt++;
                }
            }
        } else {
            if (!this.isDragging) return;
            if (targetCell && targetCell != this.selectedCell && !targetCell.IsLock()) {
                GameDataCenter.gridMap.TryMergeItems(this.selectedCell, targetCell);
                // this.selectedCell.SetSelect(false);
                // targetCell.SetSelect(true);
                EventMng.emit(GridEvent.HC_CELL_SELECT, targetCell.GetZIndex());
            } else {
                this.CheckSell();
                this.selectedCell.GetCube().BackToOriginalPos(true);
            }
            this.isDragging = false;
            this.selectedCell = targetCell;
        }

    }

    /** 检测物品是否拖动到售卖区域售卖 */
    private CheckSell() {
        let sellPos = cc.v2(0, 0);
        let sellSize = cc.size(GridConstant.CELL_WIDTH, GridConstant.CELL_WIDTH);
        let sellRect = cc.rect(sellPos.x, sellPos.y, sellSize.width, sellSize.height);
        let cubePos = this.selectedCell.GetCube().node.getPosition();
        // if (cc.rectContainsPoint(sellRect, cubePos)) {
        //     this.selectedCell.GetCube().PlayJellyAnim();
        // }
    }

    /** 根据像素坐标获取格子 */
    private GetCellByPos(pos: cc.Vec2): UECell | null {
        const startX = -(GridConstant.ROW * GridConstant.CELL_WIDTH) / 2;
        const startY = (GridConstant.COL * GridConstant.CELL_WIDTH) / 2;

        const row = Math.floor((pos.x - startX) / GridConstant.CELL_WIDTH);
        const col = Math.floor((startY - pos.y) / GridConstant.CELL_WIDTH);

        if (col >= 0 && col < GridConstant.COL && row >= 0 && row < GridConstant.ROW) {
            let idx = (col + 1) * 10 + (row + 1);
            return this.cellMap[idx];
        }
        return null;
    }

    /** 发射出新的物品 */
    private TriggerEmitter(data: { idx: number, item: HcInfoGeziInfo, targetIdx: number }) {
        let targetCell = this.cellMap[data.targetIdx];
        let startPos = GameDataCenter.gridMap.TranIdxToPos(data.idx);
        let mergeCube = this.CreateCube(startPos.y, startPos.x);
        mergeCube.Init({
            type: data.item.type,
            id: data.item.correlationId,
            idx: data.idx,
        });
        targetCell.SetCube(mergeCube);
        mergeCube.SetZIndex(1000);
        let targetPos = GameDataCenter.gridMap.TranIdxToPos(data.targetIdx);

        // 计算起点和终点
        const startWorldPos = mergeCube.node.getPosition();
        const endWorldPos = GameDataCenter.gridMap.GetPosByVec(targetPos.y, targetPos.x);

        // 计算方向向量和总距离
        const moveVec = cc.v2(endWorldPos.x - startWorldPos.x, endWorldPos.y - startWorldPos.y);
        const totalDistance = moveVec.mag();
        const normalizedDir = moveVec.normalize();

        // 根据距离动态计算动画时间（距离越远，时间越长）
        const baseDuration = 0.5; // 基础动画时间
        const distanceFactor = totalDistance / 300; // 假设300是标准距离
        const duration = Math.min(baseDuration + distanceFactor * 0.3, 1.2); // 限制最大时间为1.2秒

        // 设置最大高度（向上弹跳的高度）
        const maxHeight = 400;

        // 计算最后弹跳的起点（在终点前20%距离处）
        const bounceStartPos = cc.v3(
            endWorldPos.x - normalizedDir.x * (totalDistance * 0.2),
            endWorldPos.y - normalizedDir.y * (totalDistance * 0.2),
            0
        );

        // 创建第一段抛物线（抛向空中然后落到弹跳起点）
        const bezier1 = [];
        const midPoint1 = cc.v3(
            startWorldPos.x + moveVec.x * 0.3,
            Math.max(startWorldPos.y, bounceStartPos.y) + maxHeight,
            0
        );
        bezier1.push(cc.v2(startWorldPos.x, startWorldPos.y));
        bezier1.push(cc.v2(midPoint1.x, midPoint1.y));
        bezier1.push(cc.v2(bounceStartPos.x, bounceStartPos.y));

        // 创建第二段弹跳（第一次弹跳）
        const bezier2 = [];
        const bounceHeight = totalDistance * 0.15; // 弹跳高度设为总距离的15%

        // 计算第一次弹跳的最高点和落点
        const firstBounceTop = cc.v2(
            (bounceStartPos.x + endWorldPos.x) / 2,  // 水平位置在中间
            endWorldPos.y + bounceHeight  // 垂直高度为弹跳高度
        );

        // 计算第二段距离（从bounceStartPos到终点的距离）
        const secondDistance = totalDistance * 0.2; // 最后20%的距离
        const firstBounceEnd = cc.v2(
            bounceStartPos.x + normalizedDir.x * (secondDistance * 0.5), // 前进一半
            bounceStartPos.y + normalizedDir.y * (secondDistance * 0.5)
        );

        bezier2.push(cc.v2(bounceStartPos.x, bounceStartPos.y)); // 起跳点
        bezier2.push(firstBounceTop); // 最高点
        bezier2.push(firstBounceEnd); // 第一次落点

        // 创建第三段弹跳（最后一次弹跳到终点）
        const bezier3 = [];
        const secondBounceTop = cc.v2(
            (firstBounceEnd.x + endWorldPos.x) / 2,
            endWorldPos.y + bounceHeight * 0.6  // 第二次弹跳高度为第一次的60%
        );

        bezier3.push(firstBounceEnd); // 起跳点
        bezier3.push(secondBounceTop); // 最高点
        bezier3.push(cc.v2(endWorldPos.x, endWorldPos.y)); // 终点

        // 创建动作序列
        const bezierAction1 = cc.bezierTo(duration * 0.7, bezier1);
        const bezierAction2 = cc.bezierTo(duration * 0.18, bezier2);
        const bezierAction3 = cc.bezierTo(duration * 0.12, bezier3);

        const seq = cc.sequence(
            bezierAction1,
            bezierAction2,
            bezierAction3,
            cc.callFunc(() => {
                mergeCube.SetZIndex(data.targetIdx);
            })
        );

        // 执行动画
        mergeCube.node.runAction(seq);
    }

}
