import { _decorator, EventTouch, Node, Quat, math, Camera, sys, Vec3, Label, geometry, ProgressBar, tween, easing, Tween, UIOpacity, game, PhysicsSystem, PhysicsRayResult } from 'cc';
import { Game } from '../game/Game';
import { BaseExp } from '../core/base/BaseExp';
import { autoBind } from '../extend/AutoBind';
import { Constants } from '../data/Constants';
import { uiMgr } from '../core/manager/UIManager';
import { userIns } from '../data/UserData';
import MsgHints from '../utils/MsgHints';
import List from '../third/List';
import { Utils } from '../utils/Utils';
import { TaskEnemyItem } from '../items/item/TaskEnemyItem';
import { BulletMagazine } from '../game/BulletMagazine';
import { audioMgr } from '../core/manager/AudioManager';
const { ccclass, property } = _decorator;
const { clamp, toRadian } = math;

@ccclass('GunfightShootUI')
export class GunfightShootUI extends BaseExp {
    @autoBind({ type: Node, tooltip: "轮盘节点" })
    public wheel: Node;
    @autoBind({ type: Node, tooltip: "标准贴图" })
    public scopeOverlay: Node;
    @autoBind({ type: Node, tooltip: "准心" })
    public crossHair: Node;
    @autoBind({ type: ProgressBar, tooltip: "步枪子弹进度条" })
    public rifle_bullet_progressBar: ProgressBar;
    @autoBind({ type: Label, tooltip: "步枪子弹数文本" })
    public rifle_bullet_num_label: Label;
    @autoBind({ type: BulletMagazine, tooltip: "步枪子弹列表" })
    public rifle_bullets_scrollView: BulletMagazine;
    @autoBind({ type: BulletMagazine, tooltip: "狙击枪子弹列表" })
    public snipe_bullets_scrollView: BulletMagazine;
    @autoBind({ type: Node, tooltip: "步枪显示子弹的总的节点" })
    public rifle_bullets_bg: Node;
    @autoBind({ type: List, tooltip: "敌人任务列表" })
    public task_scrollView: List;
    @autoBind({ type: ProgressBar, tooltip: "玩家生命进度条" })
    public hpProgressBar: ProgressBar;
    @property({type: [Node], tooltip: "要隐藏的所有按钮"})
    public hiddeNodes: Array<Node> = [];
    @autoBind({ type: ProgressBar, tooltip: "换弹夹时间进度条" })
    public reloadProgressBar: ProgressBar;
    @autoBind({ type: Node, tooltip: "玩家受到伤害呼吸闪烁" })
    public injury_blood: Node;
    @autoBind({ type: Label, tooltip: "玩家枪的名字" })
    public gun_name_label: Label;

    /** 子弹飞行距离 */
    public bulletDistance: number = 800;
    /** 当前相机绕 X 轴的旋转角度 */
    private currentXRotation: number = 0;
    /** 当前相机绕 Y 轴的旋转角度 */
    private currentYRotation: number = 0;
    /** 左右旋转角度的最大限制值 */
    private maxHorizontalAngle: number = 70;
    /** 上下旋转角度的最大限制值 */
    private maxVerticalAngle: number = 40;
    /** 相机的原始视野值 */
    private originalFov: number;
    /** 玩家节点的初始旋转四元数 */
    private initialPlayerRotation: Quat = new Quat();
    /** 相机节点的初始旋转四元数 */
    private initialCameraRotation: Quat = new Quat();
    /**相机旋转的灵敏度 值越大移动越快 灵敏度越高*/
    private sensitivity: number = 0.5;
    /** 相机放大后的目标视野值 */
    private targetFov: number;
    /** 标记相机是否正在进行放大操作 */
    private isZoomingIn: boolean = false;
    /** 标记相机是否正在进行缩小操作 */
    private isZoomingOut: boolean = false;
    /** 相机视野放大的速度 */
    private zoomSpeed: number = 0;
    /** 期望的缩放时间，单位为秒 */
    private zoomDuration: number = 0.2;
    /** 记录镜头开始放大的时间 */
    private zoomStartTime: number = 0;
    /** 标记是否在2秒内完成放大 */
    private zoomValid: boolean = false;

    /** 标记是否开镜 */
    private _isScopeOpen: boolean = false;
    get isScopeOpen() {
        return this._isScopeOpen;
    }
    set isScopeOpen(value: boolean) {
        this.gunDataUI();
        if (this._isScopeOpen !== value) {
            this._isScopeOpen = value;
            if (value) {
                this.openScope();
            } else {
                this.closeScope();
            }
        }
    }
    /**镜头的位置*/
    private wheelPos: Vec3 = Vec3.ZERO;
    //任务数据
    private taskDatas: Array<any> = [];
    //是否正在被击中
    private isHurtRun: boolean = false;

