import { useCallback, useMemo } from 'react';
import { SearchGroupingType, LogicalSearchOperatorEnums, UdpSearchEnums } from '../../enums/unitySystemEnums';
import { DateTime, IANAZone } from 'luxon';
import { AgGridFilterOperators, AgGridFilterTypes, SearchValueType, SqlFilterOperators } from '../../enums/aggridEnums';
import { useUser } from '../auth/useUser';
export const getSearchObject = (searchFilterElements, page, pageSize, eagerLoad = false, logicalSearchOperator = LogicalSearchOperatorEnums.And, searchFilterGroups = []) => {
    const searchObject = {
        pageNumber: page || 1,
        pageSize: pageSize || 20,
        filterElements: [],
        filterGroups: [],
        orderElements: [],
        groupingType: '',
        groupProperty: [],
        groupOperationList: [],
        eagerLoad: eagerLoad,
        logicalSearchOperator: logicalSearchOperator
    };
    if (searchFilterElements) {
        searchFilterElements.forEach((property) => {
            var _a;
            const formattedPropertyName = property.searchField;
            // adds order elements
            if ('sortDirection' in property && property.sortDirection) {
                const orderElement = {
                    sortColumn: formattedPropertyName,
                    sortDirection: property.sortDirection
                };
                searchObject.orderElements.push(orderElement);
            }
            else {
                // An object from searchFilterElements should be added filterElements only if it is not an orderElement (i.e. it has no sortDirection)
                searchObject.filterElements.push(property);
            }
            if ('distinct' in property && property.distinct) {
                searchObject.groupingType = SearchGroupingType.Distinct;
                (_a = searchObject.groupProperty) === null || _a === void 0 ? void 0 : _a.push(formattedPropertyName);
            }
        });
    }
    searchObject.filterGroups = searchFilterGroups;
    return searchObject;
};
export const getApiMethodIdByPath = (apiMethodList, path) => {
    var _a;
    const foundApiMethod = apiMethodList.find((method) => path.includes(method.path));
    return (_a = foundApiMethod === null || foundApiMethod === void 0 ? void 0 : foundApiMethod.apiMethodId) !== null && _a !== void 0 ? _a : null;
};
export const getSearchIdentifiers = (catalogObjects, catalogReturnObject) => {
    var _a;
    var _b;
    if (!catalogObjects)
        return [];
    const matchingCatalogObject = catalogObjects.find((co) => co.catalogObjectName === catalogReturnObject);
    const properties = (_a = matchingCatalogObject === null || matchingCatalogObject === void 0 ? void 0 : matchingCatalogObject.properties) === null || _a === void 0 ? void 0 : _a.filter((property) => {
        var _a;
        return (_a = property === null || property === void 0 ? void 0 : property.extendedProperties) === null || _a === void 0 ? void 0 : _a.identifier;
    });
    return (_b = properties === null || properties === void 0 ? void 0 : properties.map((property) => property.name)) !== null && _b !== void 0 ? _b : [];
};
/**
 * Returns a reference to a function that takes an Ag-grid FilterModel object and
 * processes it to create an array of SearchFilters.
 * @param timeZone string or null;
 * @returns Function for processing Ag-grid FilterModel
 */
