import { _decorator, sys, utils} from "cc";
import { Singleton } from "../core/manager/Singleton";
import { Constants } from "./Constants";
import { Utils } from "../utils/Utils";
import { csvMgr } from "../core/csv/CsvManager";
import { stateMgr } from "../core/manager/StateManager";
const { ccclass, property } = _decorator;

@ccclass("UserData")
class UserData extends Singleton {
    //枪的属性列表
    public gunAttrKeys:string[] = ["attack","bulletSpeed","stability","magazine",
                               "reloadingSpeed","zoomingSpeed"];
    //玩家是否连续通关 如果连续通关 这个值会大于1
    public passNum: number = 0;
    //玩家数据
    private _data: any = null;
    public get data() {
        if (!this._data) {
            this.loadFromCache();
            this._data = new Proxy(this._data, {
            set: (target, prop, value) => {
                target[prop] = value;
                if(prop === "gold") {//金币
                   stateMgr.updateAllUI(Constants.gold);
                }else if(prop === "diamond") {//钻石
                   stateMgr.updateAllUI(Constants.diamond);
                }
                this.saveToCache();
                return true;
            }
        });
        }
        return this._data;
    }

    //敌人表
    public _enemyTable: Array<any> = null;
    public get enemyTable(){
        if(!this._enemyTable){
            this._enemyTable = csvMgr.getTableArr('enemy');
        }
        return this._enemyTable;
    }
    
    //敌人使用的武器表
    public _enemyWeaponTable: Array<any> = null;
    public get enemyWeaponTable(){
        if(!this._enemyWeaponTable){
            this._enemyWeaponTable = csvMgr.getTableArr('enemy_guns');
        }
        return this._enemyWeaponTable;
    }
    
     //扔飞票的表
    public _boomerangTable: Array<any> = null;
    public get boomerangTable(){
        if(!this._boomerangTable){
            this._boomerangTable = csvMgr.getTableArr('boomerang');
        }
        return this._boomerangTable;
    }

    //扔飞票商店
    public _boomerangShopTable: Array<any> = null;
    public get boomerangShopTable(){
        if(!this._boomerangShopTable){
            this._boomerangShopTable = csvMgr.getTableArr('boomerang_shop');
        }
        return this._boomerangShopTable;
    }

    //商店
    public _shopTable: Array<any> = null;
    public get shopTable(){
        if(!this._shopTable){
            this._shopTable = csvMgr.getTableArr('shop');
        }
        return this._shopTable;
    }
    
    //玩家表
    public _playerTable: Array<any> = null;
    public get playerTable(){
        if(!this._playerTable){
            this._playerTable = csvMgr.getTableArr('player');
        }
        return this._playerTable;
    }

    //关卡数据表
    public _levelsTable: Array<any> = null;
    public get levelsTable(){
        if(!this._levelsTable){
            this._levelsTable = csvMgr.getTableArr('levels');
        }
        return this._levelsTable;
    }

    //item数据表
    public _itemTable: Array<any> = null;
    public get itemTable(){
        if(!this._itemTable){
            this._itemTable = csvMgr.getTableArr('item');
        }
        return this._itemTable;
    }
    
    //玩家所有枪
    public _playerGunsTable: Array<any> = null;
    public get playerGunsTable(){
        if(!this._playerGunsTable){
            this._playerGunsTable = csvMgr.getTableArr('player_guns');
        }
        return this._playerGunsTable;
    }

    //玩家所有枪的属性
    public _playerGunAttsTable: Array<any> = null;
    public get playerGunAttsTable(){
        if(!this._playerGunAttsTable){
            this._playerGunAttsTable = csvMgr.getTableArr('player_guns_atts');
        }
        return this._playerGunAttsTable;
    }

    //杂物比如沙袋油漆桶数据
    public _sundriesTable: Array<any> = null;
    public get sundriesTable(){
        if(!this._sundriesTable){
            this._sundriesTable = csvMgr.getTableArr('sundries');
        }
        return this._sundriesTable;
    }
    /**
     * 读取数据缓存
     */
    public loadFromCache(){
        let l = sys.localStorage.getItem(Constants.localCache.playerData);
        if(l){//解密出来转成序列化JSON
            this._data = JSON.parse(Utils.decrypt(l));
        }else{
            //玩家配置数据
            let configData:any = Utils.clone(this.playerTable[0]);
            //查询玩家所有枪
            this._data = {
                gold: 88880,//金币
                diamond: 88880,//钻石
                boomerang: 0,//飞镖个数
                level: 1,//关卡等级
                ...configData, //转化的基础配置数据
                guns: [],//玩家拥有的枪
                useIdx: 0,
            };
            this.getGunData(configData.defaultWeapon,true);
        }
    }

