"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getConstant = exports.convertObjectPointers = exports.streamToBuffer = exports.normalizeString = exports.capitalizeWords = exports.capitalize = exports.humanize = exports.abbr = exports.castToString = exports.weakString = exports.strEquals = exports.strContains = exports.anyContains = exports.anyEquals = exports.cloneWithoutIdsCollision = exports.cloneWithNewIds = exports.sortBy = exports.groupBy = exports.deepClone = exports.checkType = exports.getType = exports.shortId = void 0;
const diacritics_1 = __importDefault(require("diacritics"));
const jsonpointer_1 = __importDefault(require("jsonpointer"));
const uuid_1 = require("uuid");
const exception_js_1 = require("../../exception.js");
const assert_js_1 = require("./assert.js");
function shortId() {
    return Math.random().toString(36).substring(2).padEnd(8, '0').substring(0, 8);
}
exports.shortId = shortId;
function getType(data) {
    return data == null ? 'null' : Array.isArray(data) ? 'array' : data instanceof Buffer ? 'buffer' : typeof data;
}
exports.getType = getType;
function checkType(data, expectedType, variableName = 'Value') {
    const types = Array.isArray(expectedType) ? expectedType : [expectedType];
    const actualType = getType(data);
    if (!types.includes(actualType)) {
        const expectedTypes = types.join(' or ');
        const message = `${variableName} should be ${expectedTypes}, instead got ${actualType}`;
        throw new exception_js_1.ScriptException({
            name: 'ValueTypeError',
            message,
            retry: true,
        });
    }
}
exports.checkType = checkType;
function deepClone(data) {
    return data == null ? null : JSON.parse(JSON.stringify(data));
}
exports.deepClone = deepClone;
function groupBy(items, fn) {
    const map = new Map();
    for (const [i, item] of items.entries()) {
        const key = fn(item, i);
        const list = map.get(key);
        if (list) {
            list.push(item);
        }
        else {
            map.set(key, [item]);
        }
    }
    return [...map.entries()];
}
exports.groupBy = groupBy;
function sortBy(items, fn) {
    return items.slice().sort((a, b) => fn(a) > fn(b) ? 1 : -1);
}
exports.sortBy = sortBy;
function cloneWithNewIds(obj) {
    const idsMap = new Map();
    const str = JSON.stringify(obj, (key, value) => {
        if (key === 'id') {
            const newId = (0, uuid_1.v4)();
            idsMap.set(value, newId);
            return newId;
        }
        return value;
    });
    return JSON.parse(str, (key, value) => {
        if (idsMap.has(value)) {
            return idsMap.get(value);
        }
        return value;
    });
}
exports.cloneWithNewIds = cloneWithNewIds;
function cloneWithoutIdsCollision(obj, existingIds) {
    const idsMap = new Map();
    const str = JSON.stringify(obj, (key, value) => {
        if (key === 'id' && existingIds.has(value)) {
            const newId = (0, uuid_1.v4)();
            idsMap.set(value, newId);
            return newId;
        }
        return value;
    });
    return JSON.parse(str, (key, value) => {
        if (idsMap.has(value)) {
            return idsMap.get(value);
        }
        return value;
    });
}
exports.cloneWithoutIdsCollision = cloneWithoutIdsCollision;
function anyEquals(a, b, options = {}) {
    const aType = getType(a);
    const bType = getType(b);
    switch (aType) {
        case 'object':
            return (bType === 'object' &&
                Object.keys(a).length === Object.keys(b).length &&
                Object.keys(a).every(k => anyEquals(a[k], b[k], options)));
        case 'array':
            return (bType === 'array' &&
                a.length === b.length &&
                a.every((ca, i) => anyEquals(ca, b[i], options)));
        default:
            return strEquals(a, b, options);
    }
}
exports.anyEquals = anyEquals;
function anyContains(a, b, options = {}) {
    const aType = getType(a);
    const bType = getType(b);
    switch (aType) {
        case 'object':
            return bType === 'object' && Object.keys(b).every(k => anyEquals(a[k], b[k], options));
        case 'array':
            return bType === 'array' && b.every((cb) => a.some((ca) => anyEquals(ca, cb, options)));
        default:
            return strContains(a, b, options);
    }
}
exports.anyContains = anyContains;
function strContains(actual, pattern, options = {}) {
    if (typeof pattern.test === 'function') {
        return pattern.test(actual);
    }
    return weakString(actual, options).includes(weakString(pattern, options));
}
exports.strContains = strContains;
function strEquals(a, b, options = {}) {
    return weakString(a, options) === weakString(b, options);
}
exports.strEquals = strEquals;
function weakString(str, options = {}) {
    const { removeDiacritics = true, collapseWhitespace = true, onlyAlphaNumeric = false, caseSensitive = false, } = options;
    let val = castToString(str).trim();
    if (!caseSensitive) {
        val = val.toLowerCase();
    }
    if (collapseWhitespace) {
        val = val.replace(/\s+/g, ' ');
    }
    if (removeDiacritics) {
        val = diacritics_1.default.remove(val);
    }
    if (onlyAlphaNumeric) {
        val = val.replace(/[^a-z0-9]/gi, '');
    }
    return val;
}
exports.weakString = weakString;
function castToString(str) {
    if (str == null) {
        return 'null';
    }
    if (['string', 'number', 'boolean'].includes(typeof str)) {
        return String(str);
    }
    return JSON.stringify(str);
}
exports.castToString = castToString;
function abbr(value) {
    const str = String(value || '');
    return str.length > 30 ? str.substring(0, 27) + '...' : str;
}
exports.abbr = abbr;
function humanize(str) {
    const s = str.replace(/[$_/-]/g, ' ').replace(/([A-Z])/g, ' $1');
    return capitalizeWords(s);
}
exports.humanize = humanize;
function capitalize(str) {
    return str.substring(0, 1).toUpperCase() + str.substring(1);
}
exports.capitalize = capitalize;
function capitalizeWords(str) {
    return str
        .replace(/\s+/, ' ')
        .toLowerCase()
        .replace(/( |^)([a-z])/g, (_, ws, char) => {
        return ws + char.toUpperCase();
    });
}
exports.capitalizeWords = capitalizeWords;
function normalizeString(str) {
    if (str == null) {
        return '';
    }
    return String(str)
        .replace(/\s+/g, ' ')
        .trim();
}
exports.normalizeString = normalizeString;
function streamToBuffer(readable) {
    return new Promise((resolve, reject) => {
        const buffers = [];
        readable.on('data', (chunk) => {
            buffers.push(Buffer.from(chunk));
        });
        readable.on('end', () => {
            const buffer = Buffer.concat(buffers);
            resolve(buffer);
        });
        readable.on('error', (err) => reject(err));
        readable.resume();
    });
}
exports.streamToBuffer = streamToBuffer;
function convertObjectPointers(object) {
    const newObj = {};
    for (const [key, value] of Object.entries(object)) {
        if (key[0] === '/') {
            jsonpointer_1.default.set(newObj, key, value);
        }
        else {
            newObj[key] = value;
        }
    }
    return newObj;
}
exports.convertObjectPointers = convertObjectPointers;
function getConstant(dataType, value) {
    switch (dataType) {
        case 'string':
            return value;
        case 'boolean':
            (0, assert_js_1.assertScript)(['true', 'false'].includes(value), 'Value should be either "true" or "false"');
            return value === 'true';
        case 'number': {
            const num = parseInt(value, 10);
            (0, assert_js_1.assertScript)(!isNaN(num), 'Value is not a number');
            return num;
        }
        default:
            (0, assert_js_1.assertScript)(false, `Unknown data type: ${dataType}`);
            break;
    }
}
exports.getConstant = getConstant;
//# sourceMappingURL=data.js.map