import {Session} from "/@/utils/storage";

const fileUrl = import.meta.env.VITE_FILE_URL
const serverUrl = import.meta.env.VITE_API_URL
const previewUrl = import.meta.env.VITE_PREVIEW_URL

const u = {
    url: {
        file: fileUrl,
        server: serverUrl,
        preview: previewUrl
    },
    dialog: {
        actions: {
            'add': {title: '新增', btn: '创建'},
            'del': {title: '删除', btn: '确定'},
            'edit': {title: '修改', btn: '修改'},
            'view': {title: '详情', btn: '确定'},
        },
    },
    /**
     * 16进制颜色转rgb
     * @param hex
     */
    hexToRgb(hex: string) {
        // Remove the # character if it exists
        hex = hex.replace("#", "");

        // Convert the hex value to RGB values
        const r = parseInt(hex.substring(0, 2), 16);
        const g = parseInt(hex.substring(2, 4), 16);
        const b = parseInt(hex.substring(4, 6), 16);

        // Return the RGB values as an object
        return {r, g, b};
    },
    distinctByKey(elements: Array<any>, key: string) {
        let result:any[] = [];
        let keys:Array<string> = [];
        if (!elements || elements.length === 0) {
            return result;
        }
        for (let i = 0; i < elements.length; i++) {
            if (!elements[i][key] && elements[i][key] !== 0) {
                continue;
            }
            let k = elements[i][key].toString();
            if(!keys.includes(k)){
                result.push(elements[i]);
                keys.push(k);
            }
        }
        return result;
    },
    groupByKey(elements: Array<any>, key: string) {
        let map = {};
        if (!elements || elements.length === 0) {
            return map;
        }
        for (let i = 0; i < elements.length; i++) {
            if (!elements[i][key] && elements[i][key] !== 0) {
                continue;
            }
            let k = elements[i][key].toString();
            let tmp = map[k] || [];
            tmp.push(elements[i]);
            map[k] = tmp;
        }
        return map;
    },
    groupByKeyV2(elements: Array<any>, key: string) {
        return elements.reduce((groups, item) => {
            const group = item[key];
            if (!groups[group]) {
                groups[group] = [];
            }
            groups[group].push(item);
            return groups;
        }, {});
    },
    sortByArray(elements: Array<any>, key: string, sortArray: Array<any>) {
        if (key) {
            elements.sort(function (a, b) {
                return sortArray.indexOf(a[key]) - sortArray.indexOf(b[key]);
            });
        } else {
            elements.sort(function (a, b) {
                return sortArray.indexOf(a) - sortArray.indexOf(b);
            });
        }
    },
    sort(elements: Array<any>, key: string) {
        elements.sort((o1, o2) => {
            let value1 = o1[key];
            let value2 = o2[key];
            if (value2 > value1) {
                return -1;
            } else if (value2 < value1) {
                return 1;
            } else {
                return 0;
            }
        })
    },
    toMap(elements: Array<any>, fn: Function) {
        let ret = {};
        elements.forEach(item => {
            let key = fn.apply(null, [item]);
            ret[key] = item;
        })
        return ret;
    },
    /**
     * 浅拷贝或者一层属性的对象深拷贝
     * @param obj
     * @returns {*}
     */
    copyObject(obj: Object) {
        return Object.assign({}, obj);
    },
    /**
     * 深拷贝 支持regExp、function、null、undefined
     * @param target
     * @returns {function(*=): {}}
     */
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    copyDeep(target: any) {
        // @ts-ignore
        return function deepClone(target: any) {
            // 定义一个变量
            let result;
            // 如果当前需要深拷贝的是一个对象的话
            if (typeof target === 'object') {
                // 如果是一个数组的话
                if (Array.isArray(target)) {
                    result = []; // 将result赋值为一个数组，并且执行遍历
                    for (let i in target) {
                        // 递归克隆数组中的每一项
                        result.push(deepClone(target[i]))
                    }
                    // 判断如果当前的值是null的话；直接赋值为null
                } else if (target === null) {
                    result = null;
                    // 判断如果当前的值是一个RegExp对象的话，直接赋值
                } else if (target.constructor === RegExp) {
                    result = target;
                } else {
                    // 否则是普通对象，直接for in循环，递归赋值对象的所有值
                    result = {};
                    for (let i in target) {
                        result[i] = deepClone(target[i]);
                    }
                }
                // 如果不是对象的话，就是基本数据类型，那么直接赋值
            } else {
                result = target;
            }
            // 返回最终结果
            return result;
        }
    },
    /**
     * 加强parse 支持function解析
     * @param script
     * @returns {any}
     */
    parseDeep(script: string) {
        return JSON.parse(script, function (key, value) {
            if (null != value && value.indexOf("function") === 0) {
                return eval("(function(){return " + value + "})()");
            }
            return value;
        });
    },

    isEmptyOrNull: function (exp: any) {
        return !exp || typeof (exp) == "undefined" || "undefined" === exp || exp.length === 0 || exp === '' ;
    },
    pad: function (val: any, len: number, ch: string = '0') {
        return val.toString().padStart(len, ch);
    },
    mediaType: function (url: string) {
        let type = "other";
        url = url.toLowerCase();
        if (url.endsWith(".jpg") || url.endsWith(".jpeg") || url.endsWith(".png")
            || url.endsWith(".gif") || url.endsWith(".svg")) {
            type = "image";
        }
        if (url.endsWith(".mp4") || url.endsWith(".avi") || url.endsWith(".webm")
            || url.endsWith(".ogg")) {
            type = "video";
        }
        if (url.endsWith(".mp3") || url.endsWith(".amr") || url.endsWith(".wav")) {
            type = "audio";
        }

        if ("url".endsWith(".pdf") || "url".endsWith(".doc") || "url".endsWith(".docx")
            || "url".endsWith(".xls") || "url".endsWith(".xlsx") || "url".endsWith(".ppt")) {
            type = "wps";
        }
        return type;
    },
    contains(array: Array<any>, value: any, key = null) {
        if (!u.isEmptyOrNull(array)) {
            for (let i = 0; i < array.length; i++) {
                if (!key) {
                    if (array[i] == value) {
                        return true;
                    }
                } else {
                    if (value.constructor != Object && array[i][key] == value) {
                        return true;
                    } else if (value.constructor == Object && array[i][key] == value[key]) {
                        return true;
                    }
                }
            }
        }
        return false;
    },
    removeItem(array: Array<any>, value: any, key = null) {
        if (!u.isEmptyOrNull(array)) {
            for (let i = 0; i < array.length; i++) {
                if (!key) {
                    if (array[i] == value) {
                        array.splice(i, 1);
                        break;
                    }
                } else {
                    if (value.constructor != Object && array[i][key] == value) {
                        array.splice(i, 1);
                        break;
                    } else if (value.constructor == Object && array[i][key] == value[key]) {
                        array.splice(i, 1);
                        break;
                    }
                }
            }
        }
    },
    randomChars(length: number, uuid = false) {
        let cs = "0123456789abcdef0123456789abcdef";
        let chars = "";
        for (let i = 0; i < length; i++) {
            chars += cs[Math.floor(Math.random() * cs.length)];
            if (uuid && (i === 7 || i === 11 || i === 15 || i === 19)) {
                chars += "-";
            }
        }
        return chars.toLowerCase();
    },
    randomKey(length: number, uuid = false) {
        let cs = "0123456789abcdef012345678ABCDEFGHIJKLMNRSTZZYAL29123";
        let chars = "";
        for (let i = 0; i < length; i++) {
            chars += cs[Math.floor(Math.random() * cs.length)];
            if (uuid && (i === 7 || i === 11 || i === 15 || i === 19)) {
                chars += "-";
            }
        }
        return chars;
    },
    getOsName() {
        let u = navigator.userAgent;
        if (!!u.match(/compatible/i) || u.match(/Windows/i)) {
            return 'windows';
        } else if (!!u.match(/Macintosh/i) || u.match(/MacIntel/i)) {
            return 'macOS';
        } else if (!!u.match(/iphone/i) || u.match(/Ipad/i)) {
            return 'ios';
        } else if (u.match(/android/i)) {
            return 'android';
        } else {
            return 'other';
        }
    },
    getBrowerName() {
        let u = navigator.userAgent;

        let bws = [{
            name: 'sgssapp',
            it: /sogousearch/i.test(u)
        }, {
            name: 'wechat',
            it: /MicroMessenger/i.test(u)
        }, {
            name: 'weibo',
            it: !!u.match(/Weibo/i)
        }, {
            name: 'uc',
            it: !!u.match(/UCBrowser/i) || u.indexOf(' UBrowser') > -1
        }, {
            name: 'sogou',
            it: u.indexOf('MetaSr') > -1 || u.indexOf('Sogou') > -1
        }, {
            name: 'xiaomi',
            it: u.indexOf('MiuiBrowser') > -1
        }, {
            name: 'baidu',
            it: u.indexOf('Baidu') > -1 || u.indexOf('BIDUBrowser') > -1
        }, {
            name: '360',
            it: u.indexOf('360EE') > -1 || u.indexOf('360SE') > -1
        }, {
            name: '2345',
            it: u.indexOf('2345Explorer') > -1
        }, {
            name: 'edge',
            it: u.indexOf('Edge') > -1
        }, {
            name: 'ie11',
            it: u.indexOf('Trident') > -1 && u.indexOf('rv:11.0') > -1
        }, {
            name: 'ie',
            it: u.indexOf('compatible') > -1 && u.indexOf('MSIE') > -1
        }, {
            name: 'firefox',
            it: u.indexOf('Firefox') > -1
        }, {
            name: 'safari',
            it: u.indexOf('Safari') > -1 && u.indexOf('Chrome') === -1
        }, {
            name: 'qqbrowser',
            it: u.indexOf('MQQBrowser') > -1 && u.indexOf(' QQ') === -1
        }, {
            name: 'qq',
            it: u.indexOf('QQ') > -1
        }, {
            name: 'chrome',
            it: u.indexOf('Chrome') > -1 || u.indexOf('CriOS') > -1
        }, {
            name: 'opera',
            it: u.indexOf('Opera') > -1 || u.indexOf('OPR') > -1
        }];

        for (let i = 0; i < bws.length; i++) {
            if (bws[i].it) {
                return bws[i].name;
            }
        }
        return 'other';
    },
    date: {
        /**
         * @description 获取需要的时间格式
         * @param {Date} time 时间、时间字符串、时间戳
         * @param {String} format 时间格式，默认'YYYY-MM-DD'。如果是'星期WW'，则返回（如：'星期日'）
         * @return {String} 格式化后的时间
         */
        format: function (time: any, format: string) {
            time = time ? new Date(time) : new Date()
            format = format || 'YYYY-MM-DD'

            function tf(i: any) {
                return (i < 10 ? '0' : '') + i
            }

            // @ts-ignore
            return format.replace(/YYYY|MM|DD|hh|mm|ss|WW/g, function (a: string) {
                switch (a) {
                    case 'YYYY':
                        return tf(time.getFullYear())
                    case 'MM':
                        return tf(time.getMonth() + 1)
                    case 'DD':
                        return tf(time.getDate())
                    case 'mm':
                        return tf(time.getMinutes())
                    case 'hh':
                        return tf(time.getHours())
                    case 'ss':
                        return tf(time.getSeconds())
                    case 'WW':
                        return ['日', '一', '二', '三', '四', '五', '六'][time.getDay()]
                }
            })
        },
        diff(start: Date, end: Date) {
            let d0 = this.begin(new Date(start));
            let d1 = this.begin(new Date(end));
            return (d1.getTime() - d0.getTime()) / (24 * 3600 * 1000)
        },
        delta(time: any = null, delta = 0, type = 'day') {
            let t = time || new Date();
            let year = t.getFullYear(), month = t.getMonth(), day = t.getDate(),
                hour = t.getHours(), minute = t.getMinutes(), second = t.getSeconds();

            let nextMonth = 0, mod = 0;
            switch (type) {
                case "day":
                    t = new Date(t.getTime() + (delta * 24 * 3600 * 1000))
                    break;
                case "week":
                    t = new Date(t.getTime() + (delta * 7 * 24 * 3600 * 1000))
                    break;
                case "month":
                    nextMonth = month + delta;
                    mod = Math.abs(delta) % 12;
                    if (delta < 0) {
                        if (nextMonth < 0) {
                            nextMonth = nextMonth + ((mod + 1) * 12);
                            year = year - (mod + 1);
                        }
                    } else if (delta > 0) {
                        nextMonth = nextMonth - ((mod + 1) * 12);
                        year = year + (mod + 1);
                    }
                    t = new Date(year, nextMonth, day, hour, minute, second);
                    break;
                case "quarter":
                    nextMonth = month + (delta * 3);
                    mod = Math.abs(delta * 3) % 12;
                    if (delta < 0) {
                        if (nextMonth < 0) {
                            nextMonth = nextMonth + ((mod + 1) * 12);
                            year = year - (mod + 1);
                        }
                    } else if (delta > 0) {
                        nextMonth = nextMonth - ((mod + 1) * 12);
                        year = year + (mod + 1);
                    }
                    t = new Date(year, nextMonth, day, hour, minute, second);
                    break;
                case "year":
                    t = new Date(year + delta, month, day, hour, minute, second);
                    break;
            }
            return t;
        },
        begin(time: any = null, type = 'day') {
            let t = time || new Date();
            let year = t.getFullYear(), month = t.getMonth(), day = t.getDate()
            switch (type) {
                case "day":
                    t = new Date(year, month, day);
                    break;
                case "week":
                    let date = t.getDay();
                    t = new Date(new Date(year, month, day).getTime() - (date * 24 * 3600 * 1000));
                    break;
                case "month":
                    t = new Date(year, month, 1);
                    break;
                case "quarter":
                    let nextMonth = 0;
                    if (month >= 3 && month <= 5) {
                        nextMonth = 3;
                    }
                    if (month >= 6 && month <= 8) {
                        nextMonth = 6;
                    }
                    if (month >= 9 && month <= 11) {
                        nextMonth = 9;
                    }
                    t = new Date(year, nextMonth, 1);
                    break;
                case "year":
                    t = new Date(year, 0, 1);
                    break;
            }
            return t;
        },
        end(time: Date, type = 'day') {
            let t: Date = time || new Date();
            let year = t.getFullYear(), month = t.getMonth(), day = t.getDate()
            switch (type) {
                case "day":
                    t = new Date(year, month, day, 23, 59, 59, 999);
                    break;
                case "week":
                    let date = t.getDay();
                    t = new Date(new Date(year, month, day).getTime() + ((7 - date) * 24 * 3600 * 1000) - 1);
                    break;
                case "month":
                    let _d = this.delta(t, 1, 'month');
                    _d = this.begin(_d, 'month');
                    t = new Date(new Date(_d.getFullYear(), _d.getMonth(), _d.getDate()).getTime() - 1);
                    break;
                case "quarter":
                    let __d = this.delta(t, 1, 'quarter');
                    __d = this.begin(__d, 'quarter');
                    t = new Date(new Date(__d.getFullYear(), __d.getMonth(), __d.getDate()).getTime() - 1);
                    break;
                case "year":
                    t = new Date(year, 11, 13, 23, 59, 59, 999);
                    break;
            }
            return t;
        }
    },
    validator: {
        required: {required: true, message: "必填项", trigger: 'blur'},
        requiredEnum: {type: 'number', min: 1, message: "必选项", trigger: 'blur'}, //字典类的校验规则
        verifyCode: {required: true, message: "请输入验证码", trigger: 'blur'},
        rangeDate: {type: 'array', length: 2, required: true, message: "必选项"},
        lengthMax2: {type: 'string', max: 2, message: "最多2个字"},
        lengthMax6: {type: 'string', max: 6, message: "长度最大6个字"},
        lengthMax10: {type: 'string', max: 10, message: "长度最大6个字"},
        lengthMax50: {type: 'string', max: 50, message: "长度最大50个字"},
        length: {type: 'string', min: 4, max: 50, message: "长度为4-50个字"},
        length32: {type: 'string', min: 1, max: 32, message: "不能超过32个字"},
        length64: {type: 'string', min: 1, max: 64, message: "不能超过64个字"},
        length128: {type: 'string', min: 1, max: 128, message: "不能超过128个字"},
        length256: {type: 'string', min: 1, max: 256, message: "不能超过256个字"},
        lengthShort: {min: 2, max: 20, message: "长度为4-20个字"},
        lengthName: {type: 'string', min: 2, max: 10, message: "长度为2-10个字"},
        positiveInt: {type: 'number', min: 1, message: "必须为正整数"},
        negativeInt: {type: 'number', max: -1, message: "必须为负数"},
        mobile: {type: 'string', length: 11, max: 11, pattern: '^[1][3,4,5,7,8][0-9]{9}$', message: "11位数字手机号格式错误"},
        email: {type: 'email', min: 6, pattern: '^(\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$', message: "邮箱格式错误"},
        password: {min: 8, message: "请输入8位密码", trigger: 'blur'},
        // password: {type: 'string', min: 6, max: 12, pattern: '(\\w){6,12}', message: '格式为6-12位数字字母组合'},
        idNo: {type: 'string', pattern: '(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X)$)', message: '身份证号码格式错误'},
        chinese: {type: 'string', pattern: '^[\\u4e00-\\u9fa5]{0,}$', message: '请输入中文字符'},
        num: {type: 'string', pattern: /^\d*$/, message: "只能输入数字"},
        letter: {type: 'string', pattern: /^[A-Za-z0-9\-]$/, message: "只能输入字母和数字"},
        tel: {type: 'string', pattern: /^[-\d]*$/, message: "电话只能包含数字和-"},
        url: {
            type: 'string',
            pattern: /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/,
            message: "链接地址错误"
        },
    },
    fmt: {
        fmtMoney: function (money: number) {
            if (!money) {
                return "0.00";
            }
            return (money / 100).toFixed(2);
        },
        fmtUrl: function (v: string) {
            let token = Session.get('accessToken')
            if (!v) {
                return '';
            }
            if (v.indexOf("http") === 0) {
                return v;
            }
            //console.log(v, fileUrl)
            // return fileUrl + v;
            return `${fileUrl}${v}`
        },
        fmtImg(v: string) {
            let token = Session.get('accessToken')
            if (u.isEmptyOrNull(v)) {
                return "./image/placeholder.png";
            }
            if (v.indexOf("http") === 0) {
                return v;
            }
            return `${fileUrl}${v}`
        },
        fmtPreview(v: string) {
            let token = Session.get('accessToken')
            if (u.isEmptyOrNull(v)) {
                return "./image/placeholder.png";
            }
            if (v.indexOf("http") === 0) {
                return v;
            }
            return `${previewUrl}${v}?X-Token=${btoa(token)}`
            // return `${previewUrl}${v}`
        },
        /**
         * byte 单位转换
         * @param size
         */
        fmtSize(size: number = 0) {
            if (size < 1024) {
                return size + 'B';
            }
            size = size / 1024;
            if (size > 1024) {
                size = size / 1024;
                if (size > 1024) {
                    size = size / 1024;
                    return size.toFixed(2) + 'GB'
                } else {
                    return size.toFixed(2) + 'MB'
                }
            } else {
                return size.toFixed(2) + 'KB'
            }
        },
        fmtDateTime(t: any) {
            if (!t) {
                return "-";
            }
            let date = new Date(t);
            let year = date.getFullYear();
            let month = date.getMonth() + 1;
            let day = date.getDate();
            let hour = date.getHours();
            let minute = date.getMinutes();
            let second = date.getSeconds();
            return [year, month, day].map(n => {
                return u.pad(n, 2)
            }).join('-') + ' ' + [hour, minute, second].map(n => {
                return u.pad(n, 2)
            }).join(':')
        },
        fmtDate(t: any) {
            if (!t) {
                return "-";
            }
            let date = new Date(t);
            let year = date.getFullYear();
            let month = date.getMonth() + 1;
            let day = date.getDate();
            return [year, month, day].map(n => {
                return u.pad(n, 2)
            }).join('-');
        },
        fmtMonth(t: any) {
            if (t == null) {
                return "-";
            }
            let date = new Date(t);
            let year = date.getFullYear();
            let month = date.getMonth() + 1;
            return [year, month].map(n => {
                return u.pad(n, 2)
            }).join('-');
        },
        fmtTime(t: any) {
            if (t == null) {
                return "-";
            }
            let date = new Date(t);
            let hour = date.getHours();
            let minute = date.getMinutes();
            return [hour, minute].map(n => {
                return u.pad(n, 2)
            }).join(':')
        },
        fmtDuration(ms:number){
            let seconds = Math.floor(ms / 1000);
            let minutes = Math.floor(seconds / 60);
            let hours = Math.floor(minutes / 60);
            let days = Math.floor(hours / 24);

            hours %= 24;
            minutes %= 60;
            seconds %= 60;

            // 构建时长字符串
            let durationStr = '';
            if (days > 0) {
                durationStr += `${days}天`;
            }
            if (hours > 0) {
                durationStr += `${hours}时`;
            }
            if (minutes > 0) {
                durationStr += `${minutes}分`;
            }
            if (seconds > 0 || !durationStr) { // 如果没有小时和分钟，至少显示秒
                durationStr += `${seconds}秒`;
            }

            return durationStr.trim(); // 去除可能的前后空格
        },
        fmtServerUrl(v: any) {
            if (!v) {
                return null;
            }
            if (v.indexOf("http") === 0) {
                return v;
            }
            return serverUrl + v.replace(/\\/g, "/");
        },
        fmtSensitive(v: any, start: number, length: number) {
            if (!v) {
                return "";
            }
            let ret = [];
            ret.push(v.substring(0, start));
            for (let i = 0; i < length; i++) {
                ret.push("*");
            }
            ret.push(v.substring(start + length, v.length));
            return ret.join("");
        },
        fmtUrlParam(key: string) {
            let reg = new RegExp("(^|&)" + key + "=([^&]*)(&|$)", "i");
            let r = window.location.search.substr(1).match(reg);
            if (r != null) {
                return decodeURI(r[2]);
            } else {
                return null;
            }
        },
        fmtDict(v: any, type: string) {
            if (v == null) {
                return "";
            }

            const dicts = Session.get("dicts");
            if (u.isEmptyOrNull(dicts) || u.isEmptyOrNull(dicts[type])) {
                return '--'
            }
            let dict = dicts[type].find(k =>  k.value == v);
            if (u.isEmptyOrNull(dict)) {
                return "--";
            }
            return dict.name;
        },
        fmtDictColor(v: any, type: string) {
            if (v == null) {
                return "";
            }

            const dicts = Session.get("dicts");
            if (u.isEmptyOrNull(dicts) || u.isEmptyOrNull(dicts[type])) {
                return '';
            }
            let dict = dicts[type].find(k =>  k.value == v);
            if (u.isEmptyOrNull(dict)) {
                return "";
            }
            return dict.color || "";
        },
    }
}


export default u;