    /**
     * 查询一个枪的数据 顺带把枪的属性等级提升的部分参数带过来
     * @param id 枪的id
     * @param isSave 是否保存绑定在玩家身上
     * @returns 返回枪查询的枪的数据
     */
    public getGunData(id: string,isSave: boolean = false):any{
        //如果玩家已经拥有该枪 则直接返回
        let gData: any = this._data.guns.find(e=>e.id == id);
        if(!gData){
            gData = Utils.clone(this.playerGunsTable).find(e=>e.id == id);
        }
        if(!gData)return;
        this.gunAttrKeys.forEach((arg_name:string,idx: number) => {
            const levelKey:string = `${arg_name}Level`;
            let attrLevel:number = 1;
            if(gData[levelKey] != null){
               attrLevel = gData[levelKey];
            }
            let fun: Function = (i,l,name)=>{
                const data:any = this.playerGunAttsTable.find(
                    e=>e.id == i 
                    && e.level == l
                    && e.attribute_name == name);
                return data;
            };
            let glData:any = fun(id,attrLevel,arg_name);
            if(glData){
                let nextGLData:any = fun(id,attrLevel + 1,arg_name);
                if(!nextGLData){nextGLData = glData};
                //unique_id 这个字段为了识别到时候同一个属性 升级极端情况下 材料消耗相同的时候的判断
                if(idx == 0){
                    gData.attack += glData.value;//伤害
                    gData.attackUniqueId = nextGLData.unique_id;//属性等级下的唯一id
                    gData.attackLevel= glData.level;//属性等级
                    gData.attackExpenditure = glData.expenditure;//当前等级消耗
                    gData.nextAttackExpenditure = nextGLData ? nextGLData.expenditure : null;//伤害下一个等级升级消耗
                }else if(idx == 1){
                    gData.bulletSpeed += glData.value;//射速
                    gData.bulletSpeedUniqueId = nextGLData.unique_id;//属性等级下的唯一id
                    gData.bulletSpeedLevel= glData.level;//属性等级
                    gData.bulletSpeedExpenditure = glData.expenditure;
                    gData.nextBulletSpeedExpenditure = nextGLData ? nextGLData.expenditure : null;//射速下一个等级升级消耗
                }else if(idx == 2){
                    gData.stability	+= glData.value;//稳定性
                    gData.stabilityUniqueId = nextGLData.unique_id;//属性等级下的唯一id
                    gData.stabilityLevel= glData.level;//属性等级
                    gData.stabilityExpenditure = glData.expenditure;
                    gData.nextStabilityExpenditure = nextGLData ? nextGLData.expenditure : null;//稳定性下一个等级升级消耗
                }else if(idx == 3){
                    gData.magazine+= glData.value;//弹匣
                    gData.magazineUniqueId = nextGLData.unique_id;//属性等级下的唯一id
                    gData.magazineLevel= glData.level;//属性等级
                    gData.magazineExpenditure = glData.expenditure;
                    gData.nextMagazineExpenditure = nextGLData ? nextGLData.expenditure : null;//弹匣下一个等级升级消耗
                }else if(idx == 4){
                    gData.reloadingSpeed += glData.value;//装填速度
                    gData.reloadingSpeedUniqueId = nextGLData.unique_id;//属性等级下的唯一id
                    gData.reloadingSpeedLevel= glData.level;//属性等级
                    gData.reloadingSpeedExpenditure = glData.expenditure;
                    gData.nextReloadingSpeedExpenditure = nextGLData ? nextGLData.expenditure : null;//装填速度下一个等级升级消耗
                }else if(idx == 5){
                    gData.zoomingSpeed += glData.value;//缩放速度
                    gData.zoomingSpeedUniqueId = nextGLData.unique_id;//属性等级下的唯一id
                    gData.zoomingSpeedLevel= glData.level;//属性等级
                    gData.zoomingSpeedExpenditure = glData.expenditure;
                    gData.nextZoomingSpeedExpenditure = nextGLData ? nextGLData.expenditure : null;//缩放速度下一个等级升级消耗
                }
            }
        });
        if(isSave){
            let indx: number = this._data.guns.findIndex(e=>e.id == gData.id);
            if(indx == -1){
               this._data.guns.push(gData);
            }
            this.saveToCache();
        }
        return gData;
    }

