
namespace vv {
    /**全局消息注册分发 */
    export let Notifi = new cc.EventTarget();
    /**存储本地数据 */
    export function saveData(name: string, data: any) {
        data = JSON.stringify(data)
        cc.log("本地存储：", name, data)
        cc.sys.localStorage.setItem(name, data);
    }

    /**读取本地数据 */
    export function readData(name: string) {
        let data = cc.sys.localStorage.getItem(name)
        data = JSON.parse(data);
        cc.log("本地读取：", name, data)
        return data
    }
    export let lang = lang_();
    export function lang_(): string {
        let str = cc.sys.localStorage.getItem("language");
        if (str == "" || str == null) str = "en";
        return str;
    };
    /**找到子节点
      @param nodeName 子节点名称
      @param parentNode 开始寻找的父节点
      */
    export function findChildNode(nodeName: string, parentNode: cc.Node) {
        let node: cc.Node = null
        let nodes: cc.Node[] = []
        let fun = (parentNode: cc.Node) => {
            for (let i of parentNode.children) {
                if (i.name == nodeName) {
                    nodes.push(i)
                    if (nodes.length > 1) {
                        //cc.warn("至少存在2个同名子节点:", nodes, nodeName, parentNode.name)
                        return node
                    }
                }
                if (i.childrenCount > 0) {
                    fun(i)
                }
            }
        }
        fun(parentNode)

        switch (nodes.length) {
            case 0:
                //cc.warn("找不到子节点:", nodeName, parentNode.name)
                return null;
            default:
                return nodes[0];
        }
    }

    /**
    * 加载图片
    * @param url 图片地址（网图不加png后缀，本地需要）
    * @param spriteNode 需要改变纹理的节点
    * @param isNet 默认false：本地资源, true:是网图
    */
    export function loadTexture(url: string, spriteNode: cc.Node | cc.Sprite, isNet?: boolean) {
        if (spriteNode == null) return
        spriteNode.getComponent(cc.Sprite).spriteFrame = null
        if (url == "" || url == null) return cc.log("url is null");
        if (isNet == null || !isNet) {
            cc.loader.loadRes(url, cc.SpriteFrame, (error, texture) => {
                if (error) {
                    cc.warn("图片加载失败！path:", url)
                    return
                }
                let sp = texture
                if (!spriteNode.isValid) return;
                if (spriteNode instanceof cc.Node) {
                    spriteNode.getComponent(cc.Sprite).spriteFrame = sp
                }
                else {
                    spriteNode.spriteFrame = sp
                }
            })
        }
        else {
            cc.loader.load(url, (error, texture) => {
                if (error) return error
                let sp = new cc.SpriteFrame(texture)
                if (!spriteNode.isValid) return;
                if (spriteNode instanceof cc.Node) {
                    spriteNode.getComponent(cc.Sprite).spriteFrame = sp
                }
                else {
                    spriteNode.spriteFrame = sp
                }
            })
        }
    }

    /**
     * 添加点击事件
     * 回调必须要lambda表达式或者bind(this)
     * @param target 添加点击的节点
     * @param cb 回调方法
     * @param bindNode 绑定脚本
     */
    export function addBtnEvent(target: cc.Node, cb: Function, bindNode: any, clickAudio = true) {
        let btn: cc.Button = target.getComponent(cc.Button);
        if (!btn) btn = target.addComponent(cc.Button);
        btn.clickEvents = [];
        target.on("click", (...arg) => {
            // if (clickAudio)
            //vv.playAudio("ui_click");
            cb?.(...arg);
        }, bindNode);
    }

    export function deleteBtnEvent(target: cc.Node, bindNode: any, clickAudio = true) {
        let btn: cc.Button = target.getComponent(cc.Button);
        if (!btn) btn = target.addComponent(cc.Button);
        btn.clickEvents = [];
        target.targetOff(bindNode)
    }

