import { _decorator, Component, Mask, Node, tween, Tween, UITransform, v3, Vec3 } from "cc";
import { ICON_HEIGHT, ICON_MAP, ICON_WIDTH, ROLLER_EVENT } from "./Define";
import { IconFactory } from "./IconFactory";
import { EDITOR } from "cc/env";
import { Icon } from "./Icon";

let { ccclass, property, executeInEditMode } = _decorator;

/**
 * 滚轮状态枚举
 */
export enum ROLLER_STATE {
    ACCELERATE = 1,         // 加速
    UNIFORM = 2,            // 匀速
    DECELERATE = 3,         // 减速
    LAST_PAGE_CREATE = 4,   // 最后一页的创建
    BOUNCE = 5,             // 回弹
    STOP = 6,               // 停止
}

/**
 * 滚轮信息类
 * 存储滚轮运行时的各种状态和数据
 */
export class Info {
    icons: Node[] = [];              // 图标节点数组
    iconRule: number[] = [];         // 滚轮图标创建规则
    speed: number = 0;               // 当前速度
    speedNode: Node;                 // 速度控制节点
    receiveStopData: boolean = false;// 是否收到停止数据
    StopXnInfo: any = null;// 是否收到停止数据
    speedDataComplete: boolean = false;// 速度数据是否完成
    stopSpeedData: number[][] = null;// 停止时的速度数据
    state: ROLLER_STATE = ROLLER_STATE.STOP; // 当前状态
    isFastSpin: boolean = false;    // 是否快速旋转
    isManualStop: boolean = false;  // 是否手动停止    

    constructor() {
        this.speedNode = new Node('SpeedNode');
    }

    /**
     * 重置滚轮信息
     * 保留hitBlocks数据，重置其他状态
     */
    resetLxInfo() {
        this.receiveStopData = false;
        this.StopXnInfo = null
        this.speed = 0;
        this.stopSpeedData = null;
        this.isManualStop = false;
        this.speedDataComplete = false;
    }
}

/**
 * 滚轮组件类
 */
@ccclass('BaseRoller')
@executeInEditMode
export abstract class BaseRoller extends Component {
    // 编辑器属性
    @property({ tooltip: '图标宽度' })
    iconWidth: number = ICON_WIDTH;

    @property({ tooltip: '图标高度' })
    iconHeight: number = ICON_HEIGHT;

    @property({ type: IconFactory, tooltip: '图标工厂' })
    iconFactory: IconFactory = null;

    // 保护属性，子类可访问
    protected _rollerId: number = 0;
    protected _view: Node = null;
    protected _content: Node = null;
    protected _info: Info = new Info();
    protected _stopData: number[] = [];
    protected _crossSymbols: any = null; // 存储当前滚轮的n*1 Icon信息

    // 统一的图标管理结构
    protected _allIcons: Map<string, Node> = new Map(); // 存储所有图标节点，通过唯一key访问    
    protected _posToIconKey: Map<number, string> = new Map(); // 位置到图标key的映射

    // 性能优化相关缓存
    protected _cachedUITransform: UITransform = null;
    protected _positionCache: Map<number, Vec3> = new Map();

    /**
     * 获取内容节点
     * @returns 滚轮的内容节点
     */
    getContentNode(): Node {
        return this._content;
    }



    resizeContentSize() {
        // 初始化view节点
        this._view = this.node.getChildByName('view');
        if (!this._view) {
            this._view = this.createViewNode();
        }

        // 初始化content节点
        this._content = this._view.getChildByName('content');
        if (!this._content) {
            this._content = this.createContentNode();
        }

        // 设置尺寸和位置
        this.setupNodesSizeAndPosition();

        // 初始化缓存
        this.initCache();
    }


    /**
     * 创建view节点
     */
    createViewNode(): Node {
        let node = new Node('view');
        // node.addComponent(Mask);
        node.addComponent(UITransform);
        this.node.addChild(node);
        return node;
    }


