import { Color, instantiate, sys, tween, UIOpacity, v3, Vec3, Node, Sprite, sp, resources, isValid, director, UITransform } from 'cc';
import EventManager from './Manager/EventManager';
import { GameConst } from './Config';
import LogMgr from './Manager/LogMgr';
import ResManger from './Manager/ResManger';

export default class GFunc {
    public static openPages() {
        return GameConst.openPages;
    }
    //---------以上代码在正式环境中不能运行------------
    //关闭当前最上层的页面
    public static closePage() {
        //EventManager.emit('closePage', GameConst.openPages[GameConst.openPages.length - 1]);
        let lastPage = GameConst.openPages[GameConst.openPages.length - 1];
        //----读取openPages里面的顺序关掉最后一个页面，然后打开上一个页面
        let upPage = GameConst.openPages[GameConst.openPages.length - 2];
        LogMgr.error('要切换到的页面是：', upPage);
        if (upPage) {
            let pIdx = GameConst.menuPage.indexOf(upPage);
            if (pIdx >= 0) {
                EventManager.emit('switchPage', '' + pIdx);
            } else {
                EventManager.emit('showPage', upPage);
            }
        } else {
            EventManager.emit('switchPage', '0');
        }
        EventManager.emit('closePage', lastPage);
        EventManager.emit('closePop');
        EventManager.emit('clearGuide');
    }
    //添加打开的页面名到 openPages 数组中
    public static addToOpenPage(pageName: string) {
        let idx = GameConst.openPages.indexOf(pageName);
        if (idx >= 0) {
            GameConst.openPages.splice(idx);
        }
        GameConst.openPages.push(pageName);
    }
    //获取品质的颜色
    public static getColor(str: string): Color {
        return new Color().fromHEX(this.getColorCode('' + str));
    };
    public static getColorCode(str: string): string {
        let color = {
            '1': '#C8CED0', //白装黑色
            '2': '#A2C082', //绿
            '3': '#8AB3D8', //蓝
            '4': '#A47DC6', //紫色
            '5': '#FFD651', //橙色

            'Gray': '#999999',//灰色
            'Normal': '#FFFFFF',//白色
            'Yellow': '#FFC03F',//黄色
            'BLACK': '#333333',//黑色

            '(Failed)': '#9E0000',//失败的红色
            '(Completed)': '#00FF00',//完成的绿色
            '(Pending)': '#333333',//等待中的黑色

            'less': '#9E0000',//不足的红色
            'enough': '#00FF00',//足够的绿色
            'notEnough': '#666666',//进度不足的灰黑色

            'taskNot': '#333333',//任务没完成的黑色标题
            'taskFinish': '#FF9F0B',//任务已完成的橙色标题

            'inviteReach': '#666666',//邀请进度已达成的黑色文字
            'inviteNot': '#999999',//邀请进度没达成的灰色文字

            'redTip': '#B13636',//红字提示
            'greenTip': '#72A937',//绿字提示
            'yellowTip': '#FF9F0B',//黄字提示
            "greenClock": "6FE27A",//签到文字
            "yellowClock": "FFC70A",

            'soundOn': '#8ADF80',//声音开的绿色
            'soundOff': '#917163',//声音关的赭色
        };
        return color['' + str];
    }
    //获取日期时间信息 输出：2024/08/29 13:04
    public static formatDateString(timeStamp: number = 0, dateString: string = ''): string {
        let date: Date = new Date(GameConst.netTime);
        if (timeStamp) {
            date = new Date(timeStamp);
        } else if (dateString) {
            date = new Date(dateString);
        }
        let year = date.getFullYear();
        let month = date.getMonth() + 1;
        let day = date.getDate();
        let hours = date.getHours();
        let minutes = date.getMinutes();

        return `${year}/${month < 10 ? `0${month}` : month}/${day < 10 ? `0${day}` : day} ${hours < 10 ? `0${hours}` : hours}:${minutes < 10 ? `0${minutes}` : minutes}`;
    };
    public static formatDateString1(timeStamp: number = 0, dateString: string = '', needSecond: boolean = false): string {
        let date: Date = new Date(GameConst.netTime);
        if (timeStamp) {
            date = new Date(timeStamp);
        } else if (dateString) {
            date = new Date(dateString);
        }
        //let year = date.getFullYear();
        let month = date.getMonth() + 1;
        let day = date.getDate();
        let hours = date.getHours();
        let minutes = date.getMinutes();

        let str = `${month < 10 ? `0${month}` : month}/${day < 10 ? `0${day}` : day} ${hours < 10 ? `0${hours}` : hours}:${minutes < 10 ? `0${minutes}` : minutes}`;
        if (needSecond) {
            let second = date.getSeconds();
            str += `:${second < 10 ? `0${second}` : second}`;
        }
        return str;
    };
    //格式化倒计时显示
    public static formatDjs(second: number = 0): string {
        if (second <= 0) {
            return '00:00:00';
        }
        let djsStr = '';
        let hour = Math.floor(second / 3600);
        let minute = Math.floor((second - hour * 3600) / 60);
        let sec = Math.floor(second - hour * 3600 - minute * 60);
        djsStr = `${hour < 10 ? `0${hour}` : hour}:${minute < 10 ? `0${minute}` : minute}:${sec < 10 ? `0${sec}` : sec}`;
        return djsStr;
    }
    //获取当前时间戳,这个时间戳不严密，是手机本地时间而不是联网时间戳的
    public static getTimeSign(isSecond: boolean = true, timeStr: string = null) {
        let date: Date = new Date(GameConst.netTime);
        if (timeStr) {
            date = new Date(timeStr);
        }
        if (isSecond) {
            return Math.floor(date.getTime() / 1000);
        } else {
            return date.getTime();
        }
    }
    public static getTimeStr() {
        let date: Date = new Date(GameConst.netTime);
        return date.toLocaleString();//'2025/4/18 17:56:04'
    }
    //读取本地存储的数据
    public static getLocal(key: string) {
        let str = sys.localStorage.getItem('AIMine-' + key);
        if (!str) {
            return false;
        } else {
            try {
                return JSON.parse(str);
            } catch (error) {
                return str;
            }
        }
    };
    //保存数据到本地存储
    public static setLocal(key: string, value: Object | String | Number) {
        let saveData = GFunc.copyData(value);
        if (typeof (saveData) == 'object') {
            saveData = JSON.stringify(saveData);
        }
        sys.localStorage.setItem('AIMine-' + key, saveData);
    };
    public static removeLocal(key: string) {
        sys.localStorage.removeItem('AIMine-' + key);
    };
    //浅拷贝数据
    public static copyData(data: any): any {
        if (typeof (data) == 'object') {
            return JSON.parse(JSON.stringify(data));
        } else {
            return data;
        }
    };
    //获取日期信息
    public static getNYR(timeStamp: number = 0) {
        let date: Date = new Date(GameConst.netTime);
        if (timeStamp) {
            date = new Date(timeStamp);
        }
        return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
    };
    //重新显示合适的名称长度，超过限制的显示...
    public static showName(name: string, len: number = 10) {
        if (name.length > len) {
            return name.slice(0, len - 3) + '...';
        } else {
            return name;
        }
    }
    //重新显示合适的名称长度，超过限制的显示...
    public static showNameMid(name: string, len: number = 10) {
        if (name.length > len) {
            return name.slice(0, 4) + '...' + name.slice(name.length - 4, name.length);
        } else {
            return name;
        }
    }
    /**
     * 重新显示较长的数字为短数字,省略精度,保留4个小数位
     * @param num number 输入的数字
     * @param digit number 保留的小数位数，默认4个
     */
    public static showShorter(num: number | string, digit: number = 4, maxLen: number = 10): string {
        if (num.toString().length <= maxLen) {
            return '' + num;
        } else {
            if (typeof (num) == 'number' && num.toString().length - num.toString().indexOf('.') > maxLen - digit) {
                return num.toFixed(digit) + '...';
            } else if (typeof (num) == 'string') {
                if (digit) {
                    if (num.length >= digit - 4) {
                        return num.slice(0, digit) + '...';
                    }
                } else {
                    if (num.length >= maxLen) {
                        return num.slice(0, maxLen) + '...';
                    }
                }
            } else {
                return '' + num;
            }
        }
    }
    /**
     * 显示千分位分隔的数字形式
     * @param num number 输入的数字
     * @param digit number 保留的小数位数，默认4个
     */
    public static commasNumber(num: number | string, digit: number = 4): string {
        if (typeof (num) == 'number') {
            num = num.toString();
        }
        // 将数字转换为字符串
        const parts = num.split('.');
        // 对整数部分进行千分位格式化
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
        // 如果有小数部分，返回格式化后的字符串
        //return parts.length > 1 ? parts.join('.') : parts[0];
        if (parts.length > 1) {
            if (digit > 0) {
                parts[1] = parts[1].slice(0, digit);
                return parts.join('.');
            } else {
                return parts[0];
            }
        } else {
            return parts[0];
        }
    }
    /**
     * 使用 K M B 显示数字
     * @param num number 输入的数字
     * @param digit number 保留的小数位数，默认2个
     */
    public static shorterKMB(num: number, digit: number = 2): string {
        if (num >= 1000000000) {
            return (num / 1000000000).toFixed(digit) + 'B';
        } else if (num >= 1000000) {
            return (num / 1000000).toFixed(digit) + 'M';
        } else if (num >= 1000) {
            return (num / 1000).toFixed(digit) + 'K';
        } else {
            return '' + num.toFixed(digit);
        }
    }
    //使用kmb格式化数字，省略末尾的0
    public static formatNumber(value, decimals = 3) {
        if (value < 1000) {
            // 小于 1000 不加后缀
            return this.trimNum(value, decimals); // 调用自定义的截取小数方法
        }
        const units = ['k', 'm', 'b', 't']; // 后缀单位
        let unitIndex = -1;
        while (value >= 1000 && unitIndex < units.length - 1) {
            value /= 1000; // 继续缩小数字，添加单位
            unitIndex++;
        }
        return `${this.trimNum(value, decimals)}${units[unitIndex]}`;
    }
    public static trimNum(value, decimals) {
        const factor = Math.pow(10, decimals); // 计算 10^decimals
        return (Math.floor(value * factor) / factor).toString(); // 截取多余的小数位
    }
    //保留3位小数
    public static trimDecimal(value: number): number {
        // 将输入转换为字符串
        const valueStr = value.toString();
        // 检查是否是小数
        if (valueStr.includes('.')) {
            const [integerPart, decimalPart] = valueStr.split('.'); // 拆分整数部分和小数部分
            if (decimalPart.length > 3) {
                // 如果小数部分超过三位，舍弃多余部分
                return parseFloat(`${integerPart}.${decimalPart.substring(0, 3)}`);
            }
        }
        // 如果没有小数部分，或小数部分不超过三位，直接返回
        return value;
    }