    start() {
        this.hasAnim = false;
        this.closeOnBlank = false;
        this.injury_blood.active = false;
        this.reloadProgressBar.node.active = false;

        if(!Constants.isDebug){
           this.hiddeNodes.forEach(e => e.active = false);
        }
        this.wheelPos = this.wheel.position.clone();
        //记录摄像机原始视野
        this.originalFov = Game.I.camera.getComponent(Camera).fov;
        //录初始旋转角度
        this.initialPlayerRotation = Game.I.player.node.rotation.clone();
        this.initialCameraRotation = Game.I.camera.node.rotation.clone();
        //监听当前节点触摸事件
        this.node.on(Node.EventType.TOUCH_START, this.onNodeTouchMove, this);
        this.node.on(Node.EventType.TOUCH_MOVE, this.onNodeTouchMove, this);
        this.node.on(Node.EventType.TOUCH_END, this.onCustomNodeTouchEnd, this);
        this.node.on(Node.EventType.TOUCH_CANCEL, this.onCustomNodeTouchEnd, this);

        //监听轮盘点击事件 监听轮盘的触摸开始事件，当触摸开始时调用 onWheelClick 方法
        this.wheel.on(Node.EventType.TOUCH_START, this.onWheelClick, this);
        this.wheel.on(Node.EventType.TOUCH_END, this.onWheelRelease, this);
        this.wheel.on(Node.EventType.TOUCH_CANCEL, this.onWheelRelease, this);
        //敌人数量改变
        this.register(Constants.eventName.enemy_num_change, this.loadTaskData.bind(this));
    }

    public show(...args: any[]){
        this.loadTaskData();
    }

    /**
     * enemyId total count enemyData
     * 加载数据
     */
    public loadTaskData() {
        this.taskDatas = Game.I.buildEnemys.enemyTypeRecords;
        this.task_scrollView.numItems = this.taskDatas.length;
        //加载子弹的数据
        this.gunDataUI();
    }
    
    /**
     * 任务数据
     * @param item item节点
     * @param idx 数据下标
     */
    public setTaskItemData(item: Node, idx: number) {
        item.getComponent(TaskEnemyItem).init(this.taskDatas[idx]);
    }

    /**
     * 设置枪的数据
     */
    public gunDataUI() {
        const gData:any = Game.I.player.pData;
        if(Game.I.isGameOver 
            || Game.I.isPause 
            || !Game.I.player.gun
            || !gData){
           return;
        }
        this.crossHair.active = true;//准心
        //步枪没有开镜贴图
        this.scopeOverlay.active = !this.isRifleGun();
        this.gun_name_label.string = gData.name_lang;
        const isSnipeGun: boolean = gData.type == 1;
        //换弹夹进度条
        const isMagazine: boolean = Game.I.player.isReloadMagazine;
        if(isMagazine){
           this.rifle_bullets_bg.active = false;
           this.snipe_bullets_scrollView.node.active = false;
        }else{
            //步枪子弹视图
            this.rifle_bullets_bg.active = !isSnipeGun;
            //狙击子弹视图列表
            this.snipe_bullets_scrollView.node.active = isSnipeGun;
            if(isSnipeGun){
                this.snipe_bullets_scrollView.magazineNum = gData.magazine;
            }else{
                this.rifle_bullets_scrollView.magazineNum = gData.magazine;
                //子弹进度条
                let s_bullet: number = gData.magazine - Game.I.player.gun.shotBullets;
                this.rifle_bullet_progressBar.progress = s_bullet / gData.magazine;
                this.rifle_bullet_num_label.string = `${s_bullet}/${gData.magazine}`;
            }
        }
    }

    /**
     * 更换弹夹动画
     * @param time 换弹时间 单位秒
     * @param complete 完成回调
     */
    public reloadMagazineing(time: number,complete?: Function) {
        if(time <= 0){
            complete?.();
        }else{
            this.reloadProgressBar.node.active = true;
            this.reloadProgressBar.progress = 1;
            this.rifle_bullets_bg.active = false;
            this.snipe_bullets_scrollView.node.active = false;
            //创建定时器动画
            tween(this.reloadProgressBar)
                .to(time, { progress: 0 }, {
                    easing: easing.linear,
                    onStart: () => {
                        tween(this.reloadProgressBar).stop();
                    },
                    onComplete: () => {
                        this.reloadProgressBar.node.active = false;
                        complete?.();
                    }
                })
                .start();
        }
    }