    /**
     * 创建content节点
     */
    createContentNode(): Node {
        let node = new Node('content');
        node.addComponent(UITransform);
        this._view.addChild(node);
        return node;
    }

    /**
     * 通过位置获取图标节点
     * @param pos 位置索引
     * @returns 对应位置的图标节点
     */
    getIconNode(pos: number): Node {
        let iconId = this._posToIconKey.get(pos);
        if (iconId) {
            return this._allIcons.get(iconId);
        }
        return null;
    }

    /**
     * 为图标生成唯一ID
     * @param pos 位置索引
     * @param size 图标大小          
     * @returns 唯一key字符串
     */
    generateIconKey(startPos: number, size: number, endPos: number): string {
        if (size > 1) {
            return `large_${startPos}_${endPos}_${size}`;
        } else {
            return `normal_${startPos}_${endPos}_${size}`;
        }
    }


    /**
     * 初始化滚轮
     * @param rollerId 滚轮ID
     */
    initRoller(rollerId: number) {
        this._rollerId = rollerId;
        this._view = this.node.getChildByName('view');
        this._content = this._view.getChildByName('content');
        this._content.removeAllChildren();

        // 清空图标映射
        this._allIcons.clear();
        this._posToIconKey.clear();
        this._crossSymbols = null;

        if (!EDITOR) {
            // 运行时初始化
            this._info.speedNode.parent = null;
            this.node.addChild(this._info.speedNode);
        }
    }

    /**
     * 初始化滚轮并创建初始图
     * @param id 滚轮ID
     * @param data 初始图标数据数组
     * @param crossSymbols n*1 Icon数据
     */
    initRollerWithIcon(id: number, data: number[], crossSymbols?: any, XnInfo?: any) {
        this.iconFactory.init();
        this.initRoller(id);
        // 创建图标
        this._crossSymbols = crossSymbols;
        this.createInitIcons(data, XnInfo, id == 0);
    }

    /**
     * 创建初始图标，包括处理n*1 Icon
     * @param data 图标数据数组
     */
    createInitIcons(data: number[], XnInfo: any, isHroll: boolean) {
        // 清空现有的图标和映射
        this._allIcons.clear();
        this._posToIconKey.clear();

        // 先处理n*1 Icon
        if (this._crossSymbols && Object.keys(this._crossSymbols).length > 0) {
            // 创建n*1 Icon
            this.createSpecialIcons(XnInfo);
        }

        // 然后创建普通图标（跳过已被n*1 Icon占用的位置）
        for (let i = 0; i < data.length; i++) {
            // 如果位置已被占用，跳过
            if (this._posToIconKey.has(i)) continue;

            let iconIndex = data[i];
            this.createNormalIcon(i, iconIndex, XnInfo, isHroll);
        }
    }

    createSpecialIcons(XnInfo: any) {
        // 直接使用已有的符号数据，避免重复处理
        let processedPoses = new Set<string>(); // 用于跟踪已处理的符号ID
        // 遍历所有位置的符号数据
        for (let pos in this._crossSymbols) {
            let iconSpecialMsg = this._crossSymbols[pos];
            // 如果这个符号ID已经处理过，跳过
            if (processedPoses.has(iconSpecialMsg.id)) continue;
            // 标记这个符号ID为已处理
            processedPoses.add(iconSpecialMsg.id);
            // 创建特殊图标
            this.createOneSpecialIcon(iconSpecialMsg, XnInfo);
        }
    }