export const useConvertFilterModelToSearchFilters = (timeZone = null) => {
    const user = useUser();
    const zone = useMemo(() => {
        var _a, _b;
        var _c;
        let tz = (_c = 
        // @ts-ignore - legacy user.additionalProperties is untyped/unknown
        timeZone !== null && 
        // @ts-ignore - legacy user.additionalProperties is untyped/unknown
        timeZone !== void 0 ? 
        // @ts-ignore - legacy user.additionalProperties is untyped/unknown
        timeZone : (_a = user === null || user === void 0 ? void 0 : user.additionalProperties) === null || _a === void 0 ? void 0 : _a.activeUtilityTimeZone) !== null && _c !== void 0 ? _c : 'local';
        const validTimeZone = tz !== 'local' &&
            // @ts-ignore - legacy user.additionalProperties is untyped/unknown
            (tz === ((_b = user === null || user === void 0 ? void 0 : user.additionalProperties) === null || _b === void 0 ? void 0 : _b.activeUtilityTimeZone) ||
                IANAZone.isValidZone(tz))
            ? tz
            : 'local'; // IANAZone.isValidZone is very slow, skip it if known valid timeZone passed
        return validTimeZone;
    }, [timeZone, user]);
    const convertFilterModelToSearchFilters = useCallback((filterModel = null) => {
        if (!filterModel) {
            return [];
        }
        let searchFilters = [];
        searchFilters = Object.entries(filterModel).map((item) => {
            var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
            let field = item[0];
            let operator;
            let type;
            let value;
            // Set the filter value; dependent on filter type (e.g. Date, Set, etc.)
            if (((_a = item[1]) === null || _a === void 0 ? void 0 : _a.filterType) === AgGridFilterTypes.DATE) {
                // Applies the applicable timezone to the date filter value for usage when
                // constructing the database query.
                let dateFilterValueWithoutTime = (_c = (_b = item[1]) === null || _b === void 0 ? void 0 : _b.dateFrom) === null || _c === void 0 ? void 0 : _c.substring(0, 10); // e.g. 2022-02-05
                let dateSplit = dateFilterValueWithoutTime.split('-');
                let date = new Date(dateSplit[0], dateSplit[1] - 1, dateSplit[2]);
                const filterDateTimeMidnight = DateTime.fromJSDate(date).setZone(zone, { keepLocalTime: true });
                let dateString = filterDateTimeMidnight.toJSDate().toISOString();
                value = dateString;
            }
            else if (((_d = item[1]) === null || _d === void 0 ? void 0 : _d.filterType) === AgGridFilterTypes.SET) {
                value = item[1].values.join(',');
                operator = SqlFilterOperators.IN;
            }
            else {
                value = (_e = item[1]) === null || _e === void 0 ? void 0 : _e.filter;
            }
            switch ((_g = (_f = item[1]) === null || _f === void 0 ? void 0 : _f.type) === null || _g === void 0 ? void 0 : _g.toLowerCase()) {
                case AgGridFilterOperators.CONTAINS:
                    operator = SqlFilterOperators.LIKE;
                    break;
                case AgGridFilterOperators.EQUALS:
                    operator = SqlFilterOperators.EQUALS;
                    if (((_h = item[1]) === null || _h === void 0 ? void 0 : _h.filterType) === AgGridFilterTypes.DATE) {
                        type = SearchValueType.Type_DateTime;
                    }
                    break;
                case AgGridFilterOperators.NOT_EQUALS:
                    operator = SqlFilterOperators.NOT_EQUALS;
                    break;
                case AgGridFilterOperators.GREATER_THAN:
                    operator = SqlFilterOperators.GREATER_THAN;
                    break;
                case AgGridFilterOperators.GREATER_THAN_OR_EQUAL:
                    operator = SqlFilterOperators.GREATER_THAN_OR_EQUAL;
                    break;
                case AgGridFilterOperators.LESS_THAN:
                    operator = SqlFilterOperators.LESS_THAN;
                    break;
                case AgGridFilterOperators.LESS_THAN_OR_EQUAL:
                    operator = SqlFilterOperators.LESS_THAN_OR_EQUAL;
                    break;
                case AgGridFilterOperators.STARTSWITH:
                    operator = SqlFilterOperators.STARTSWITH;
                    break;
                case AgGridFilterOperators.IN_RANGE:
                    operator = SqlFilterOperators.BETWEEN;
                    if (((_j = item[1]) === null || _j === void 0 ? void 0 : _j.filterType) === AgGridFilterTypes.NUMBER) {
                        value += ',' + ((_k = item[1]) === null || _k === void 0 ? void 0 : _k.filterTo);
                    }
                    else if (((_l = item[1]) === null || _l === void 0 ? void 0 : _l.filterType) === AgGridFilterTypes.DATE) {
                        let dateFilterValueWithoutTime = (_o = (_m = item[1]) === null || _m === void 0 ? void 0 : _m.dateTo) === null || _o === void 0 ? void 0 : _o.substring(0, 10); // e.g. 2022-02-05
                        let dateSplit = dateFilterValueWithoutTime.split('-');
                        let date = new Date(dateSplit[0], dateSplit[1] - 1, dateSplit[2]);
                        const filterDateTimeMidnight = DateTime.fromJSDate(date).setZone(zone, { keepLocalTime: true });
                        let dateString = filterDateTimeMidnight
                            .toJSDate()
                            .toISOString();
                        value += ',' + dateString;
                    }
                    break;
                case AgGridFilterOperators.ENDSWITH:
                    operator = SqlFilterOperators.ENDSWITH;
                    break;
                default:
                    break;
            }
            return {
                searchField: field,
                searchValue: value,
                searchOperator: operator,
                searchValueType: type,
                groupId: null
            };
        });
        return searchFilters;
    }, [zone]);
    return convertFilterModelToSearchFilters;
};
// Parses the URL search params for UDP search filters
// e.g. udp_search-FieldName-Operator=Value - udp_search-firstName-like=John
export const parseSearchParamsIntoFilterObjects = () => {
    /* eslint-disable @typescript-eslint/no-unsafe-assignment */
    const qs = new URLSearchParams(window.location.search);
    const filterObjects = [];
    qs.forEach((value, key) => {
        if (key.startsWith(UdpSearchEnums.UdpQueryParamPrefix)) {
            const keyParts = key.split('-');
            const searchField = keyParts[1] || undefined;
            const searchOperatorRaw = keyParts[2] || undefined;
            const searchOperator = SqlFilterOperators[searchOperatorRaw.toUpperCase()] || undefined;
            const searchValue = value || undefined;
            if (searchField && searchOperator && searchValue) {
                filterObjects.push({
                    searchField,
                    searchOperator,
                    searchValue
                });
            }
        }
    });
    return filterObjects;
};
//# sourceMappingURL=SearchUtilities.js.map