import { LogicalSearchOperatorEnums, SearchGroupingType, SearchSortDirection } from '../../../enums/unitySystemEnums';
import { getSearchObject } from '../../search/SearchUtilities';
import { FilterOperators } from '../../../models/SearchOperator';
import { cloneDeep } from 'lodash-es';
export const SearchServiceDatasource = (queryData, apiMethodId, searchFilterElements, logicalSearchOperator = LogicalSearchOperatorEnums.And, executeQuery, storeRowData, lookupsMap, eagerLoad = false, getCleanData = null) => {
    return {
        async getRows(params) {
            var _a;
            const { startRow, endRow, rowGroupCols, groupKeys, valueCols, filterModel, sortModel } = params.request;
            const page = endRow / 20;
            const originalSearchObject = getSearchObject(searchFilterElements, page, null, eagerLoad, logicalSearchOperator);
            const searchObject = cloneDeep(originalSearchObject);
            // handle server-side sorting on ag-grid
            if (sortModel.length) {
                const orderElements = searchObject.orderElements;
                sortModel.forEach((sortItem) => {
                    const formattedPropertyName = sortItem.colId.charAt(0).toUpperCase() + sortItem.colId.slice(1);
                    const element = orderElements.find((element) => element.sortColumn === formattedPropertyName);
                    if (element) {
                        element.sortDirection = sortItem.sort.toUpperCase();
                    }
                    else {
                        orderElements.push({
                            sortColumn: formattedPropertyName,
                            sortDirection: sortItem.sort.toUpperCase()
                        });
                    }
                });
            }
            // handle server-side filtering on ag-grid
            if (Object.keys(filterModel).length) {
                const filterElements = searchObject.filterElements;
                Object.keys(filterModel).forEach((key) => {
                    const filterItem = filterModel[key];
                    const formattedPropertyName = key.charAt(0).toUpperCase() + key.slice(1);
                    filterElements.push({
                        searchField: formattedPropertyName,
                        searchValue: filterItem.filter,
                        searchOperator: FilterOperators[filterItem.type]
                    });
                });
            }
            // construct search for initial grouping
            if (rowGroupCols.length && !groupKeys.length) {
                const formattedPropertyName = rowGroupCols[0].field.charAt(0).toUpperCase() +
                    rowGroupCols[0].field.slice(1);
                searchObject.groupingType = SearchGroupingType.Distinct;
                if (!searchObject.groupProperty.includes(formattedPropertyName)) {
                    searchObject.groupProperty.push(formattedPropertyName);
                    const orderElements = searchObject.orderElements;
                    const element = orderElements.find((element) => element.sortColumn === formattedPropertyName);
                    if (!element) {
                        orderElements.push({
                            sortColumn: formattedPropertyName,
                            sortDirection: SearchSortDirection.Asc
                        });
                    }
                }
            }
            // construct the filter for grouped columns
            if (groupKeys.length) {
                // construct search for last grouped element
                if (groupKeys.length === rowGroupCols.length) {
                    searchObject.groupingType = '';
                    const filterElements = searchObject.filterElements;
                    groupKeys.forEach((key, index) => {
                        const rowGroupCol = rowGroupCols[index];
                        const formattedPropertyName = rowGroupCol.field.charAt(0).toUpperCase() +
                            rowGroupCol.field.slice(1);
                        const element = filterElements.find((element) => element.searchField === formattedPropertyName);
                        let currentNode = null;
                        params.api.forEachNode((node) => {
                            var _a;
                            const nodeKey = node.field;
                            if ((nodeKey === null || nodeKey === void 0 ? void 0 : nodeKey.toLowerCase()) ===
                                (formattedPropertyName === null || formattedPropertyName === void 0 ? void 0 : formattedPropertyName.toLowerCase()) &&
                                ((_a = node === null || node === void 0 ? void 0 : node.data) === null || _a === void 0 ? void 0 : _a[nodeKey]) === key) {
                                currentNode = node;
                                return;
                            }
                        });
                        let searchValue = key;
                        if (currentNode) {
                            const cleanData = getCleanData
                                ? getCleanData(currentNode.data, lookupsMap)
                                : null;
                            if (cleanData) {
                                searchValue = cleanData[currentNode.field];
                            }
                        }
                        if (element) {
                            element.searchValue = searchValue;
                            element.searchOperator = '=';
                        }
                        else {
                            filterElements.push({
                                searchField: formattedPropertyName,
                                searchValue: searchValue,
                                searchOperator: '='
                            });
                        }
                    });
                }
                else {
                    // construct search for the next grouped element
                    groupKeys.forEach((key, index) => {
                        const formattedPropertyNameForSearch = rowGroupCols[index].field.charAt(0).toUpperCase() +
                            rowGroupCols[index].field.slice(1);
                        let currentNode = null;
                        params.api.forEachNode((node) => {
                            var _a;
                            const nodeKey = node.field;
                            if ((nodeKey === null || nodeKey === void 0 ? void 0 : nodeKey.toLowerCase()) ===
                                (formattedPropertyNameForSearch === null || formattedPropertyNameForSearch === void 0 ? void 0 : formattedPropertyNameForSearch.toLowerCase()) &&
                                ((_a = node === null || node === void 0 ? void 0 : node.data) === null || _a === void 0 ? void 0 : _a[nodeKey]) === key) {
                                currentNode = node;
                                return;
                            }
                        });
                        let searchValue = key;
                        if (currentNode) {
                            const cleanData = getCleanData
                                ? getCleanData(currentNode.data, lookupsMap)
                                : null;
                            if (cleanData) {
                                searchValue = cleanData[currentNode.field];
                            }
                        }
                        searchObject.filterElements.push({
                            searchField: formattedPropertyNameForSearch,
                            searchValue: searchValue,
                            searchOperator: '='
                        });
                    });
                    searchObject.groupingType = SearchGroupingType.Distinct;
                    const searchIndex = groupKeys.length;
                    const rowGroupCol = rowGroupCols[searchIndex];
                    const formattedPropertyName = rowGroupCol.field.charAt(0).toUpperCase() +
                        rowGroupCol.field.slice(1);
                    if (!searchObject.groupProperty.includes(formattedPropertyName)) {
                        searchObject.groupProperty.push(formattedPropertyName);
                        const orderElements = searchObject.orderElements;
                        const element = orderElements.find((element) => element.sortColumn === formattedPropertyName);
                        if (!element) {
                            orderElements.push({
                                sortColumn: formattedPropertyName,
                                sortDirection: SearchSortDirection.Asc
                            });
                        }
                    }
                }
            }
            if (!startRow &&
                rowGroupCols.length === 0 &&
                !sortModel.length &&
                !Object.keys(filterModel).length &&
                !groupKeys.length &&
                queryData) {
                if (queryData.pageList && queryData.pageList) {
                    params.success({
                        rowData: queryData.pageList,
                        rowCount: parseInt(queryData.total)
                    });
                    if (storeRowData) {
                        storeRowData(queryData.pageList);
                    }
                }
                else {
                    // TODO: add an overlay to display no rows
                    params.success({
                        rowData: [],
                        rowCount: 0
                    });
                    if (storeRowData) {
                        storeRowData([]);
                    }
                }
            }
            else {
                let response = null;
                if (executeQuery) {
                    const data = { data: searchObject };
                    response = await executeQuery(data, apiMethodId, lookupsMap).catch((e) => params.success({
                        rowData: [],
                        rowCount: 0
                    }));
                }
                const rowData = (response === null || response === void 0 ? void 0 : response.status) === 200 ? response === null || response === void 0 ? void 0 : response.data : response;
                if (rowData && response) {
                    if (((_a = rowData === null || rowData === void 0 ? void 0 : rowData.pageList) === null || _a === void 0 ? void 0 : _a.length) > 0) {
                        params.success({
                            rowData: rowData.pageList,
                            rowCount: parseInt(rowData.total)
                        });
                        if (storeRowData) {
                            storeRowData(rowData.pageList);
                        }
                    }
                    else {
                        params.success({
                            rowData: [],
                            rowCount: 0
                        });
                        if (storeRowData) {
                            storeRowData([]);
                        }
                    }
                }
                else {
                    params.success({
                        rowData: [],
                        rowCount: 0
                    });
                    if (storeRowData) {
                        storeRowData([]);
                    }
                }
            }
        }
    };
};
//# sourceMappingURL=SearchServiceDatasource.js.map