    /**
     * 创建n*1 Icon
     * @param pos 位置索引
     * @param iconIndex 图标类型索引
     * @param height 图标高度     
     * @param frameType 框架类型
     * @returns 创建的图标节点
     */
    createOneSpecialIcon(iconSpecialMsg: any, XnInfo: any): Node {
        let startPos = iconSpecialMsg.startPos;
        let endPos = iconSpecialMsg.endPos;
        let height = iconSpecialMsg.lHeight;
        let iconIndex = iconSpecialMsg.iconIndex;
        let frameType = iconSpecialMsg.frameType;
        // 生成图标ID
        let iconKey = this.generateIconKey(startPos, height, endPos);
        // 创建图标节点
        let icon = this.iconFactory.icfactoryCreateIcon(iconIndex);
        // 初始化图标
        let multi = 0
        if (XnInfo.Bottom && iconIndex == 2) {
            for (let i = 0; i < XnInfo.Bottom.length; i++) {
                if (XnInfo.Bottom[i].StartIndex == startPos + (this._rollerId - 1) * 5) {
                    multi = XnInfo.Bottom[i].N
                }
            }
        }
        icon.getComponent(Icon).initIcon(iconIndex, height, iconKey, frameType, this._rollerId, multi);
        // 设置位置
        let position = this.getIconPosition(startPos, height);
        this._content.addChild(icon);
        icon.setPosition(position);

        // 存储图标节点
        this._allIcons.set(iconKey, icon);
        // 设置位置映射
        for (let i = 0; i < height; i++) {
            this._posToIconKey.set(startPos + i, iconKey);
        }
        return icon;
    }

    /**
     * 创建普通图标
     * @param pos 位置索引
     * @param iconIndex 图标类型索引
     * @returns 创建的图标节点
     */
    createNormalIcon(pos: number, iconIndex: number, XnInfo: any, isHroll: boolean): Node {
        // 生成图标ID
        let iconKey = this.generateIconKey(pos, 1, pos);
        // 创建图标节点
        let icon = this.iconFactory.icfactoryCreateIcon(iconIndex);
        // 初始化图标
        let multi = 1
        if (XnInfo.Top || XnInfo.Bottom) {
            let XnInfoData = isHroll ? XnInfo.Top : XnInfo.Bottom
            if (XnInfoData) {
                for (let i = 0; i < XnInfoData.length; i++) {
                    if (XnInfoData[i].StartIndex == pos + (isHroll ? 0 : (this._rollerId - 1) * 5)) {
                        multi = XnInfoData[i].N
                    }
                }
            }
        }
        icon.getComponent(Icon).initIcon(iconIndex, 1, iconKey, 0, this._rollerId, multi);
        // 设置位置
        let position = this.getIconPosition(pos, 1);
        this._content.addChild(icon);
        icon.setPosition(position);
        // 存储图标节点
        this._allIcons.set(iconKey, icon);
        this._posToIconKey.set(pos, iconKey);
        return icon;
    }

    /**
     * 设置n*1 Icon数据
     * @param crossSymbols n*1 Icon数据
     */
    setCrossSymbols(crossSymbols: any) {
        this._crossSymbols = crossSymbols;
    }

    /**
     * 设置滚轮图标规则
     * @param rollerIconRule 图标规则数组
     */
    setRollerIconRule(rollerIconRule: number[]) {
        this._info.iconRule = rollerIconRule;
    }

    /**
     * 设置快速旋转模式
     * @param isFastSpin 是否快速旋转
     */
    setFastSpin(isFastSpin: boolean) {
        if (this._info.isFastSpin === isFastSpin) return;
        this._info.isFastSpin = isFastSpin;
    }

    /**
     * 重置滚轮信息
     */
    resetInfo() {
        this._stopData = null;
        this._info.resetLxInfo();
    }
    /**
     * 获取初始速度数据
     * @returns 速度数据数组
     */
    getInitialSpeedData(): number[][] {
        return this._info.isFastSpin ?
            [
                // [0.1, -1000],
                [0, 0],
                [0, 4000]
            ] :
            [
                [0.05 * this._rollerId, 0],
                // [0.1, -1000],
                [0.1, 0],
                [0.1, 4000]
            ];
    }


