"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArrayExtensions = exports.sortArrayWithOrder = exports.reorderArray = exports.SumArray = exports.createCommaSeparatedString = exports.groupArrayBy = exports.sortCellValueArrayDates = exports.sortCellValueArrayNumeric = exports.sortCellValueArray = exports.sortArray = exports.sortArrayWithProperty = exports.areArraysEqualWithOrderandProperties = exports.areArraysEqualWithOrder = exports.areArraysNotEqual = exports.areArraysEqual = exports.moveArray = exports.hasItemsOfCount = exports.hasOneItem = exports.getOccurrence = exports.HasSingleEmptyValue = exports.IsNotNullOrEmptyNorContainsSingleEmptyValue = exports.IsNullOrEmptyOrContainsSingleEmptyValue = exports.IsNotNullOrEmpty = exports.IsNullOrEmpty = exports.IsNotEmpty = exports.IsEmpty = exports.IsNotNull = exports.IsNull = exports.RetrieveDistinct = exports.NotContainsItem = exports.ContainsAnyItem = exports.ContainsItem = exports.AddItem = exports.NotCorrectLength = exports.CorrectLength = exports.GetLength = void 0;
const Enums_1 = require("../../AdaptableState/Common/Enums");
function GetLength(arrayToCheck) {
    return IsNotNull(arrayToCheck) ? arrayToCheck.length : 0;
}
exports.GetLength = GetLength;
function CorrectLength(arrayToCheck, requiredLength) {
    return GetLength(arrayToCheck) == requiredLength;
}
exports.CorrectLength = CorrectLength;
function NotCorrectLength(arrayToCheck, requiredLength) {
    return !CorrectLength(arrayToCheck, requiredLength);
}
exports.NotCorrectLength = NotCorrectLength;
function AddItem(array, itemToAdd) {
    if (NotContainsItem(array, itemToAdd)) {
        array.push(itemToAdd);
    }
}
exports.AddItem = AddItem;
function ContainsItem(array, itemToCheck) {
    if (array == null) {
        return false;
    }
    return array.indexOf(itemToCheck) > -1;
}
exports.ContainsItem = ContainsItem;
function ContainsAnyItem(array, itemsToCheck) {
    if (array == null) {
        return false;
    }
    let foundItem = false;
    itemsToCheck.forEach((item) => {
        if (!foundItem) {
            if (ContainsItem(array, item)) {
                foundItem = true;
            }
        }
    });
    return foundItem;
}
exports.ContainsAnyItem = ContainsAnyItem;
function NotContainsItem(array, itemToCheck) {
    return !ContainsItem(array, itemToCheck);
}
exports.NotContainsItem = NotContainsItem;
function RetrieveDistinct(array) {
    return Array.from(new Set(array.map((item) => item)));
}
exports.RetrieveDistinct = RetrieveDistinct;
function IsNull(arrayToCheck) {
    return arrayToCheck == null || arrayToCheck == undefined;
}
exports.IsNull = IsNull;
function IsNotNull(arrayToCheck) {
    return !IsNull(arrayToCheck);
}
exports.IsNotNull = IsNotNull;
function IsEmpty(arrayToCheck) {
    return arrayToCheck?.length == 0;
}
exports.IsEmpty = IsEmpty;
function IsNotEmpty(arrayToCheck) {
    return !IsEmpty(arrayToCheck);
}
exports.IsNotEmpty = IsNotEmpty;
function IsNullOrEmpty(arrayToCheck) {
    return IsNull(arrayToCheck) || IsEmpty(arrayToCheck);
}
exports.IsNullOrEmpty = IsNullOrEmpty;
function IsNotNullOrEmpty(arrayToCheck) {
    return IsNotNull(arrayToCheck) && IsNotEmpty(arrayToCheck);
}
exports.IsNotNullOrEmpty = IsNotNullOrEmpty;
function IsNullOrEmptyOrContainsSingleEmptyValue(arrayToCheck) {
    if (IsNullOrEmpty(arrayToCheck)) {
        return true;
    }
    if (HasSingleEmptyValue(arrayToCheck)) {
        return true;
    }
    return false;
}
exports.IsNullOrEmptyOrContainsSingleEmptyValue = IsNullOrEmptyOrContainsSingleEmptyValue;
function IsNotNullOrEmptyNorContainsSingleEmptyValue(arrayToCheck) {
    return !IsNullOrEmptyOrContainsSingleEmptyValue(arrayToCheck);
}
exports.IsNotNullOrEmptyNorContainsSingleEmptyValue = IsNotNullOrEmptyNorContainsSingleEmptyValue;
function HasSingleEmptyValue(arrayToCheck) {
    if (arrayToCheck.length == 1 && arrayToCheck[0] == '') {
        return true;
    }
    return false;
}
exports.HasSingleEmptyValue = HasSingleEmptyValue;
function getOccurrence(arrayToCheck, valueToCheck) {
    var count = 0;
    arrayToCheck.forEach((v) => v === valueToCheck && count++);
    return count;
}
exports.getOccurrence = getOccurrence;
function hasOneItem(arrayToCheck) {
    return hasItemsOfCount(arrayToCheck, 1);
}
exports.hasOneItem = hasOneItem;
function hasItemsOfCount(arrayToCheck, numberOfItems) {
    return arrayToCheck.length == numberOfItems;
}
exports.hasItemsOfCount = hasItemsOfCount;
function moveArray(array, from, to) {
    array.splice(to, 0, array.splice(from, 1)[0]);
}
exports.moveArray = moveArray;
//This deliberately only checks contents equality and not positional so [1, 2, 3]== [1, 3, 2]
function areArraysEqual(arr1, arr2) {
    if (IsNullOrEmpty(arr1) && IsNotNullOrEmpty(arr2)) {
        return false;
    }
    if (IsNotNullOrEmpty(arr1) && IsNullOrEmpty(arr2)) {
        return false;
    }
    if (arr1.length !== arr2.length) {
        return false;
    }
    return arr1.every((x) => arr2.indexOf(x) != -1);
}
exports.areArraysEqual = areArraysEqual;
function areArraysNotEqual(arr1, arr2) {
    return !areArraysEqual(arr1, arr2);
}
exports.areArraysNotEqual = areArraysNotEqual;
function areArraysEqualWithOrder(arr1, arr2) {
    if (arr1 == null) {
        return true;
    }
    if (arr1.length !== arr2.length) {
        return false;
    }
    return arr1.every((x, index) => arr2.indexOf(x) == index);
}
exports.areArraysEqualWithOrder = areArraysEqualWithOrder;
function areArraysEqualWithOrderandProperties(value, other) {
    const type = Object.prototype.toString.call(value);
    // If the two objects are not the same type, return false
    if (type !== Object.prototype.toString.call(other)) {
        return false;
    }
    // If items are not an object or array, return false
    if (['[object Array]', '[object Object]'].indexOf(type) < 0) {
        return false;
    }
    // Compare the length of the length of the two items
    const valueLen = type === '[object Array]' ? value.length : Object.keys(value).length;
    const otherLen = type === '[object Array]' ? other.length : Object.keys(other).length;
    if (valueLen !== otherLen) {
        return false;
    }
    // Compare two items
    const compare = function (item1, item2) {
        // Get the object type
        const itemType = Object.prototype.toString.call(item1);
        // If an object or array, compare recursively
        if (['[object Array]', '[object Object]'].indexOf(itemType) >= 0) {
            if (!areArraysEqualWithOrderandProperties(item1, item2)) {
                return false;
            }
        }
        // Otherwise, do a simple comparison
        else {
            // If the two items are not the same type, return false
            if (itemType !== Object.prototype.toString.call(item2)) {
                return false;
            }
            // Else if it's a function, convert to a string and compare
            // Otherwise, just compare
            if (itemType === '[object Function]') {
                if (item1.toString() !== item2.toString()) {
                    return false;
                }
            }
            else {
                if (item1 !== item2) {
                    return false;
                }
            }
        }
    };
    // Compare properties
    if (type === '[object Array]') {
        for (let i = 0; i < valueLen; i++) {
            if (compare(value[i], other[i]) === false) {
                return false;
            }
        }
    }
    else {
        for (let key in value) {
            if (value.hasOwnProperty(key)) {
                if (compare(value[key], other[key]) === false) {
                    return false;
                }
            }
        }
    }
    // If nothing failed, return true
    return true;
}
exports.areArraysEqualWithOrderandProperties = areArraysEqualWithOrderandProperties;
function sortArrayWithProperty(sortOrder, values, sortProperty) {
    if (sortProperty) {
        let newValues = [].concat(values);
        let direction = 1;
        if (sortOrder == Enums_1.SortOrder.Desc) {
            direction = -1;
        }
        return newValues.sort((a, b) => {
            let aSortProperty = a[sortProperty];
            let bSortProperty = b[sortProperty];
            if (typeof aSortProperty == 'string' && typeof bSortProperty == 'string') {
                return aSortProperty.localeCompare(bSortProperty) * direction;
            }
            else {
                return aSortProperty < bSortProperty
                    ? -1 * direction
                    : aSortProperty > bSortProperty
                        ? 1 * direction
                        : 0;
            }
        });
    }
    else {
        return sortArray(values, sortOrder);
    }
}
exports.sortArrayWithProperty = sortArrayWithProperty;
function sortArray(values, sortOrder = Enums_1.SortOrder.Asc) {
    const newValues = [].concat(values);
    const direction = sortOrder == Enums_1.SortOrder.Asc ? 1 : -1;
    return newValues.sort((a, b) => (a < b ? -1 * direction : a > b ? 1 * direction : 0));
}
exports.sortArray = sortArray;
function sortCellValueArray(cellValues, sortOrder = Enums_1.SortOrder.Asc) {
    const newValues = [].concat(cellValues);
    const direction = sortOrder == Enums_1.SortOrder.Asc ? 1 : -1;
    return newValues.sort((a, b) => a.rawValue < b.rawValue ? -1 * direction : a.rawValue > b.rawValue ? 1 * direction : 0);
}
exports.sortCellValueArray = sortCellValueArray;
function sortCellValueArrayNumeric(cellValues, sortOrder = Enums_1.SortOrder.Asc) {
    const direction = sortOrder == Enums_1.SortOrder.Asc ? 1 : -1;
    const newValues = [].concat(cellValues);
    return newValues.sort((a, b) => {
        const valueAAsNumber = Number(a.rawValue);
        const valueBAsNumber = Number(b.rawValue);
        if (isNaN(valueAAsNumber)) {
            return 0;
        }
        if (isNaN(valueBAsNumber)) {
            return 0;
        }
        return valueAAsNumber < valueBAsNumber
            ? -1 * direction
            : valueAAsNumber > valueBAsNumber
                ? 1 * direction
                : 0;
    });
}
exports.sortCellValueArrayNumeric = sortCellValueArrayNumeric;
function sortCellValueArrayDates(cellValues, sortOrder = Enums_1.SortOrder.Asc) {
    cellValues.sort((a, b) => {
        return sortOrder == Enums_1.SortOrder.Asc
            ? +new Date(a.rawValue) - +new Date(b.rawValue)
            : +new Date(b.rawValue) - +new Date(a.rawValue);
    });
    return cellValues;
}
exports.sortCellValueArrayDates = sortCellValueArrayDates;
function groupArrayBy(array, prop) {
    return array.reduce((acc, item) => {
        let key = item[prop];
        acc[key] = acc[key] || [];
        acc[key].push(item);
        return acc;
    }, {});
}
exports.groupArrayBy = groupArrayBy;
function createCommaSeparatedString(values) {
    return values.join(', ');
}
exports.createCommaSeparatedString = createCommaSeparatedString;
function SumArray(array) {
    return array.filter((num) => typeof num === 'number' && !isNaN(num)).reduce((a, b) => a + b, 0);
}
exports.SumArray = SumArray;
function reorderArray(array, startIndex, endIndex) {
    const result = [...array];
    if (startIndex > array.length - 1) {
        // not much that we can do if the dragged item is out of bounds...
        return result;
    }
    if (endIndex > array.length - 1) {
        endIndex = array.length - 1;
    }
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result;
}
exports.reorderArray = reorderArray;
function sortArrayWithOrder(array, order, 
/**
 *
 * The array can contain items which are not listed in the order array.
 * So sortUnorderedItems decides whether to leave these items untouched
 * in the current order in which they are in the array (sortUnorderedItems: false)
 * or to sort them using normal comparison rules
 */
{ sortUnorderedItems }) {
    const itemsToIndex = array.reduce((acc, x, i) => {
        acc.set(x, i);
        return acc;
    }, new Map());
    const orderItemsToIndex = order.reduce((acc, x, i) => {
        acc.set(x, i);
        return acc;
    }, new Map());
    function compareItemsOfCustomSort(valueA, valueB) {
        const orderContainsFirstElement = orderItemsToIndex.has(valueA);
        const indexInOrderOfFirstElement = orderContainsFirstElement
            ? orderItemsToIndex.get(valueA)
            : -1;
        const orderContainsSecondElement = orderItemsToIndex.has(valueB);
        const indexInOrderSecondElement = orderContainsSecondElement
            ? orderItemsToIndex.get(valueB)
            : -1;
        //if none of the element are in the order list we just return normal compare
        if (!orderContainsFirstElement && !orderContainsSecondElement) {
            if (!sortUnorderedItems) {
                // keep the original order
                return itemsToIndex.get(valueA) - itemsToIndex.get(valueB);
            }
            if (valueA == valueB) {
                return 0;
            }
            return valueA < valueB ? -1 : 1;
        }
        //if first item not in the list make sure we put it after the second item
        if (!orderContainsFirstElement) {
            return 1;
        }
        //if second item not in the list make sure we put it after the first item
        if (!orderContainsSecondElement) {
            return -1;
        }
        //return the comparison from the list if the two items are in the list
        return indexInOrderOfFirstElement - indexInOrderSecondElement;
    }
    return [].concat(array).sort(compareItemsOfCustomSort);
}
exports.sortArrayWithOrder = sortArrayWithOrder;
exports.ArrayExtensions = {
    GetLength,
    CorrectLength,
    NotCorrectLength,
    groupArrayBy,
    AddItem,
    ContainsItem,
    NotContainsItem,
    ContainsAnyItem,
    RetrieveDistinct,
    IsNull,
    IsNotNull,
    IsEmpty,
    IsNotEmpty,
    IsNullOrEmpty,
    IsNotNullOrEmpty,
    IsNullOrEmptyOrContainsSingleEmptyValue,
    IsNotNullOrEmptyNorContainsSingleEmptyValue,
    HasSingleEmptyValue,
    getOccurrence,
    hasOneItem,
    hasItemsOfCount,
    moveArray,
    areArraysEqual,
    areArraysNotEqual,
    areArraysEqualWithOrder,
    areArraysEqualWithOrderandProperties,
    sortArray,
    sortCellValueArray,
    sortCellValueArrayNumeric,
    sortCellValueArrayDates,
    sortArrayWithProperty,
    createCommaSeparatedString,
    SumArray,
    reorderArray,
    sortArrayWithOrder,
};
exports.default = exports.ArrayExtensions;