    /**
     * 数字跳动 
     * @param startNum 起始值
     * @param originNum 目标值
     * @param go 数字节点
     * @param time 跳动时间
     */
    export function numberAnim(startNum: number, endNum: number, go: cc.Node, str: string = "", time: number = 0.6) {
        let originNum = (endNum - startNum) * 100;
        let obj: any = {};
        obj.num = originNum;
        let tempNum = 0;
        let ac = cc.tween(obj)
            .to(time, { num: 0 }, {
                progress: (start, end, current, t) => {
                    tempNum = Math.ceil((start - end) * t);
                    go.getComponent(cc.Label).string = str + vv.goldFormat((Number(Number(startNum) + Number(((tempNum) / 100).toFixed(2))).toFixed(2)));
                    return start + (start - end) * t;
                }
            })
            .call(() => {
                go.getComponent(cc.Label).string = str + vv.goldFormat(Number(endNum).toFixed(2));
            })
            .start();
        return ac;
    }

    /**
     * 将数字格式转换成 100.000,00 的格式
     * @param num 数字或字符串类型的数
     * @param isInt 整数是否保留.00
     * @returns 
     */
    export function goldFormat(num, isInt = false) {
        if (typeof (num) == "string") num = Number(num);
        let fushu = false;
        if (num < 0) {
            fushu = true;
            num = Math.abs(num);
        }
        if (isInt) {
            num = num.toString();
            if (num.indexOf(".") != -1) {
                num = num.split(".")[0];
                cc.warn("当前传入的不是正数");
            }
            let str = "";
            let zheng = "";
            let idx = 0;
            for (let i = num.length - 1; i > -1; i--) {
                str = num[i] + str;
                idx++;
                if (idx % 3 == 0 || i == 0) {
                    if (zheng != "")
                        zheng = str + "." + zheng;
                    else zheng = str + zheng;
                    str = "";
                }
            }
            return fushu ? "-" + zheng : zheng;
        }

        num = num.toFixed(2);
        let arr = num.split(".");
        let dian = arr.length == 1 ? "00" : arr[1];
        if (Number(dian) < 10 && dian.length == 1) dian = "0" + dian;
        let str = "";
        let zheng = "";
        let idx = 0;
        for (let i = arr[0].length - 1; i > -1; i--) {
            str = arr[0][i] + str;
            idx++;
            if (idx % 3 == 0 || i == 0) {
                if (zheng != "")
                    zheng = str + "." + zheng;
                else zheng = str + zheng;
                str = "";
            }

        }

        return fushu ? ("-" + zheng + "," + dian) : (zheng + "," + dian);
    }

    /**
     * 分割网址中的参数
     * @param url 网址
     * @returns 
     */
    export function getUrlData(url: string): any {
        let arr = url.split("?");
        if (arr.length == 1) {
            return null
        }
        let arr1 = arr[1].split("&");
        let data = {};
        arr1.forEach(v => {
            let temp = v.split('=');
            if (!temp[1] || data[temp[0]]) {

            } else
                data[temp[0]] = temp[1];
        });
        return data;
    }

    /**加载预制体并适配 适配仅限个别预制体 */
    export function loadPrefab(str, parent = null, cb = null, isactive = true) {
        return new Promise((resolve, reject) => {
            cc.resources.load<cc.Prefab>("Prefab/" + str, (err, res) => {
                if (err) {
                    reject(err);
                    return cc.warn(err);
                }
                let can = cc.find("Canvas");
                let ch = cc.instantiate(res);
                let arr = str.split("/");
                ch.name = arr[arr.length - 1];
                ch.active = isactive;
                if (parent == null) ch.parent = can;
                else ch.parent = parent;
                if (cb != null && typeof (cb) == 'function') cb(ch);
                resolve(ch);
            })
        })
    }

    /**预加载场景 */
    export function preLoadScene(sceneName, onProgressCB = null) {
        return new Promise((resolve, reject) => {
            cc.director.preloadScene(sceneName, (completedCount: number, totalCount: number, item: any) => {
                onProgressCB && onProgressCB(completedCount, totalCount);
            }, (err) => {
                if (err) {
                    reject(err);
                    return;
                }
                cc.log(`场景 ${sceneName} 预加载完成`)
                resolve(sceneName);
            })
        });
    }

