"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isEqual = isEqual;
exports.escapeHtml = escapeHtml;
exports.isUndefined = isUndefined;
exports.isObject = isObject;
exports.deepMerge = deepMerge;
exports.cloneDeep = cloneDeep;
exports.get = get;
const escapeHtmlMap = {
    '"': "&quot;",
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;"
};
const escapeHtmlRegex = /["&<>]/g;
function isEqual(a, b) {
    // Fast path: identical references or primitives
    if (a === b) {
        return true;
    }
    if (a == null || b == null) {
        return a === b;
    }
    const aType = typeof a;
    if (aType !== typeof b) {
        return false;
    }
    // Primitives already handled by ===
    if (aType !== "object") {
        return false;
    }
    // Arrays
    const aIsArray = Array.isArray(a);
    const bIsArray = Array.isArray(b);
    if (aIsArray !== bIsArray) {
        return false;
    }
    if (aIsArray) {
        const len = a.length;
        if (len !== b.length) {
            return false;
        }
        for (let i = 0; i < len; i++) {
            if (!isEqual(a[i], b[i])) {
                return false;
            }
        }
        return true;
    }
    // Objects
    const aKeys = Object.keys(a);
    const bKeys = Object.keys(b);
    if (aKeys.length !== bKeys.length) {
        return false;
    }
    for (let i = 0, len = aKeys.length; i < len; i++) {
        const key = aKeys[i];
        if (!Object.prototype.hasOwnProperty.call(b, key)) {
            return false;
        }
        if (!isEqual(a[key], b[key])) {
            return false;
        }
    }
    return true;
}
function escapeHtml(html) {
    return html.replace(escapeHtmlRegex, char => escapeHtmlMap[char]);
}
function isUndefined(val) {
    return val === undefined;
}
function isObject(val) {
    return val !== null && typeof val === "object" && !Array.isArray(val);
}
function deepMerge(...args) {
    const target = args[0] || {};
    const len = args.length;
    for (let i = 1; i < len; i++) {
        const arg = args[i];
        if (!arg) {
            continue;
        }
        if (Array.isArray(arg)) {
            for (let j = 0, jLen = arg.length; j < jLen; j++) {
                const val = arg[j];
                if (val === undefined) {
                    continue;
                }
                const src = target[j];
                if (Array.isArray(val)) {
                    target[j] = deepMerge(Array.isArray(src) ? src : [], val);
                }
                else if (isObject(val)) {
                    target[j] = deepMerge(isObject(src) ? src : {}, val);
                }
                else {
                    target[j] = val;
                }
            }
        }
        else {
            const keys = Object.keys(arg);
            for (let j = 0, jLen = keys.length; j < jLen; j++) {
                const key = keys[j];
                // Prevent prototype pollution
                if (key === "__proto__" || key === "constructor" || key === "prototype") {
                    continue;
                }
                const val = arg[key];
                if (val === undefined) {
                    continue;
                }
                const src = target[key];
                if (Array.isArray(val)) {
                    target[key] = deepMerge(Array.isArray(src) ? src : [], val);
                }
                else if (isObject(val)) {
                    target[key] = deepMerge(isObject(src) ? src : {}, val);
                }
                else {
                    target[key] = val;
                }
            }
        }
    }
    return target;
}
function cloneDeep(obj, preserveUndefined = true) {
    if (obj === null || typeof obj !== "object") {
        return obj;
    }
    if (obj instanceof Date) {
        return obj;
    }
    if (Array.isArray(obj)) {
        const len = obj.length;
        const clone = new Array(len);
        for (let i = 0; i < len; i++) {
            const value = obj[i];
            if (value !== undefined) {
                clone[i] = cloneDeep(value, preserveUndefined);
            }
            else if (preserveUndefined) {
                clone[i] = undefined;
            }
        }
        return clone;
    }
    const clone = {};
    const keys = Object.keys(obj);
    for (let i = 0, len = keys.length; i < len; i++) {
        const key = keys[i];
        const value = obj[key];
        if (value !== undefined) {
            clone[key] = cloneDeep(value, preserveUndefined);
        }
        else if (preserveUndefined) {
            clone[key] = undefined;
        }
    }
    return clone;
}
function get(obj, path, defaultValue) {
    const keys = path.split(".");
    let result = obj;
    for (let i = 0, len = keys.length; i < len; i++) {
        if (result == null) {
            return defaultValue;
        }
        result = result[keys[i]];
    }
    return result ?? defaultValue;
}
