import { isValid } from "@visactor/vutils";

import { HierarchyState } from "../ts-types";

export const judgeType = value => {
    switch (Object.prototype.toString.call(value)) {
      case "[object Object]":
        return "object";

      case "[object Function]":
        return "function";

      case "[object Array]":
        return "array";

      case "[object String]":
        return "string";

      case "[object Number]":
        return "number";

      case "[object RegExp]":
        return "regExp";

      case "[object Boolean]":
        return "boolean";

      case "[object Symbol]":
        return "symbol";

      case "[object Date]":
        return "date";

      case "[object Undefined]":
        return "undefined";

      case "[object Null]":
        return "null";

      case "[object Error]":
        return "error";

      case "[object HTMLDocument]":
        return "document";

      case "[object global]":
        return "global";

      default:
        return null;
    }
};

export const isIt = (v, type) => judgeType(v) === type;

export const isObject = v => isIt(v, "object");

export const isFunction = v => isIt(v, "function");

export const isArray = v => isIt(v, "array");

export const isString = v => isIt(v, "string");

export const isNumber = v => isIt(v, "number");

export const isRegExp = v => isIt(v, "regExp");

export const isBoolean = v => isIt(v, "boolean");

export const isSymbol = v => isIt(v, "symbol");

export const isDate = v => isIt(v, "date");

export const isUndefined = v => isIt(v, "undefined");

export const isNull = v => isIt(v, "null");

export const isError = v => isIt(v, "error");

export const isDocument = v => isIt(v, "document");

export const isGlobal = v => isIt(v, "global");

export function merge(target, ...sources) {
    if (!sources.length) return target || {};
    const source = sources.shift();
    if (isObject(target) && isObject(source)) for (const key in source) isObject(source[key]) ? (target[key] || Object.assign(target, {
        [key]: {}
    }), isObject(target[key]) || Object.assign(target, {
        [key]: source[key]
    }), merge(target[key], source[key])) : Object.assign(target, {
        [key]: source[key]
    });
    return merge(target, ...sources);
}

export function ingoreNoneValueMerge(target, ...sources) {
    if (!sources.length) return target || {};
    const source = sources.shift();
    if (isObject(target) && isObject(source)) for (const key in source) isObject(source[key]) ? (target[key] || Object.assign(target, {
        [key]: {}
    }), isObject(target[key]) || Object.assign(target, {
        [key]: source[key]
    }), ingoreNoneValueMerge(target[key], source[key])) : null !== source[key] && void 0 !== source[key] && Object.assign(target, {
        [key]: source[key]
    });
    return ingoreNoneValueMerge(target, ...sources);
}

export function convertInternal(value) {
    return "function" == typeof value && (value = value()), isValid(value) ? `${value}` : "";
}

export function transpose(matrix) {
    if ((null == matrix ? void 0 : matrix.length) <= 0) return matrix;
    const m = matrix.length, n = matrix[0].length, transposed = new Array(n);
    for (let i = 0; i < m; i++) for (let j = 0; j < n; j++) transposed[j] || (transposed[j] = new Array(m)), 
    transposed[j][i] = matrix[i][j];
    return transposed;
}

export function debounce(fn, delay, immediate = !1) {
    let timer, result;
    return function(...args) {
        if (timer && clearTimeout(timer), immediate) {
            if (!timer) return result = fn.apply(this, args), result;
            timer = setTimeout((() => timer = 0), delay);
        } else timer = setTimeout((() => fn.apply(this, args)), delay);
    };
}

export function throttle(func, delay) {
    let timer = null;
    return function(...args) {
        timer || (func.apply(this, args), timer = setTimeout((() => {
            timer = null;
        }), delay));
    };
}

export function throttle2(func, delay) {
    let timer = null;
    return function(...args) {
        timer || (timer = setTimeout((() => {
            func.apply(this, args), timer = null;
        }), delay));
    };
}

function pad(num, totalChars) {
    for (num = `${num}`; num.length < totalChars; ) num = "0" + num;
    return num;
}