    /**
     * 开始滚动
     */
    startScroll() {
        if (this._info.state != ROLLER_STATE.STOP) {
            return;
        }

        // 收集现有图标
        this.collectExistingIcons();

        // 设置速度数据
        let speedData = this.getInitialSpeedData();

        // 开始加速
        this.changeState(ROLLER_STATE.ACCELERATE);
        this.tweenSpeed(speedData, () => {
            // 进入匀速阶段
            let uniformSpeedData = this._info.isFastSpin ? [[0]] : [[0.3]];
            this.changeState(ROLLER_STATE.UNIFORM);

            this.tweenSpeed(uniformSpeedData, () => {
                this._info.speedDataComplete = true;
                let stopSpeedData = this._info.isFastSpin ? [[0, 6000]] : [[0.1, 3500]];
                if (this._info.receiveStopData) {

                    this.stopScrollWork(stopSpeedData, this._info.StopXnInfo);
                }
            });
        });
    }

    /**
     * 停止滚动
     * @param data 停止时的图标数据
     */
    stopScroll(data: number[], stopSpeedData: number[][], XnInfo: any) {
        this._stopData = data;
        this._info.receiveStopData = true;
        this._info.StopXnInfo = XnInfo

        // 如果速度数据已完成，执行停止逻辑
        if (this._info.speedDataComplete) {

            this.stopScrollWork(stopSpeedData, this._info.StopXnInfo);
        }
    }


    /**
     * 执行停止滚动的具体工作
     */
    stopScrollWork(stopSpeedData: number[][], XnInfo) {
        // 如果不是手动停止，执行正常的停止逻辑
        if (!this._info.isManualStop) {
            this.changeState(ROLLER_STATE.DECELERATE);

            // 设置停止时的速度数据
            this._info.stopSpeedData = stopSpeedData;

            // 执行减速动画
            this.tweenSpeed(this._info.stopSpeedData, () => {
                this.changeState(ROLLER_STATE.LAST_PAGE_CREATE, XnInfo);
            });
        }
    }

    /**
     * 执行速度变化动画
     * @param speedData 速度数据数组
     * @param callback 完成回调
     * @param obsv 回调的this指向
     */
    tweenSpeed(speedData: number[][], callback: Function = null, obsv: any = null) {
        let speedNode = this._info.speedNode;
        let speed = this._info.speed;

        // 停止现有动画
        Tween.stopAllByTarget(speedNode);
        speedNode.setPosition(0, speed);

        // 创建动画序列
        let timeline = 0;
        speedData.forEach((cur, i) => {
            if (cur.length === 2) {
                // 速度变化动画
                this.createSpeedChangeTween(speedNode, cur, timeline, i === speedData.length - 1, callback, obsv);
                timeline += cur[0];
            } else if (cur.length === 1) {
                // 延时
                this.createDelayTween(speedNode, cur[0], timeline, i === speedData.length - 1, callback, obsv);
                timeline += cur[0];
            }
        });
    }


    /**
     * 创建速度变化动画
     */
    createSpeedChangeTween(
        speedNode: Node,
        data: number[],
        startTime: number,
        isLast: boolean,
        callback: Function,
        obsv: any
    ) {
        tween(speedNode)
            .delay(startTime)
            .to(data[0], { position: v3(0, data[1], 0) }, {
                onUpdate: () => {
                    this._info.speed = Math.floor(speedNode.position.y);
                }
            })
            .call(() => {
                if (isLast && callback) {
                    callback.call(obsv);
                }
            })
            .start();
    }

    /**
    * 创建延时动画
    */
    createDelayTween(
        speedNode: Node,
        delay: number,
        startTime: number,
        isLast: boolean,
        callback: Function,
        obsv: any
    ) {
        tween(speedNode)
            .delay(startTime)
            .delay(delay)
            .call(() => {
                if (isLast && callback) {
                    callback.call(obsv);
                }
            })
            .start();
    }