    /**
     * 查询玩家的一把武器的某个属性的总的值 和 武器某个属性升级的最大等级
     * @param gun 查询的枪
     * @param attribute_name 属性
     */
    public getGunMaxValue(gun: any,attribute_name: string): {
            totalValue: number, 
            maxLevel: number,
            isMaxLevel?: boolean
        }{
        if(!gun) return {totalValue: 0, maxLevel: 0,isMaxLevel: false};
        //过滤匹配的数据
        const filteredData = this.playerGunAttsTable.filter(
            e => e.id === gun.id && e.attribute_name === attribute_name
        );
        //计算总值
        const totalValue = filteredData.reduce((sum, item) => sum + item.value, 0);
        //计算最大等级 如果数组为空则返回0
        const maxLevel = filteredData.length > 0 
            ? Math.max(...filteredData.map(item => item.level)) 
            : 0;
        //基础值 + 升级累加值
        const attrLevelKey:string = `${attribute_name}Level`;
        const baseData:any = userIns.playerGunsTable.find(e=>e.id == gun.id);
        return {
            totalValue: baseData[attribute_name] + totalValue,
            maxLevel: maxLevel,
            isMaxLevel: gun[attrLevelKey] >= maxLevel
        };
    }

    /**
     * 升级某个枪的属性
     */
    public upgradeGun(gun: any,attribute_name: string){
        if(!gun)return;
        let hasGun:any = this.data.guns.find(e=>e.id == gun.id);
        if(!hasGun)return;
        //查询属性的等级
        const attrLevelKey:string = `${attribute_name}Level`;
        hasGun[attrLevelKey]+= 1;
        this.getGunData(gun.id,true);
    }

    /**
     * 得到当前用户使用的枪
     */
    public getCurUseGun(){
        let pData:any = {};
        if(this.data.useIdx < this.data.guns.length){
           let gun = this.data.guns[this.data.useIdx];
           Object.assign(pData,this._data,gun);
        }
        return pData;
    }

    /**
     * 用户切换使用的枪
     * @param id 枪的id
     */
    public changeGun(id: string){
        if(Utils.isNull(id))return;
        let idx:number = this.data.guns.findIndex(e=>e.id == id);
        if(idx != -1){
           this.data.useIdx = idx;
           this.getGunData(id,true);
        }
    }

    /**
     * 解锁全部枪玩家的枪
     */
    public unlockAllGuns(){
        Utils.clone(this.playerGunsTable).forEach(e => {
            this.getGunData(e.id,true);
        });
    }
    
    /**
     * 是否拥有这把枪
     */
    public isHasGun(id: string){
        if(Utils.isNull(id))return false;
        let gun:any = this.data.guns.find(e=>e.id == id);
        return gun != null;
    }
    
    /**
     * 解锁武器
     * @param id 枪的id
     */
    public unlockGun(id: string){
        if(Utils.isNull(id) || this.isHasGun(id))return;
        this.getGunData(id,true);
    }

    /**
     * 得到当前关卡下的敌人数据
     */
    public getCurLevelData(){
        const safeIndex = Math.min(this.data.level - 1, this.levelsTable.length -1);
        return this.levelsTable[safeIndex];
    }

    /**
     * 保存到缓存中
     */
    public saveToCache(){
        const data = JSON.stringify(this.data);
        //序列化JSON字符串过后加密存储
        sys.localStorage.setItem(Constants.localCache.playerData, Utils.encrypt(data));
    }

    /**
     * 删除缓存
     */
    public removeData(){
        this._data = null;
        sys.localStorage.removeItem(Constants.localCache.playerData);
        this.loadFromCache();
    }
}

//全局单例
export const userIns = UserData.ins();