export function changeColor(color, ratio, isDarker) {
    color = (color = color.replace(/^\s*|\s*$/, "")).replace(/^#?([a-f0-9])([a-f0-9])([a-f0-9])$/i, "#$1$1$2$2$3$3");
    const difference = Math.round(256 * ratio) * (isDarker ? -1 : 1), rgb = color.match(new RegExp("^rgba?\\(\\s*(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])\\s*,\\s*(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])\\s*,\\s*(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])(?:\\s*,\\s*(0|1|0?\\.\\d+))?\\s*\\)$", "i")), alpha = rgb && isValid(rgb[4]) ? rgb[4] : null, decimal = rgb ? [ rgb[1], rgb[2], rgb[3] ] : color.replace(/^#?([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])/i, (function() {
        return `${parseInt(arguments[1], 16)},${parseInt(arguments[2], 16)},${parseInt(arguments[3], 16)}`;
    })).split(/,/);
    return rgb ? `rgb${null !== alpha ? "a" : ""}(${Math[isDarker ? "max" : "min"](parseInt(decimal[0], 10) + difference, isDarker ? 0 : 255)}, ${Math[isDarker ? "max" : "min"](parseInt(decimal[1], 10) + difference, isDarker ? 0 : 255)}, ${Math[isDarker ? "max" : "min"](parseInt(decimal[2], 10) + difference, isDarker ? 0 : 255)}${null !== alpha ? `, ${alpha}` : ""})` : [ "#", pad(Math[isDarker ? "max" : "min"](parseInt(decimal[0], 10) + difference, isDarker ? 0 : 255).toString(16), 2), pad(Math[isDarker ? "max" : "min"](parseInt(decimal[1], 10) + difference, isDarker ? 0 : 255).toString(16), 2), pad(Math[isDarker ? "max" : "min"](parseInt(decimal[2], 10) + difference, isDarker ? 0 : 255).toString(16), 2) ].join("");
}

export function toFixed(n, fixed = 0) {
    return parseFloat(n.toFixed(fixed));
}

export function validToString(v) {
    return isString(v) || isNumber(v) || isBoolean(v) ? v.toString() : "";
}

export function isMobile() {
    return navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
}

export function defaultOrderFn(v1, v2, order) {
    return "desc" !== order ? v1 === v2 ? 0 : v1 > v2 ? 1 : -1 : v1 === v2 ? 0 : v1 < v2 ? 1 : -1;
}

export function getValueByPath(obj, paths) {
    let prop, res = obj;
    for (;(prop = paths.shift()) && (res = res[prop], res); ) ;
    return res;
}

export function inBound({x: x, y: y}, {left: left, top: top, width: width, height: height}) {
    return x > left && x < left + width && y > top && y < top + height;
}

export const isArrEqual = (arr1, arr2) => arr1.length === arr2.length && arr1.every(((ele, index) => Object.is(ele, arr2[index])));

export function hashCode(input) {
    const I64BIT_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-".split("");
    let hash = 5381, i = input.length - 1;
    for (;i > -1; i--) hash += (hash << 5) + input.charCodeAt(i);
    let value = 2147483647 & hash, retValue = "";
    do {
        retValue += I64BIT_TABLE[63 & value];
    } while (value >>= 6);
    return retValue;
}

export function toBoolean(val) {
    if ("string" == typeof val) {
        if ("false" === val) return !1;
        if ("off" === val) return !1;
        if (/^0+$/.exec(val)) return !1;
    }
    return Boolean(val);
}

export function isAllDigits(str) {
    return /^-?\d+(\.\d+)?$/.test(str);
}

export function deduplication(array) {
    const result = [];
    for (let i = 0; i < array.length; i++) -1 === result.indexOf(array[i]) && result.push(array[i]);
    return result;
}

export function isDivSelected(div) {
    const selection = window.getSelection();
    if (selection.rangeCount) {
        const range = selection.getRangeAt(0);
        return range.endOffset > range.startOffset && div.contains(range.commonAncestorContainer);
    }
    return !1;
}

export function traverseObject(obj, childrenProperty, callback) {
    callback(obj), (null == obj ? void 0 : obj[childrenProperty]) && Array.isArray(null == obj ? void 0 : obj[childrenProperty]) && obj[childrenProperty].forEach((child => traverseObject(child, childrenProperty, callback)));
}

export function computeChildrenNodeLength(indexKey, hierarchyState, nodeData) {
    let size = 0;
    if (!hierarchyState || hierarchyState === HierarchyState.collapse || hierarchyState === HierarchyState.none) return size;
    const children = nodeData.filteredChildren ? nodeData.filteredChildren : nodeData.children;
    if (children) for (let i = 0; i < children.length; i++) {
        size += 1;
        size += computeChildrenNodeLength(Array.isArray(indexKey) ? indexKey.concat([ i ]) : [ indexKey, i ], children[i].hierarchyState, children[i]);
    }
    return size;
}
//# sourceMappingURL=util.js.map