    /**
     * 根据切换枪的stability设置镜头的稳定性
     */
    public crossHairStability() {
        const gData:any = Game.I.player.pData;
        if(!gData)return;
        this.gunDataUI();
        this.wheel.position = this.wheelPos;
        //参数映射优化（假设stability范围0-1） 振幅稳定性越低振幅越大 频率稳定性越低抖动越快
        const amplitude = 20 * (1 - gData.stability / 1000); 
        let elapsed = 0;
        //基础抖动持续时间
        const duration = 0.4; 
        const updateShake = (deltaTime: number) => {
            elapsed += deltaTime;
            //双轴随机偏移
            const offsetX = amplitude * (Math.random() - 0.5) * Math.max(1 - elapsed/duration, 0);
            const offsetY = amplitude * (Math.random() - 0.5) * Math.max(1 - elapsed/duration, 0);
            this.wheel.position = new Vec3(
                this.wheelPos.x + offsetX,
                this.wheelPos.y + offsetY,
                this.wheelPos.z
            );
            //自动结束
            if(elapsed >= duration) {
                this.wheel.position = this.wheelPos;
                this.unschedule(updateShake);
            }
        };
        this.unschedule(updateShake);
        // 使用游戏时间而非系统时间
        this.schedule(updateShake, 0.02); // 每0.02秒更新（约50FPS）
    }

    /**
     * 屏幕触摸事件
     * 触摸移动时，根据触摸的位置计算旋转角度，并应用到节点上
     * @param event 
     */
    private onNodeTouchMove(event: EventTouch) {
        const delta = event.getDelta();
        //计算旋转角度
        this.currentYRotation -= delta.x * this.sensitivity;
        this.currentXRotation -= delta.y * this.sensitivity; 
        //分别限制左右和上下旋转角度
        this.currentYRotation = clamp(this.currentYRotation, -this.maxHorizontalAngle, this.maxHorizontalAngle);
        this.currentXRotation = clamp(this.currentXRotation, -this.maxVerticalAngle, this.maxVerticalAngle);
        //计算水平和垂直旋转的四元数
        const yQuat = new Quat();
        Quat.fromEuler(yQuat, 0, this.currentYRotation, 0);
        const xQuat = new Quat();
        Quat.fromEuler(xQuat, +this.currentXRotation, 0, 0);
        //合并旋转
        let finalQuat = new Quat();
        Quat.multiply(finalQuat, yQuat, xQuat);
        //将最终旋转与初始摄像机旋转合并
        Quat.multiply(finalQuat, this.initialPlayerRotation, finalQuat);
        //应用旋转到摄像机
        Game.I.player.node.rotation = finalQuat;
    }

    /**
     * 触摸结束
     * 触摸结束时 触摸结束处理方法
     */
    private onCustomNodeTouchEnd() {
        //触摸结束，可添加其他逻辑
    }

    /**
     * 开始慢慢放大视野
     */
    private onWheelClick() {
        this.isScopeOpen = true;
    }

     /**
     * 恢复原始视野
     */
     private onWheelRelease() {
        if(!this.zoomValid){
            this.isScopeOpen = false;
            return
        }
        this.scheduleOnce(()=>{
            //检查是否在秒内完成放大 已经在update里开镜完成时调用 Game.I.player.shoot();
            this.isScopeOpen = false;
        },0.2)
    }

    /**
     * 开始开镜
     */
    private openScope() {
        //从枪械数据获取参数
        const gData = Game.I.player.pData;
        if(!gData)return;
        const isRifle: boolean = this.isRifleGun();
        //是步枪直接连续开火
        if(isRifle){
           Game.I.player.shoot();
        }
        this.isZoomingIn = true;
        //将 zoomingSpeed 转换为持续时间（450对应1.2秒）
        this.zoomDuration = 72 / gData.zoomingSpeed;
        //使用枪械类型决定视口倍数 步枪使用 rifleZoom 狙击枪使用 scopeZoom
        const zoomMultiplier = isRifle ? 
            1 / gData.rifleZoom :
            1 / gData.scopeZoom; 
        this.targetFov = this.originalFov * zoomMultiplier;
        //保持原有速度计算逻辑
        const fovDifference = this.originalFov - this.targetFov;
        this.zoomSpeed = fovDifference / this.zoomDuration;
        this.zoomStartTime = sys.now();
    }
    
    // 在 closeScope 方法中保持相同持续时间
    private closeScope() {
        this.isZoomingIn = false;
        this.isZoomingOut = true;
        const fovDifference = this.originalFov - this.targetFov;
        //使用相同 zoomDuration 保证缩镜速度一致
        this.zoomSpeed = fovDifference / this.zoomDuration; 
    }

    /**
     * 是否是步枪
     */
    public isRifleGun(){
        const gData:any = Game.I.player.pData;
        if(!gData)return false;
        return gData.id == '100014' || gData.id == '100015';
    }