    /**预加载场景 */
    export function loadScene(sceneName, onProgressCB = null) {
        return new Promise((resolve, reject) => {
            cc.director.loadScene(sceneName, (err) => {
                if (err) {
                    reject(err);
                    return;
                }
                cc.log(`场景 ${sceneName} 加载完成`)
                resolve(sceneName);
                onProgressCB?.()
            })
        });
    }


    /**时间戳转换成时间格式
    @param format 格式,比如:"2019.6.3" "2018-11-27" "11月7日" "13:05:45:585"
    @param time 时间戳[13位](兼容10位 默认当前时间)
    @param bitZero 是否补零(只针对月、日) 默认不补零
    */
    export function timeToTime(format: string, time?: number, bitZero: boolean = false) {
        if (time == null) time = Date.now()
        if (time < 100000000000) time = time * 1000
        let newTime = new Date(time)
        let str = ""

        if (format.includes(" ")) {
            cc.warn("该时间字符串模版未实现解析:", format)
            return str
        }

        if (format.indexOf(":") == -1) { //年月日
            let year = String(newTime.getFullYear())
            let month = String(newTime.getMonth() + 1)
            let day = String(newTime.getDate())

            if (bitZero) {
                if (month.length == 1) month = "0" + month
                if (day.length == 1) day = "0" + day
            }

            let m = ""

            if (format.indexOf(".") > 0) m = "."
            else if (format.indexOf("-") > 0) m = "-"
            else if (format.indexOf("/") > 0) m = "/"

            if (m != "") {
                let num = 0
                for (let i = 0; i < format.length; i++) {
                    if (format[i] == m) num++
                }

                if (num == 2) { //年月日
                    str = year + m + month + m + day
                } else if (num == 1) { //年月或月日
                    if (format.length < 6) { //月日
                        str = month + m + day
                    } else { //年月
                        str = year + m + month
                    }
                }
            } else {
                if (format.includes("年") && format.includes("日")) { //年月日
                    str = year + "年" + month + "月" + day + "日"
                } else if (format.includes("年")) { //年月
                    str = year + "年" + month + "月"
                } else if (format.includes("日")) { //月日
                    str = month + "月" + day + "日"
                }
            }
        } else {
            let f = format.split(':')

            let hour = String(newTime.getHours())
            let minute = String(newTime.getMinutes())
            let second = String(newTime.getSeconds())
            let millisecond = String(newTime.getMilliseconds())

            if (hour.length == 1) hour = "0" + hour
            if (minute.length == 1) minute = "0" + minute
            if (second.length == 1) second = "0" + second
            while (millisecond.length < 3) millisecond = "0" + millisecond

            if (f.length == 4) { //小时:分:秒:毫秒
                str = hour + ":" + minute + ":" + second + ":" + millisecond
            } else if (f.length == 3) {
                if (f[2].length > 2 || +f[0] > 24) { //分:秒:毫秒
                    str = minute + ":" + second + ":" + millisecond
                } else { //小时:分:秒
                    str = hour + ":" + minute + ":" + second
                }
            } else if (f.length == 2) {
                if (+f[0] > 24) { //分:秒
                    str = minute + ":" + second
                } else { //小时:分
                    str = hour + ":" + minute
                }
            }
        }

        if (str == "") cc.warn("该时间字符串模版未实现解析:", format)

        return str
    }
    /** 00:00:00 */
    export function timeToTime2(time?: number) {
        if (time == null) time = Date.now()
        if (time < 100000000000) time = time * 1000
        let newTime = new Date(time)
        let str = ""

        let hour = String(newTime.getHours())
        let minute = String(newTime.getMinutes())
        let second = String(newTime.getSeconds())

        if (hour.length == 1) hour = "0" + hour
        if (minute.length == 1) minute = "0" + minute
        if (second.length == 1) second = "0" + second

        str = hour + ":" + minute + ":" + second;
        cc.log(hour, minute, second)
        cc.log(str)
        return str
    }