    /**
    * 改变滚轮状态
    * @param state 目标状态
    */
    changeState(state: ROLLER_STATE, XnInfo?: any) {
        if (this._info.state === state) return;

        this._info.state = state;

        // 状态变化处理
        switch (state) {
            case ROLLER_STATE.LAST_PAGE_CREATE:
                this.createLastPage(XnInfo);
                break;
            case ROLLER_STATE.BOUNCE:
                this.emitRollerEvent(ROLLER_EVENT.ROLLER_BOUNCE);
                break;
            case ROLLER_STATE.STOP:
                this.emitRollerEvent(ROLLER_EVENT.ROLLER_STOP);
                break;
        }
    }

    /**
     * 发送滚轮事件
     * @param eventName 事件名称
     */
    emitRollerEvent(eventName: string) {
        this.node.emit(eventName, this._rollerId);
    }




    /**
     * 获取随机图标索引
     */
    getRandomIconIndex(): number {
        let rule = this._info.iconRule;
        if (!rule?.length) {
            let res = Math.floor(Math.random() * this.iconFactory.getIconNum());
            if (res == 2) {
                res = 3
            }
            return res
        }
        let res = rule[Math.floor(Math.random() * rule.length)];
        if (res == 2) {
            res = 3
        }
        return res
    }

    /**
     * 判断是否显示快速图标效果
     */
    shouldShowFastIcon(): boolean {
        return this._info.state === ROLLER_STATE.ACCELERATE ||
            this._info.state === ROLLER_STATE.UNIFORM;
    }

    /**
     * 检查是否正在滚动
     */
    isScroll(): boolean {
        return this._info.state !== ROLLER_STATE.STOP;
    }

    /**
     * 更新方法
     */
    localUpdate(dt: number) {
        if (EDITOR) return;

        let state = this._info.state;
        if (this.shouldUpdateRoller(state)) {
            this.updateRollerMovement(dt, state);
        }
    }

    /**
    * 判断是否需要更新滚轮
    */
    shouldUpdateRoller(state: ROLLER_STATE): boolean {
        return state !== ROLLER_STATE.STOP && state !== ROLLER_STATE.BOUNCE;
    }

    /**
     * 更新滚轮移动
     */
    updateRollerMovement(dt: number, state: ROLLER_STATE) {
        this.rollerMove(dt);
        this.recycleRollerIcon();

        switch (state) {
            case ROLLER_STATE.LAST_PAGE_CREATE:
                this.stopProcess();
                break;
            case ROLLER_STATE.ACCELERATE:
            case ROLLER_STATE.UNIFORM:
            case ROLLER_STATE.DECELERATE:
                this.suppleIcon();
                break;
        }
    }

    /**
    * 获取图标的世界坐标
    */
    getIconWorldPosition(pos: number): Vec3 {

        let iconKey = this._posToIconKey.get(pos);
        let icon = this._allIcons.get(iconKey);
        if (!icon) {

            return null; // 返回安全的默认值
        }

        return this._content.getComponent(UITransform).convertToWorldSpaceAR(icon.position);
    }

    /**
   *改变速度
   */
    changeSpeed() {
        this._info.speed = 7000;
    }

    abstract setupNodesSizeAndPosition(): void;

    abstract getIconPosition(pos: number, size: number): Vec3;

    abstract initCache(): void;

    abstract collectExistingIcons(): void;

    abstract manualStopScroll(data: number[], XnInfo: any): void;

    abstract createLastPage(XnInfo: any): void;

    abstract checkDeadLine(icon: Node): boolean;

    abstract suppleIcon(): void;

    abstract findHighestIconXorY(icons: Node[]): number;

    abstract computeNewIconXorY(): number;

    abstract createRandomIcon(): void;

    abstract rollerMove(dt: number): void;

    abstract recycleRollerIcon(): void;

    abstract stopProcess(): void;

    abstract playBounceAnimation(): void;

    abstract deleteIconNode(deleteMsg: any): void;

    abstract playFrameTypeChangeAni(positions: number[]): void;

    abstract showMultiMove(XnInfo): void;

    abstract chanegeIconAndFrameType(data: any[]): void;

    abstract createNewIconTop(createDatas: number[], XnInfo: any): void;

    abstract iconFallDown(data: number[], crossSymbols: any): void;
}