    /**
     * 计算从枪口出发，沿准心射线方向的点
     * @param isBulletEndPos 是否获得子弹的终点
     */
    public getCrossHairPos(){
        //获取屏幕准心位置（世界坐标）
        const worldPos = this.crossHair.worldPosition.clone(); 
        const camera2D: Camera = Game.I.canvas.getChildByName('Camera2D').getComponent(Camera);
        let screenPos = camera2D.worldToScreen(worldPos);
        //校准补偿准心的偏移量
        screenPos.x -= 0;
        screenPos.y += this._isScopeOpen ? 60 : 40;
        //从摄像机发射通过准心的射线
        const ray = new geometry.Ray();
        Game.I.camera.screenPointToRay(screenPos.x, screenPos.y, ray);
        //获取枪口位置
        const muzzlePos = Game.I.player.gun.muzzleNode.worldPosition;
        return new Vec3(
                muzzlePos.x + ray.d.x * this.bulletDistance,
                muzzlePos.y + ray.d.y * this.bulletDistance,
                muzzlePos.z + ray.d.z * this.bulletDistance);
    }

    /**
     * 玩家血量低于30%一直闪烁、打一枪的时候闪一下
     * @param progress 血量进度
     * @returns 
     */
    public playerHurtTwinkle(progress: number){
        this.hpProgressBar.progress = progress;
        const isLowHP = progress <= 0.3;
        const op = this.injury_blood.getComponent(UIOpacity);
        //如果当前是高血量且正在闪烁 停止并隐藏
        if (!isLowHP && this.isHurtRun) {
            this.isHurtRun = false;
            Tween.stopAllByTarget(op);
            this.injury_blood.active = false;
            return;
        }
        if (isLowHP && !this.isHurtRun) {//低血量且未在闪烁时，启动循环闪烁
            this.isHurtRun = true;
            this.injury_blood.active = true;
            op.opacity = 255;
            tween(op)
                .to(0.5, { opacity: 0 }, { easing: easing.linear }) 
                .to(0.5, { opacity: 255 }, { easing: easing.linear })
                .repeatForever()   
                .start();
        }else if (!isLowHP) {//高血量时触发单次闪烁
            this.injury_blood.active = true;
            Tween.stopAllByTarget(op);
            op.opacity = 255;
            tween(op)
                .to(0.4, { opacity: 0 }, { easing: easing.linear }) 
                .call(() => {
                    this.injury_blood.active = false;
                })
                .start();
        }
    }

    /**
     * 点击事件
     * @param event 事件
     * @param customEventData 数据
     */
    public onBtnClicked(event: EventTouch, customEventData: any) {
        super.onBtnClicked(event,customEventData);
        let btnName = event.target.name;
        if (btnName === 'pause_btn') { // 暂停页面
            uiMgr.show(Constants.popUIs.pauseUI);
        }else if (btnName === 'shot_btn') {//射击
            if(this.isRifleGun){
                //模拟按下射击
                this._isScopeOpen = true;
                Game.I.player.shoot();
                this.scheduleOnce(()=>{
                    this._isScopeOpen = false;
                },1.5)
            }else{
                Game.I.player.shoot();
            }
        }else if (btnName === 'cut_gun_btn') {//切枪
            Game.I.player.randomCutGun()
        }else if(btnName === 'clean_btn'){//重新加载数据
            userIns.removeData();
            Game.I.player.pData = userIns.getCurUseGun();
            MsgHints.show('重新加载数据完成');
        }else if(btnName === 'unlock_btn'){//解锁全部枪数据
            userIns.unlockAllGuns();
            MsgHints.show('已经解锁全部枪数据');
        }
    }

    /**
     * 每帧更新，处理视野渐变和检查 2 秒时间限制
     * @param deltaTime - 上一帧到当前帧的时间间隔
     */
    update(deltaTime: number) {
        if (this.isZoomingIn) {
            const currentFov = Game.I.camera.fov;
            if (currentFov > this.targetFov) {
                const newFov = currentFov - this.zoomSpeed * deltaTime;
                Game.I.camera.fov = Math.max(newFov, this.targetFov);
            } else {
                //检查是否在2秒内完成放大
                const elapsedTime = (sys.now() - this.zoomStartTime) / 1000;
                if (elapsedTime <= 1.5) {
                    this.zoomValid = true;
                }
                this.isZoomingIn = false;
            }
        } else if (this.isZoomingOut) {
            const currentFov = Game.I.camera.fov;
            if (currentFov < this.originalFov) {
                const newFov = currentFov + this.zoomSpeed * deltaTime;
                Game.I.camera.fov = Math.min(newFov, this.originalFov);
            } else {
                this.isZoomingOut = false;
                this.zoomValid = false;
                //非步枪开镜结束开火
                if(!this.isRifleGun()){
                    Game.I.player.shoot();
                }
            }
        }
    }
}