    ///-----
    public static GFormatNumber(value, decimals = 3) {//不带四舍五入，用于钱包余额的显示
        if (value < 1000) {
            // 小于 1000 不加单位，保留指定小数位但不四舍五入
            return this.GnoRound(value, decimals).toString();
        }

        const units = ['k', 'm', 'b', 't']; // 单位数组
        let unitIndex = -1;

        while (value >= 1000 && unitIndex < units.length - 1) {
            value /= 1000; // 缩放数字到 1000 以下
            unitIndex++;
        }

        // 确保缩放后的值保留小数位但不四舍五入
        return `${this.GnoRound(value, decimals)}${units[unitIndex]}`;
    }

    // 不进行四舍五入的方法
    public static GnoRound(value, decimals) {
        const strValue = value.toString();
        const [integerPart, decimalPart] = strValue.split('.');
        if (!decimalPart || decimalPart.length <= decimals) {
            // 如果没有小数部分或小数位数不超过指定长度，直接返回原值
            return value;
        }
        // 截取到指定小数位长度但不进行四舍五入
        const truncatedDecimal = decimalPart.slice(0, decimals);
        return parseFloat(`${integerPart}.${truncatedDecimal}`);
    }

    public static formatNumberSR(value, decimals = 3) {//有四舍五入的，用于上架是售价的显示
        if (value < 1000) {
            return parseFloat(value.toFixed(decimals)).toString();
        }
        const units = ['k', 'm', 'b', 't'];
        let unitIndex = -1;
        while (value >= 1000 && unitIndex < units.length - 1) { value /= 1000; unitIndex++; }
        return `${parseFloat(value.toFixed(decimals)).toString()}${units[unitIndex]}`;
    }
    //----
    /**根据给定属性key重新对数组进行排序，会改变原数组 */
    public static sortArrayByKey(arr: any[], key: string, isMinToMax: boolean = true) {
        if (!arr || arr.length < 1 || !key || !arr[0].hasOwnProperty(key)) {
            LogMgr.warn('sortArrayByKey参数错误,len:', arr.length, 'key:', key, !arr[0].hasOwnProperty(key));
            return;
        }
        arr.sort((a, b) => {
            if (isMinToMax) {
                return a[key] - b[key];
            } else {
                return b[key] - a[key];
            }
        });
    }
    /**
     * 对数组进行随机排序，会改变原数组
     * @param arr 数组
     */
    public static randSortArray(arr: any[]) {
        if (!arr || arr.length < 1) {
            LogMgr.warn('randSortArray参数错误,len:', arr.length);
            return;
        }
        arr.sort(function () {
            return Math.random() - 0.5;
        });
    }
    public static getJuXingPoints(count: number, pos: Vec3, width: number, height: number): Vec3[] {
        let points = [];
        for (let i = 0; i < count; i++) {
            /*
            //以下三行会得到一个椭圆圆周上的落点
            let angle = (pos.x - width / 2) + Math.random() * 100 * width / count; // 当前角度
            let x = pos.x + width / 2 * Math.sin((Math.PI / 180) * angle);
            let y = pos.y + height / 2 * Math.cos((Math.PI / 180) * angle);*/
            //在矩形中心pos的基础上，在矩形范围内纯随机落点
            let x = (pos.x - width / 2) + Math.random() * width
            let y = (pos.y - height / 2) + Math.random() * height
            points.unshift(v3(x, y, 0));
        }
        return points;
    }
    /**
     * 以某点为圆心，生成圆周上等分点的坐标
     *
     * @param {number} r 半径
     * @param {cc.Vec2} pos 圆心坐标
     * @param {number} count 等分点数量
     * @param {number} [randomScope=80] 等分点的随机波动范围
     * @returns {cc.Vec2[]} 返回等分点坐标
     */
    public static getCirclePoints(r: number, pos: Vec3, count: number, randomScope: number = 60): Vec3[] {
        let points = [];
        let radians = (Math.PI / 180) * Math.round(360 / count);
        for (let i = 0; i < count; i++) {
            let x = pos.x + r * Math.sin(radians * i);
            let y = pos.y + r * Math.cos(radians * i);
            points.unshift(v3(x + Math.random() * randomScope, y + Math.random() * randomScope, 0));
        }
        return points;
    }
    //以某点为圆心，扇形等分点的坐标
    public static getShanXingPoints(r: number, pos: Vec3, count: number, randomScope: number = 60): Vec3[] {
        let points = [];
        let startAngle = -135; // 起始角度
        let endAngle = -215; // 结束角度
        let angleRange = endAngle - startAngle; // 角度范围
        let radians = (Math.PI / 180) * angleRange / count; // 每个点之间的弧度差

        for (let i = 0; i < count; i++) {
            let angle = startAngle + i * angleRange / count; // 当前角度
            let x = pos.x + r * Math.sin((Math.PI / 180) * angle);
            let y = pos.y + r * Math.cos((Math.PI / 180) * angle);
            points.unshift(v3(x + Math.random() * randomScope, y + Math.random() * randomScope, 0));
        }
        return points;
    }

