import { _decorator, Component, EventTouch, Material, Node, Sprite, UIOpacity, UITransform, v3, Vec2, Vec3 } from 'cc';
import { AudioManager } from '../AudioManager';
import { Url } from '../Url';
import { BlockController } from './Block/BlockController';
import { BlockConfig, BlocksAll, BlockState, ReConfig, Region } from './Block/BlockData';
import GlobalData from './GlobalData';
import { GridBlockMgr } from './GridBlockMgr';
import { Guide } from './Guide';
import { MainGameLogic } from './MainGameLogic';
import ResSprite from '../ResSprite';
const { ccclass, property } = _decorator;


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

    /** 单例模式 */
    private static _ins: TouchMgr;
    constructor() {
        super();
        TouchMgr._ins = this;
    }
    public static get ins(): TouchMgr {
        if (!TouchMgr._ins) {
            TouchMgr._ins = new TouchMgr();
        }
        return TouchMgr._ins;
    }



    @property(Node)
    selection_container: Node = null;
    //三个方块的选择区
    @property(Node)
    select1: Node = null;
    @property(Node)
    select2: Node = null;
    @property(Node)
    select3: Node = null;

    //三个方块的选择区的状态
    selectCanTouch: boolean[] = [false, false, false]

    @property(Node)
    tempBlock: Node = null;   // 临时方块

    @property(Material)
    material: Material = null;

    @property(Material)
    defaultmaterial: Material = null;

    posOffset: Vec3 = new Vec3(0, 0, 0);

    isCanPlaced: boolean = false;  // 是否可以放置
    // 是否可以放置的索引数组
    placedIndexArr: number[] = [];
    tempBlockColor: string = '';    // 临时方块的颜色

    private longPressThreshold: number = 200; // 长按阈值，单位毫秒
    private longPressTimerID: any = null;
    private isLongPress: boolean = false;  // 是否长按

    vec3Reusable: Vec3 = new Vec3();

    private enlargedBlocks: Node[] = []; // 记录上一次放大的块


    private touchStartPos: Vec2;

    onLoad() {
        this.select1.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.select1.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.select1.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.select1.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);

        this.select2.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.select2.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.select2.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.select2.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);

        this.select3.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.select3.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.select3.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
        this.select3.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
    }

    start() {
        // log(this.selectCanTouch)
        // const p = this.getRegion(new Vec3(0, 300, 0));
        // console.log(GridBlockMgr.ins.block_ba_data[p.i][p.j].block_ba_node.position);
        // console.log(GridBlockMgr.ins.block_ba_data[p.i][p.j].index_i, GridBlockMgr.ins.block_ba_data[p.i][p.j].index_j);

    }

    //长按的数据
    private longPressEle: {
        event: EventTouch,
        touch_node: Node,
        target_block: Node,
        target_block_config: BlockConfig
    }
    onTouchStart(event: EventTouch) {
        AudioManager.ins.playOneShot(Url.AUDIO.SFX2, 1);
        this.isLongPress = false;
        this.resumePromptBlock();
        this.touchStartPos = event.getUILocation();
        let touch_node = event.getCurrentTarget() as Node;
        let touchSelectIndex = touch_node.getSiblingIndex();
        if (!this.selectCanTouch[touchSelectIndex]) {
            return;
        }

        // 获取点击的目标block
        let target_block = touch_node.children[0];

        // 获取block的BlockController组件中的BlockConfig数据
        let target_block_config: BlockConfig = target_block.getComponent(BlockController).curBlockConfig;
        this.tempBlockColor = target_block_config.block_color;
        this.longPressEle = {
            event,
            touch_node,
            target_block,
            target_block_config
        }
        // this.longPressTimerID = setTimeout(() => {
        //     this.longPressFunc(this.longPressEle.event, this.longPressEle.touch_node, this.longPressEle.target_block, this.longPressEle.target_block_config);
        // }, this.longPressThreshold);
    }

    longPressFunc(event: EventTouch, touch_node: Node, target_block, target_block_config) {
        this.isLongPress = true;
        touch_node.children[1].active = false;

        // 点击之后下方展示block隐藏
        target_block.active = false;

        // 生成一个要跟随鼠标移动的临时block，并将位置放在鼠标点击位置
        this.tempBlock.active = true;
        this.tempBlock.getComponent(BlockController).updateBlockSet(false, target_block_config);
        const touch_pos = event.getUILocation();
        const temp_touch_pos = this.getRelativePosition(this.selection_container, this.vec2ToVec3(touch_pos));

        // 设置临时block的位置到点击位置
        this.tempBlock.setPosition(temp_touch_pos.add(new Vec3(0, 250, 0))); // 将tempBlock位置放在点击位置的上方200处

        this.tempBlock.getComponent(BlockController).addBlockOffset(2);

        // 获取临时tempBlock和鼠标之间的向量差
        // this.posOffset = this.vectorDifference(temp_touch_pos, this.tempBlock.position);
    }

    calculateDistance(vec1: Vec2, vec2: Vec2): number {
        return Vec2.distance(vec1, vec2);
    }

    onTouchMove(event: EventTouch) {
        // clearTimeout(this.longPressTimerID);
        let touchMovePos = event.getUILocation();
        // console.log(this.calculateDistance(touchMovePos, this.touchStartPos));
        if (this.calculateDistance(touchMovePos, this.touchStartPos) <= 25) {
            //太短就不管
            return
        }
        // console.log("MOVE");

        this.longPressFunc(this.longPressEle.event, this.longPressEle.touch_node, this.longPressEle.target_block, this.longPressEle.target_block_config)

        this.resumePromptBlock();
        let touch_node = event.getCurrentTarget() as Node;
        let touchSelectIndex = touch_node.getSiblingIndex();
        if (!this.selectCanTouch[touchSelectIndex]) {
            return;
        }
        touch_node.children[1].active = false;

        // 获取鼠标当前位置并转换
        let touch_pos = event.getUILocation();
        // let temp_touch_pos = this.getRelativePosition(this.selection_container, this.vec2ToVec3(touch_pos));
        const temp_touch_pos = this.getRelativePosition(this.selection_container, this.vec2ToVec3(touch_pos));

        // 设置临时block的位置到点击位置
        this.tempBlock.setPosition(temp_touch_pos.add(new Vec3(0, 250, 0))); // 将tempBlock位置放在点击位置的上方200处

        this.tempBlock.getComponent(BlockController).addBlockOffset(2);

        let pos_to_grid = this.getNodeAToNodeBPoint(GridBlockMgr.ins.gridcontainer.parent, this.tempBlock);
        let indexi_j = this.getRegion(new Vec3(pos_to_grid.x, pos_to_grid.y, 0));

        GridBlockMgr.ins.updateBoard();

        if (indexi_j) {
            let date = GridBlockMgr.ins.block_ba_data[indexi_j.i][indexi_j.j];
            let tempBlockData = this.tempBlock.getComponent(BlockController).curBlockConfig;
            if (!tempBlockData) {
                return;
            }
            let config = this.getCenteredBlocks(date.index_i, date.index_j, tempBlockData.block_arr, tempBlockData.block_color, this.tempBlock);
            // console.log(config);

            this.isCanPlaced = config.iscanplaced;
            this.placedIndexArr = config.indexarr;
            this.tempBlockColor = tempBlockData.block_color;

        } else {
            this.isCanPlaced = false;
        }
    }

    onTouchEnd(event: EventTouch) {
        this.resumePromptBlock();
        let touch_node = event.getCurrentTarget() as Node;
        let touchSelectIndex = touch_node.getSiblingIndex();
        if (!this.selectCanTouch[touchSelectIndex]) {
            return;
        }

        // if (this.longPressTimerID) {
        //     clearTimeout(this.longPressTimerID);
        //     this.longPressTimerID = null;
        // }

        if (this.isLongPress) {
            touch_node.children[1].active = false;
            GridBlockMgr.ins.updateBoard();
            if (this.isCanPlaced) {
                //可以放置
                AudioManager.ins.playOneShot(Url.AUDIO.SFX3, 1);
                this.tempBlock.active = false;
                for (let i = 0; i < this.placedIndexArr.length; i++) {
                    //这做一个吸附效果，从上到下，快点放置上去，而不是全部一起直接放置，很生硬


                    let boardindex_i = this.placedIndexArr[i][0];
                    let boardindex_j = this.placedIndexArr[i][1];
                    GridBlockMgr.ins.block_ba_data[boardindex_i][boardindex_j].block_state = BlockState.SHOW;
                    GridBlockMgr.ins.block_ba_data[boardindex_i][boardindex_j].block_ba_node.getComponent(UIOpacity).opacity = 255;
                    GridBlockMgr.ins.block_ba_data[boardindex_i][boardindex_j].block_sprite.setSpriteFrame(this.tempBlockColor + '/spriteFrame');
                    GridBlockMgr.ins.block_ba_data[boardindex_i][boardindex_j].block_color = this.tempBlockColor;
                    // node.getComponent(ResSprite).setSpriteFrame(blockConfig.block_color + '/spriteFrame');
                }
                this.selectCanTouch[touch_node.getSiblingIndex()] = false;

                let is_empty = this.selectionConEmpty();
                if (is_empty && GlobalData.guideRecord > 3) {
                    // GridBlockMgr.ins.generateSpecificSelectionBlock(false);
                    GridBlockMgr.ins.generateSelectionBlock(false);
                }
                GridBlockMgr.ins.checkAndUpdateBlocks();
            } else {
                //不可以放置
                let targetBlock = touch_node.children[0];
                targetBlock.active = true;
                this.tempBlock.active = false;
            }
            this.isCanPlaced = false;
            if (!GlobalData.isCommer) {
                let isOver = GridBlockMgr.ins.detectGameOver();
                // console.log(isOver);

                if (isOver) {
                    MainGameLogic.ins.gameOver();
                }

            }
            this.isLongPress = false;

        } else {
            //旋转逻辑
            if (!GlobalData.isRotate) {
                return
            }
            let target_block_config = touch_node.children[0].getComponent(BlockController).curBlockConfig;
            if (target_block_config.block_type != 0 && target_block_config.block_type != 4 && target_block_config.block_type != 5) {
                touch_node.children[1].active = true;
            }

            let new_target_block_arr = this.rotateMatrix(target_block_config.block_arr);
            const matchingBlockConfig = this.findMatchingBlockConfig(new_target_block_arr);
            matchingBlockConfig.block_color = this.tempBlockColor;
            touch_node.children[0].getComponent(BlockController).updateBlockSet(true, matchingBlockConfig);
            touch_node.children[0].setPosition(Vec3.ZERO);
            touch_node.children[0].getComponent(BlockController).addBlockOffset(4);

            if (!GlobalData.isCommer) {
                let isOver = GridBlockMgr.ins.detectGameOver();
                if (isOver) {
                    MainGameLogic.ins.gameOver();
                }
            }
        }
        GridBlockMgr.ins.detectSelectsBlockCanUse(false);
    }

    //  判断数组一致性
    arraysEqual(arr1: number[][], arr2: number[][]): boolean {
        if (arr1.length !== arr2.length) return false;
        for (let i = 0; i < arr1.length; i++) {
            if (arr1[i].length !== arr2[i].length) return false;
            for (let j = 0; j < arr1[i].length; j++) {
                if (arr1[i][j] !== arr2[i][j]) return false;
            }
        }
        return true;
    }

    //  根据旋转后的二维数组，找到匹配的数据
    public findMatchingBlockConfig(arr: number[][]): BlockConfig | null {
        for (const block of BlocksAll) {
            if (this.arraysEqual(block.block_arr, arr)) {
                return block;
            }
        }
        return null;
    }

    //获取地区
    getRegion(pos: Vec3): Region | null {
        const nodeSize = 980;   // 节点的大小
        const gridSize = 8;     // 区域的数量
        const cellSize = 122.5; // 每个区域块的大小

        // 中心点的偏移量
        const halfNodeSize = nodeSize / 2;

        // 转换坐标到以中心点为原点的坐标系
        const localX = pos.x + halfNodeSize;
        const localY = pos.y + halfNodeSize;

        // 计算坐标所在的区域块索引
        const i = Math.floor((localY) / cellSize);
        const j = gridSize - 1 - Math.floor(localX / cellSize);

        // 检查索引是否在有效范围内
        if (i >= 0 && i < gridSize && j >= 0 && j < gridSize) {
            return { i, j };
        } else {
            return null;
        }
    }

    // 获取中心块的坐标和颜色
    // index_i: 当前块的行索引
    getCenteredBlocks(index_i: number, index_j: number, curBlockArr: number[][], curBlockColor: string, tempBlock: Node): ReConfig {
        if (!curBlockArr) {
            this.resumePromptBlock();
            return { iscanplaced: false, indexarr: null };
        }

        // 检查是否处于引导状态，并验证当前位置是否符合引导位置
        if (GlobalData.isCommer) {
            this.resumePromptBlock();
            if ((GlobalData.guideRecord == 1 && (index_i != Guide.ins.guideindex1[0] || index_j != Guide.ins.guideindex1[1])) ||
                (GlobalData.guideRecord == 2 && (index_i != Guide.ins.guideindex2[0] || index_j != Guide.ins.guideindex2[1])) ||
                (GlobalData.guideRecord == 3 && (index_i != Guide.ins.guideindex3[0] || index_j != Guide.ins.guideindex3[1]))) {

                return { iscanplaced: false, indexarr: null };
            }
        }

        const blocks: (number | null)[][] = Array(5).fill(null).map(() => Array(5).fill(null));
        const blocks_ba_node: (Node | null)[][] = Array(5).fill(null).map(() => Array(5).fill(null));
        const blocks_index: (number[] | null)[][] = Array(5).fill(null).map(() => Array(5).fill(null));

        const startI = Math.max(index_i - 2, 0);
        const endI = Math.min(index_i + 2, GridBlockMgr.ins.block_ba_data.length - 1);
        const startJ = Math.max(index_j - 2, 0);
        const endJ = Math.min(index_j + 2, GridBlockMgr.ins.block_ba_data[0].length - 1);

        for (let i = startI; i <= endI; i++) {
            for (let j = startJ; j <= endJ; j++) {
                const block = GridBlockMgr.ins.block_ba_data[i][j].block_state;
                const block_ba_node = GridBlockMgr.ins.block_ba_data[i][j].block_ba_node;
                const block_index = [GridBlockMgr.ins.block_ba_data[i][j].index_i, GridBlockMgr.ins.block_ba_data[i][j].index_j];
                blocks[i - (index_i - 2)][j - (index_j - 2)] = block;
                blocks_ba_node[i - (index_i - 2)][j - (index_j - 2)] = block_ba_node;
                blocks_index[i - (index_i - 2)][j - (index_j - 2)] = block_index;
            }
        }

        // 检查当前位置是否可以放置块
        for (let i = 0; i < 5; i++) {
            for (let j = 0; j < 5; j++) {
                const block = blocks[i][j];
                const curBlock = curBlockArr[i][j];
                if ((block === 1 && curBlock === 1) || (block === null && curBlock === 1)) {
                    this.resumePromptBlock();
                    return { iscanplaced: false, indexarr: null };
                }
            }
        }

        let returnIndexArr = [];
        // 显示提示位置
        for (let i = 0; i < 5; i++) {
            for (let j = 0; j < 5; j++) {
                const block = blocks[i][j];
                const curBlock = curBlockArr[i][j];
                if (block === 0 && curBlock === 1) {
                    blocks_ba_node[i][j].getComponent(UIOpacity).opacity = 150;
                    blocks_ba_node[i][j].getComponent(ResSprite).setSpriteFrame(curBlockColor + '/spriteFrame')

                    returnIndexArr.push(blocks_index[i][j]);
                }
            }
        }

        // 处理 tempBlock 的 25 个子节点并建立映射关系
        const tempBlockChildren = tempBlock.children;
        const tempBlockArr: (Node | null)[][] = Array(5).fill(null).map(() => Array(5).fill(null));
        for (let i = 0; i < 5; i++) {
            for (let j = 0; j < 5; j++) {
                tempBlockArr[i][j] = tempBlockChildren[i * 5 + j];
            }
        }

        // 创建临时棋盘数据对象，并模拟 tempBlock 已经放置
        const tempGrid = Array(8).fill(null).map(() => Array(8).fill(0));
        for (let i = 0; i < 8; i++) {
            for (let j = 0; j < 8; j++) {
                tempGrid[i][j] = GridBlockMgr.ins.block_ba_data[i][j].block_state;
            }
        }

        // 模拟放置 curBlockArr 到临时棋盘上
        for (let i = 0; i < 5; i++) {
            for (let j = 0; j < 5; j++) {
                if (curBlockArr[i][j] === 1) {
                    const gridI = index_i - 2 + i;
                    const gridJ = index_j - 2 + j;
                    if (gridI >= 0 && gridI < 8 && gridJ >= 0 && gridJ < 8) {
                        tempGrid[gridI][gridJ] = 1;
                    }
                }
            }
        }

        // 检查临时棋盘是否有可消除的行或列
        let canEliminate = false;
        const rowsToCheck = [];
        const colsToCheck = [];

        for (let i = 0; i < 8; i++) {
            if (tempGrid[i].every(value => value === 1)) {
                canEliminate = true;
                rowsToCheck.push(i);
            }
            if (tempGrid.every(row => row[i] === 1)) {
                canEliminate = true;
                colsToCheck.push(i);
            }
        }

        if (canEliminate) {
            // 放大真实棋盘上可消除的块
            rowsToCheck.forEach(row => {
                for (let j = 0; j < 8; j++) {
                    const blockNode = GridBlockMgr.ins.block_ba_data[row][j].block_ba_node;
                    if (blockNode && GridBlockMgr.ins.block_ba_data[row][j].block_state === BlockState.SHOW) {
                        blockNode.getComponent(Sprite).material = this.material;
                        this.enlargedBlocks.push(blockNode); // 记录放大的块
                    }
                }
            });
            5
            colsToCheck.forEach(col => {
                for (let i = 0; i < 8; i++) {
                    const blockNode = GridBlockMgr.ins.block_ba_data[i][col].block_ba_node;
                    if (blockNode && GridBlockMgr.ins.block_ba_data[i][col].block_state === BlockState.SHOW) {
                        blockNode.getComponent(Sprite).material = this.material;
                        this.enlargedBlocks.push(blockNode); // 记录放大的块
                    }
                }
            });

            // 放大 tempBlock 中会产生消除的块
            for (let i = 0; i < 5; i++) {
                for (let j = 0; j < 5; j++) {
                    if (curBlockArr[i][j] === 1) {
                        const gridI = index_i - 2 + i;
                        const gridJ = index_j - 2 + j;
                        if (rowsToCheck.includes(gridI) || colsToCheck.includes(gridJ)) {
                            tempBlockArr[i][j].getComponent(Sprite).material = this.material;
                            this.enlargedBlocks.push(tempBlockArr[i][j]); // 记录放大的块
                        }
                    }
                }
            }
        } else {
            this.resumePromptBlock();
        }

        return { iscanplaced: true, indexarr: returnIndexArr };
    }

    resumePromptBlock() {
        // 恢复上一次放大的块大小
        this.enlargedBlocks.forEach(node => {
            node.getComponent(Sprite).material = this.defaultmaterial;
        });
        this.enlargedBlocks = []; // 清空放大块的记录
    }

    /**
     * 获取坐标在目标节点（容器）下的相对位置
     * @param container 目标节点（容器）
     * @param nodepos 已有node节点坐标可传
     */
    public getRelativePosition(container: Node, nodepos?: Vec3,): Vec3 {
        //const worldPos = (node.getParent() || node).getComponent(UITransform).convertToWorldSpaceAR(nodepos ? nodepos : node.getPosition());
        return container.getComponent(UITransform).convertToNodeSpaceAR(nodepos);
    }

    /**
    * 获取A相对B的局部坐标
    * @param {*} nodeA 
    * @param {*} nodeB 
    */
    public getNodeAToNodeBPoint(nodeA: Node, nodeB: Node) {
        var nodeAWorldPoint = nodeA.getComponent(UITransform).convertToWorldSpaceAR(Vec3.ZERO);
        //console.log("nodeAWorldPoint",nodeAWorldPoint);
        var AToBPos = nodeB.getComponent(UITransform).convertToNodeSpaceAR(nodeAWorldPoint);

        return v3(AToBPos.x, AToBPos.y, 1) //{ x: AToBPos.x, y: AToBPos.y };
    }
    /**
     * 计算两个向量的差
     * @param vec1 向量1
     * @param vec2 向量2
     * @returns 
     */
    vectorDifference(vec1: Vec3, vec2: Vec3): Vec3 {
        // 使用 cc.Vec3 的 subtract 方法计算向量差
        const result = new Vec3();
        Vec3.subtract(result, vec1, vec2);
        return result;
    }
    /**
     * 
     * @param arr 判断选择区是否已经清空
     * @returns 
     */
    selectionConEmpty(): boolean {
        for (let i = 0; i < this.selectCanTouch.length; i++) {
            if (this.selectCanTouch[i] !== false) {
                return false;
            }
        }
        return true;
    }
    /**
     * 二维数组旋转
     * @param matrix 二维矩阵
     * @param clockwise 是否顺时针
     * @returns 
     */
    rotateMatrix(matrix: any[][], clockwise: boolean = true): any[][] {
        const N = matrix.length;
        const rotatedMatrix: any[][] = [];

        for (let i = 0; i < N; i++) {
            rotatedMatrix.push([]);
        }

        for (let i = 0; i < N; i++) {
            for (let j = 0; j < N; j++) {
                if (clockwise) {
                    rotatedMatrix[j][N - 1 - i] = matrix[i][j];
                } else {
                    rotatedMatrix[N - 1 - j][i] = matrix[i][j];
                }
            }
        }

        return rotatedMatrix;
    }


    /**
     * Vec2转Vec3
     * @param vec2 一个Vec2
     * @returns 一个Vec3
     */
    vec2ToVec3(vec2: Vec2): Vec3 {
        this.vec3Reusable.set(vec2.x, vec2.y, 0);
        return this.vec3Reusable;
    }


}

