/**
 * 基本的函数
 * Created by GUY on 2015/6/24.
 */
import { every, isKey, isArray, toUpperCase, each, stripEL, isNotNull, isNull, isObject } from "../2.base";
import { makeFirstPY } from "../utils/chinesePY";

/**
 * 创建唯一的名字
 * @param array
 * @param name
 * @returns {*}
 */
export function createDistinctName(array, name) {
    let src = name, idx = 1;
    name = name || "";
    while (true) {
        if (every(array, (i, item) => isKey(item) ? item !== name : item.name !== name)) {
            break;
        }
        name = src + (idx++);
    }

    return name;
}

/**
 * 获取字符宽度
 * @param str
 * @return {number}
 */
export function getGBWidth(str) {
    str = `${str}`;
    str = str.replace(/[^\x00-\xff]/g, "xx");

    return Math.ceil(str.length / 2);
}

/**
 * 获取搜索结果
 * @param items
 * @param keyword
 * @param param  搜索哪个属性
 */
export function getSearchResult(items, keyword, param) {
    const array = isArray(items);
    items = array ? BI.flatten(items) : items;
    param || (param = "text");
    if (!isKey(keyword)) {
        return {
            find: items,
            match: array ? [] : {},
        };
    }
    let t, text, py;
    keyword = toUpperCase(keyword);
    const matched = array ? [] : {}, find = array ? [] : {};
    each(items, (i, item) => {
        // 兼容item为null的处理
        if (isNull(item)) {
            return;
        }
        t = stripEL(item);
        text = [t[param], t.text, t.value, t.name, t].find(isNotNull);

        if (isNull(text) || isObject(text)) return;

        py = makeFirstPY(text, {
            splitChar: "\u200b",
        });
        text = toUpperCase(text);
        py = toUpperCase(py);
        let pidx;
        if (text.indexOf(keyword) > -1) {
            if (text === keyword) {
                array ? matched.push(item) : (matched[i] = item);
            } else {
                array ? find.push(item) : (find[i] = item);
            }
        } else { // BI-56386 这边两个pid / text.length是为了防止截取的首字符串不是完整的,但光这样做还不够,即时错位了,也不能说明就不符合条件
            pidx = py.indexOf(keyword);
            if (pidx > -1) {
                if (text === keyword || keyword.length === text.length) {
                    array ? matched.push(item) : (matched[i] = item);
                } else {
                    array ? find.push(item) : (find[i] = item);
                }
            }
        }
    });

    return {
        match: matched,
        find,
    };
}

/**
 * 获取按GB2312排序的结果
 * @param items
 * @param key
 * @return {any[]}
 */
export function getSortedResult(items, key = null) {
    const getTextOfItem = BI.isFunction(key) ? key :
        function (item, key) {
            if (BI.isNotNull(key)) {
                return item[key];
            }
            if (BI.isNotNull(item.text)) {
                return item.text;
            }
            if (BI.isNotNull(item.value)) {
                return item.value;
            }

            return item;
        };

    return items.sort((item1, item2) => {
        const str1 = getTextOfItem(item1, key);
        const str2 = getTextOfItem(item2, key);
        if (BI.isNull(str1) && BI.isNull(str2)) {
            return 0;
        }
        if (BI.isNull(str1)) {
            return -1;
        }
        if (BI.isNull(str2)) {
            return 1;
        }
        if (str1 === str2) {
            return 0;
        }
        const len1 = str1.length, len2 = str2.length;
        for (let i = 0; i < len1 && i < len2; i++) {
            const char1 = str1[i];
            const char2 = str2[i];
            if (char1 !== char2) {
                // 找不到的字符都往后面放
                return (BI.isNull(BI.CODE_INDEX[char1]) ? BI.MAX : BI.CODE_INDEX[char1]) - (BI.isNull(BI.CODE_INDEX[char2]) ? BI.MAX : BI.CODE_INDEX[char2]);
            }
        }

        return len1 - len2;
    });
}

export function beforeFunc(sFunc, func) {
    const __self = sFunc;

    return function () {
        if (func.apply(sFunc, arguments) === false) {
            return false;
        }

        return __self.apply(sFunc, arguments);
    };
}

export function afterFunc(sFunc, func) {
    const __self = sFunc;

    return function () {
        const ret = __self.apply(sFunc, arguments);
        if (ret === false) {
            return false;
        }
        func.apply(sFunc, arguments);

        return ret;
    };
}


export const Func = {
    createDistinctName,
    getGBWidth,
    getSearchResult,
    getSortedResult,
};