    /**
     * 使用贝塞尔曲线移动的tween动画
     * @param node 移动的节点
     * @param pos 移动的坐标数组
     * @param time 移动的时长
     * @param delayTime 移动的延迟时间
     * @param bezier 贝塞尔曲线控制点数组
     * */
    public static tweenBezierMove(node: Node, pos: Vec3[], time: number = 2, delayTime: number = 1,) {
        if (!node || !pos || pos.length < 3) {
            return;
        }
        const quadraticCurve = (t: number, p1: Vec3, cp: Vec3, p2: Vec3, out: Vec3) => {
            out.x = (1 - t) * (1 - t) * p1.x + 2 * t * (1 - t) * cp.x + t * t * p2.x;
            out.y = (1 - t) * (1 - t) * p1.y + 2 * t * (1 - t) * cp.y + t * t * p2.y;
            out.z = (1 - t) * (1 - t) * p1.z + 2 * t * (1 - t) * cp.z + t * t * p2.z;
        }

        const startPos = v3(pos[0].x, pos[0].y, 0);
        const controlPos = v3(pos[1].x, pos[1].y + 200, 0);
        const endPos = v3(pos[pos.length - 1].x, pos[pos.length - 1].y, 0)
        const tempVec3 = v3();

        tween(node)
            .delay(delayTime)
            .to(time, { position: endPos }, {
                onUpdate: (target, ratio) => {
                    quadraticCurve(ratio, startPos, controlPos, endPos, tempVec3);
                    node.setPosition(tempVec3);
                }
            })
            .call(() => {
                node.destroy();
            })
            .start();
    }
    //获取最终子节点
    public static seekChild(path: string, parentNode: Node) {
        let pathArr = path.split('/'), pNode = parentNode;
        for (let i = 0; i < pathArr.length; i++) {
            let cNode = pNode.getChildByName(pathArr[i]);
            if (cNode && isValid(cNode)) {
                pNode = cNode;
            } else {
                return null;
            }
        }
        return pNode;
    }

}