    /** 00:00:00 */
    export function timeToTime3(time?: number) {
        let str = "";
        let hour: any = Math.floor(time / 3600);
        let less: any = time - 3600 * hour;
        let minute: any = Math.floor(less / 60);
        less = less - 60 * minute;
        let second: any = less;
        if (hour < 10) hour = "0" + hour;
        if (minute < 10) minute = "0" + minute;
        if (second < 10) second = "0" + second;

        str = hour + ":" + minute + ":" + second;
        return str
    }


    //加载resources下文件
    export function loadRes(url, type, completeCallback?, progressCallback?) {
        var extname = cc.path.extname(url);
        if (extname) {
            url = url.slice(0, - extname.length);
        }

        cc.resources.load(url, type, progressCallback, (err, asset: cc.Asset) => {
            if (err) {
                console.error("加载失败", url, "\n", err);
                return;
            }
            completeCallback(asset);
        });
    }

    /**子节点转换子节点坐标 */
    export function nodePosToNodePos(node_1: cc.Node, node_2: cc.Node) {
        let wPos = this.nodePosToWord(node_1);
        let nPos = this.nodePosToNode(node_2);
        return nPos;
    }

    /**转世界坐标 */
    export function nodePosToWord(node: cc.Node) {
        return node.parent.convertToWorldSpaceAR(node.position);
    }

    /**将世界坐标转节点坐标 */
    export function nodePosToNode(pos: cc.Vec3, node: cc.Node) {
        return node.convertToNodeSpaceAR(pos);
    }

    /**限制小数点后位数，大于5位限制5，小于5显示正常，最少保留2位 */
    export function limtStr(number, limit = 5) {
        let str = number.toString();
        let arr = str.split(".");
        if (arr.length > 1 && arr[1].length > 2) {
            if (arr[1].length > 5) return number.toFixed(limit);
            else return number.toFixed(arr[1].length);
        }
        return number.toFixed(2);
    }

    export function maskString(str: string): string {
        const length = str.length;
        if (length === 0) {
            // 如果是空字符串，返回 "***"
            return '***';
        } else if (length === 1) {
            // 如果长度为1，保留该字符前后加上“***”
            return str + '***';
        } else if (length === 2) {
            // 如果长度为2，保留前1和后1，中间加上“***”
            return str.charAt(0) + '***' + str.charAt(1);
        } else if (length < 6) {
            // 如果长度小于6，保留前2位和后2位
            return str.slice(0, 2) + '***' + str.slice(-2);
        } else {
            // 如果长度大于或等于6，保留前3位和后3位
            return str.slice(0, 3) + '***' + str.slice(-3);
        }
    }




    export function webCopyString(copyStr) {
        const el = document.createElement('textarea');
        el.value = copyStr;

        // Prevent keyboard from showing on mobile
        el.setAttribute('readonly', '');
        //el.style.contain = 'strict';
        el.style.position = 'absolute';
        el.style.left = '-9999px';
        el.style.fontSize = '12pt'; // Prevent zooming on iOS

        const selection = getSelection()!;
        let originalRange;
        if (selection.rangeCount > 0) {
            originalRange = selection.getRangeAt(0);
        }

        document.body.appendChild(el);
        el.select();

        // Explicit selection workaround for iOS
        el.selectionStart = 0;
        el.selectionEnd = copyStr.length;

        let success = false;
        try {
            success = document.execCommand('copy');
        } catch (err) { }

        document.body.removeChild(el);

        if (originalRange) {
            selection.removeAllRanges();
            selection.addRange(originalRange);
        }
    }

    /**限制名字 */
    export function limitName(str) {
        str = str.slice(0, 3) + "..." + str.slice(str.length - 2, str.length);
        return str;
    }
}

if (!window["vv"]) { window["vv"] = vv }
else { for (let i in vv) { window["vv"][i] = vv[i] } }
setTimeout(() => { for (let i in window["vv"]) vv[i] = window["vv"][i] }, 0)
