var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import { DateTime } from 'luxon';
import { findTermByType } from '../utilities/maintenanceEngine/CrudBrowserUtilities';
import { cloneDeep } from 'lodash-es';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useHistory } from 'react-router-dom';
import { SqlFilterOperators } from '../enums/aggridEnums';
import { LogicalSearchOperatorEnums, LookupTypeIdEnums, UdpEnums } from '../enums/unitySystemEnums';
import { usePromotedMethodEntity } from '../hooks/usePromotedMethodEntity';
import { useQueryExecutors } from '../hooks/useQueryExecutors';
import { CrudTableSidePanel } from '../maintenanceEngine/crudBrowser/CrudTableSidePanel';
import { useLookupsStore } from '../stores/lookupsStore';
import { executeQueryAdHoc, executeQueryWithParameters } from '../udp/utilities/methodUtils';
import { FluentDialog } from '../UI/feedback';
import { SideSheet } from '../UI/surfaces/SideSheet';
import { ClientSideUdpGrid, SearchMethodUdpGrid } from '../UI/templates/newGrid';
import { useAgGridApi } from '../utilities/aggrid/AgTable';
import { getSanitizedName } from '../utilities/entities/entityUtilities';
import { toTitleCase, toUpperFirstChar } from '../utilities/input/StringUtilities';
import { getSearchObject } from '../utilities/search/SearchUtilities';
import { DataBrowserColumnDefs } from './DataBrowserColumnDefs';
const GRID_ID = '4be3be45-1930-4ab9-b7b7-0c0fa3e30490';
export const DataBrowserContainer = (props) => {
    const { entityData, onCreate, onUpdate, onDelete, onLoadInquiryNode, entityAttributes, foreignKeyData, loading, promotedEntity, isServerSide = false, setGridApi, filterElements, backToConfigPage, queryColumnsData, lookupsMap = {} } = props, other = __rest(props, ["entityData", "onCreate", "onUpdate", "onDelete", "onLoadInquiryNode", "entityAttributes", "foreignKeyData", "loading", "promotedEntity", "isServerSide", "setGridApi", "filterElements", "backToConfigPage", "queryColumnsData", "lookupsMap"]);
    const [dialogOpen, setDialogOpen] = useState(false);
    const [sideSheetOpenState, setSideSheetOpenState] = useState({
        add: false,
        update: false,
    });
    const [sideSheetWidth, setSideSheetWidth] = useState(600);
    const [, setSideSheetButtonLabel] = useState('');
    const [, setOtherSideSheetProps] = useState({});
    const [, setSideSheetOnSubmit] = useState(() => () => console.warn('onSubmit not set'));
    const [, setFilterChipsArray] = useState([]);
    const [searchFilterElements, setSearchFilterElements] = useState(filterElements);
    const [entityUdpObjectInfo, setEntityUdpObjectInfo] = useState(null);
    const { t } = useTranslation();
    const history = useHistory();
    const { gridApi } = useAgGridApi();
    const { getCleanData } = useQueryExecutors();
    const lookupApiMethodId = useLookupsStore((state) => state.lookupApiMethodId);
    const [selectedEntity, setSelectedEntity] = useState(null);
    const gridApiRef = useRef(null);
    const handleSideSheet = useCallback((type, open, selectedEntity) => {
        setSelectedEntity(selectedEntity);
        setSideSheetOpenState((prev) => (Object.assign(Object.assign({}, prev), { [type]: open })));
    }, []);
    const { data: udpObjectInfoEntity } = usePromotedMethodEntity('udpObjectInfo', true);
    const entityName = useMemo(() => {
        if (!promotedEntity)
            return '';
        return promotedEntity.entityName || '';
    }, [promotedEntity]);
    const commonEntityName = useMemo(() => {
        var _a;
        if (!entityName && !entityUdpObjectInfo)
            return '';
        return toTitleCase(((_a = entityUdpObjectInfo === null || entityUdpObjectInfo === void 0 ? void 0 : entityUdpObjectInfo.properties) === null || _a === void 0 ? void 0 : _a.displayName) || getSanitizedName(entityName));
    }, [entityName, entityUdpObjectInfo]);
    const createApiMethodPageId = useMemo(() => {
        var _a;
        return (_a = promotedEntity === null || promotedEntity === void 0 ? void 0 : promotedEntity.unityBaseCreateMethod) === null || _a === void 0 ? void 0 : _a.pageId;
    }, [promotedEntity]);
    const secondaryActionButtons = useMemo(() => {
        const actions = [];
        if (backToConfigPage) {
            actions.push({
                onClick: backToConfigPage,
                label: t('Back To Config'),
                iconName: 'settings',
                tooltip: t('Back To Config'),
                background: 'transparent',
            });
        }
        return actions;
    }, [backToConfigPage, t]);
    const closeDialog = useCallback(() => {
        setDialogOpen(false);
    }, []);
    const deleteDialogConfig = useMemo(() => {
        return {
            title: t('Delete'),
            message: t('Are you sure you want to delete this row?'),
            actionOne: closeDialog,
            labelOne: t('Cancel'),
            actionTwo: onDelete,
            labelTwo: t('Confirm'),
            loading: !!!foreignKeyData,
        };
    }, [closeDialog, foreignKeyData, onDelete, t]);
    const actionList = useMemo(() => {
        if (!promotedEntity) {
            return;
        }
        const actions = [
            {
                id: 1, // Must be unique
                title: (promotedEntity === null || promotedEntity === void 0 ? void 0 : promotedEntity.unityBaseUpdateMethod) ? t('Edit') : t('Edit Method Not Accessible'),
                iconName: 'edit',
                handleOnClick: (e, params) => handleSideSheet('update', true, params === null || params === void 0 ? void 0 : params.data),
                disabled: !!!(promotedEntity === null || promotedEntity === void 0 ? void 0 : promotedEntity.unityBaseUpdateMethod),
            },
            {
                id: 2, // Must be unique
                title: (promotedEntity === null || promotedEntity === void 0 ? void 0 : promotedEntity.unityBaseDeleteMethod)
                    ? t('Delete')
                    : t('Delete Method Not Accessible'),
                iconName: 'trashCan',
                handleOnClick: () => setDialogOpen(true),
                opens: 'dialog',
                disabled: !!!(promotedEntity === null || promotedEntity === void 0 ? void 0 : promotedEntity.unityBaseDeleteMethod),
            },
        ];
        if (!!onLoadInquiryNode) {
            actions.push({
                id: 5, // Must be unique
                title: t('Load to Tree'),
                iconName: 'migrateAlt',
                handleOnClick: (e, params) => {
                    const obj = getCleanData(params === null || params === void 0 ? void 0 : params.data, lookupsMap);
                    onLoadInquiryNode(obj);
                },
                loading: !!!foreignKeyData,
                view: {},
            });
        }
        return actions;
    }, [
        promotedEntity,
        t,
        onLoadInquiryNode,
        handleSideSheet,
        foreignKeyData,
        getCleanData,
        lookupsMap,
    ]);
    const virtualActions = useMemo(() => {
        return [
            // Action for opening Virtual Configuration
            {
                id: 3,
                title: t('Open Virtual Table'),
                iconName: 'search',
                loading: !!!foreignKeyData,
                handleOnClick: (value) => {
                    history.push({
                        pathname: `/virtual/${value.id}`,
                        search: `?entityName=${entityName}`,
                        state: {
                            value,
                            promotedEntity,
                            label: value.name,
                        },
                    });
                },
                checkDisabled: (value) => value.typeId !== LookupTypeIdEnums.Lookup,
            },
        ];
    }, [entityName, t, history, promotedEntity, foreignKeyData]);
    const jointActionList = useMemo(() => {
        if (!actionList) {
            return [];
        }
        // Check if it's a udp lookup entity
        if (entityName.toLowerCase() === UdpEnums.Udp_Lookup.toLowerCase()) {
            return [...actionList, ...virtualActions];
        }
        return actionList;
    }, [actionList, virtualActions, entityName]);
    const columnDefs = useMemo(() => {
        return DataBrowserColumnDefs(entityAttributes, jointActionList, true, queryColumnsData);
    }, [entityAttributes, jointActionList, queryColumnsData]);
    const sideSheetList = useMemo(() => {
        var _a;
        const data = getCleanData(entityData, lookupsMap);
        return [
            {
                open: sideSheetOpenState.add,
                closeSheet: () => handleSideSheet('add', false),
                title: `Add New ${commonEntityName}`,
                width: sideSheetWidth,
                children: (React.createElement(CrudTableSidePanel, { entityAttributes: entityAttributes, foreignKeyData: foreignKeyData, onCreate: onCreate, closeSideSheet: () => handleSideSheet('add', false), pageId: createApiMethodPageId, setSideSheetWidth: setSideSheetWidth, setSideSheetButtonLabel: setSideSheetButtonLabel, setSideSheetOnSubmit: setSideSheetOnSubmit, setSideSheetProps: setOtherSideSheetProps, isNewEntry: true, entityData: entityData, entityName: entityName }))
            },
            {
                open: sideSheetOpenState.update,
                closeSheet: () => handleSideSheet('update', false),
                title: `Update ${commonEntityName}`,
                width: 550,
                children: (React.createElement(CrudTableSidePanel, { entityAttributes: entityAttributes, foreignKeyData: foreignKeyData, crudTableEditionData: selectedEntity, onUpdate: onUpdate, closeSideSheet: () => handleSideSheet('update', false), closeSideSheetPropName: 'closeSideSheet', pageId: (_a = promotedEntity === null || promotedEntity === void 0 ? void 0 : promotedEntity.unityBaseUpdateMethod) === null || _a === void 0 ? void 0 : _a.pageId, isNewEntry: false, entityData: data, entityName: entityName })),
            },
        ];
    }, [
        commonEntityName,
        createApiMethodPageId,
        entityAttributes,
        entityData,
        entityName,
        foreignKeyData,
        handleSideSheet,
        onCreate,
        onUpdate,
        promotedEntity,
        selectedEntity,
        sideSheetOpenState,
        sideSheetWidth,
        getCleanData,
        lookupsMap,
    ]);
    const SideOptionList = useMemo(() => {
        return sideSheetList.map((item, index) => (React.createElement(SideSheet, { open: item.open, onClose: item.closeSheet, title: item.title, width: item.width, key: index }, item.children)));
    }, [sideSheetList]);
    const getLookupResults = useCallback(async () => {
        if (!lookupsMap || !lookupApiMethodId)
            return null;
        const lookupToFilterOn = Object.values(lookupsMap).find((item) => item.filterOn);
        const lookupId = (lookupToFilterOn === null || lookupToFilterOn === void 0 ? void 0 : lookupToFilterOn.value) || '';
        if (lookupId) {
            const lookupResult = await executeQueryWithParameters({ data: { id: lookupId } }, lookupApiMethodId);
            return lookupResult;
        }
        return null;
    }, [lookupsMap, lookupApiMethodId]);
    const formattedData = useMemo(() => {
        if (entityData) {
            let formattedEntityData = cloneDeep(entityData);
            // get list of attributes that are datetime
            const datetimeFields = entityAttributes === null || entityAttributes === void 0 ? void 0 : entityAttributes.reduce((defs, element) => {
                var _a;
                if (!((_a = element === null || element === void 0 ? void 0 : element.extendedProperties) === null || _a === void 0 ? void 0 : _a.childEntity) &&
                    findTermByType(element === null || element === void 0 ? void 0 : element.type, 'datetime')) {
                    defs.push((element === null || element === void 0 ? void 0 : element.name.charAt(0).toLowerCase()) + (element === null || element === void 0 ? void 0 : element.name.slice(1)));
                }
                return defs;
            }, []);
            if (datetimeFields === null || datetimeFields === void 0 ? void 0 : datetimeFields.length) {
                formattedEntityData.forEach((e) => {
                    Object.keys(e).forEach((key) => {
                        // format all datetime fields
                        if (datetimeFields.find((field) => field === key)) {
                            // LAA UNT-2977: add null check to prevent default date from being added when null
                            if (e[key] === null)
                                return;
                            e[key] = DateTime.fromJSDate(new Date(e[key])).toFormat('yyyy/MM/dd HH:mm:ss');
                        }
                    });
                });
            }
            return formattedEntityData;
        }
        return [];
    }, [entityAttributes, entityData]);
    const handleChipToggle = useCallback((chip) => {
        if (isServerSide && chip && chip.filterValue && chip.keyName) {
            const updatedSearchFilterElements = [...searchFilterElements];
            const chipFilterElement = {
                searchValue: chip.filterValue,
                searchField: toUpperFirstChar(chip.keyName),
                searchOperator: SqlFilterOperators.EQUALS,
            };
            updatedSearchFilterElements.push(chipFilterElement);
            setSearchFilterElements(updatedSearchFilterElements);
        }
        else {
            // TODO: handle client side filter chips
        }
    }, [isServerSide, searchFilterElements]);
    const handleChipUntoggle = useCallback(() => {
        setSearchFilterElements(filterElements);
    }, [filterElements]);
    const setFilterChips = useCallback(async () => {
        var _a;
        let filterChipsArray = [];
        // A list of all the products (for product lookup)
        const lookup = await getLookupResults();
        const lookupResults = lookup === null || lookup === void 0 ? void 0 : lookup.data;
        if (!lookupResults) {
            setFilterChipsArray([]);
            return; // no lookup results
        }
        let keyName = lookupResults.keyName;
        const valueName = lookupResults.valueName;
        const lookupToFilterOn = Object.values(lookupsMap).find((item) => item.filterOn);
        let chipKey = keyName;
        const lookupMapKeys = Object.keys(lookupsMap);
        for (let i = 0; i < lookupMapKeys.length; i++) {
            const key = lookupMapKeys[i];
            if (lookupsMap[key].value === (lookupToFilterOn === null || lookupToFilterOn === void 0 ? void 0 : lookupToFilterOn.value)) {
                chipKey = key;
                break;
            }
        }
        // Add the chips
        for (let i = 0; i < (lookupResults === null || lookupResults === void 0 ? void 0 : lookupResults.data.length); i++) {
            const lookupResult = lookupResults.data[i];
            const label = lookupResult[valueName];
            const numRows = (_a = formattedData === null || formattedData === void 0 ? void 0 : formattedData.filter((obj) => obj[keyName] === label)) === null || _a === void 0 ? void 0 : _a.length;
            let chipData = {
                label: `${label}`,
                value: !isServerSide ? numRows || '' : '',
                filterValue: lookupResult[keyName],
                id: i,
                keyName: chipKey,
            };
            chipData.onToggle = () => handleChipToggle(chipData);
            chipData.onUntoggle = () => handleChipUntoggle();
            // Only add the chip if it has results and is not using server side
            if (!isServerSide && numRows > 0) {
                filterChipsArray.push(chipData);
            }
            if (isServerSide) {
                filterChipsArray.push(chipData);
            }
        }
        setFilterChipsArray(filterChipsArray);
    }, [
        getLookupResults,
        handleChipToggle,
        handleChipUntoggle,
        isServerSide,
        formattedData,
        lookupsMap,
    ]);
    useEffect(() => {
        setFilterChips();
    }, [setFilterChips]);
    useEffect(() => {
        // eslint-disable-next-line react-you-might-not-need-an-effect/no-derived-state
        setSearchFilterElements(filterElements || []);
    }, [filterElements]);
    useEffect(() => {
        if (!gridApi)
            return;
        if (setGridApi) {
            // eslint-disable-next-line react-you-might-not-need-an-effect/no-pass-data-to-parent
            setGridApi(gridApi);
        }
    }, [gridApi, setGridApi]);
    useEffect(() => {
        var _a;
        const executeSearchForEntityUdpObjectInfo = async (apiMethodId, sanitizedEntityName) => {
            var _a;
            const filterElements = [
                {
                    searchField: 'SanitizedName',
                    searchOperator: '=',
                    searchValue: sanitizedEntityName,
                },
            ];
            const requestObj = getSearchObject(filterElements, 1, 50, false);
            const response = await executeQueryAdHoc({ data: requestObj }, apiMethodId);
            if (response.status === 200) {
                const data = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.pageList[0];
                setEntityUdpObjectInfo(data);
            }
        };
        if ((udpObjectInfoEntity === null || udpObjectInfoEntity === void 0 ? void 0 : udpObjectInfoEntity.unityBaseSearchMethod) && entityName) {
            executeSearchForEntityUdpObjectInfo((_a = udpObjectInfoEntity === null || udpObjectInfoEntity === void 0 ? void 0 : udpObjectInfoEntity.unityBaseSearchMethod) === null || _a === void 0 ? void 0 : _a.apiMethodId, getSanitizedName(entityName));
        }
    }, [udpObjectInfoEntity, entityName]);
    const handleGridApiCallback = (api) => {
        gridApiRef.current = api;
    };
    const gridHeaderConfig = useMemo(() => {
        return {
            title: commonEntityName,
            primaryActionButton: {
                label: t('Add'),
                iconName: 'add',
                onClick: () => handleSideSheet('add', true, null),
            },
            secondaryActionButtons: secondaryActionButtons,
        };
    }, [commonEntityName, handleSideSheet, secondaryActionButtons, t]);
    const gridFunctions = useMemo(() => {
        return [
            { name: 'agGridExport' },
            { name: 'agGridHideShowColumns' },
            { name: 'agGridSizeColumnsToFit' },
            { name: 'agGridAutoSizeColumns' },
            { name: 'openSavedViews' },
            { name: 'quickFilter' },
        ];
    }, []);
    const gridOptions = useMemo(() => {
        return {
            pagination: true,
            paginationPageSize: 20,
        };
    }, []);
    const searchMethodConfig = useMemo(() => {
        var _a;
        const searchObject = getSearchObject(searchFilterElements, 1, null, false, LogicalSearchOperatorEnums.And);
        return {
            apiMethodId: (_a = promotedEntity === null || promotedEntity === void 0 ? void 0 : promotedEntity.unityBaseSearchMethod) === null || _a === void 0 ? void 0 : _a.apiMethodId,
            customSearchObject: searchObject
        };
    }, [promotedEntity, searchFilterElements]);
    return (React.createElement(React.Fragment, null, isServerSide && !!promotedEntity ? (React.createElement(SearchMethodUdpGrid, Object.assign({ gridId: GRID_ID, searchMethodConfig: searchMethodConfig, columnDefs: columnDefs, gridApiCallback: handleGridApiCallback, gridHeaderConfig: gridHeaderConfig, gridFunctions: [{ name: 'agGridRefreshData' }, ...gridFunctions], gridOptions: gridOptions, loading: loading }, other))) : (React.createElement(ClientSideUdpGrid, Object.assign({ gridId: GRID_ID, rowData: formattedData, columnDefs: columnDefs, gridApiCallback: handleGridApiCallback, gridHeaderConfig: gridHeaderConfig, gridFunctions: gridFunctions, gridOptions: gridOptions, loading: loading }, other))), SideOptionList, React.createElement(FluentDialog, { open: dialogOpen, handleClose: closeDialog, title: deleteDialogConfig === null || deleteDialogConfig === void 0 ? void 0 : deleteDialogConfig.title, message: deleteDialogConfig === null || deleteDialogConfig === void 0 ? void 0 : deleteDialogConfig.message, actionOne: deleteDialogConfig === null || deleteDialogConfig === void 0 ? void 0 : deleteDialogConfig.actionOne, labelOne: deleteDialogConfig === null || deleteDialogConfig === void 0 ? void 0 : deleteDialogConfig.labelOne, actionTwo: deleteDialogConfig === null || deleteDialogConfig === void 0 ? void 0 : deleteDialogConfig.actionTwo, labelTwo: deleteDialogConfig === null || deleteDialogConfig === void 0 ? void 0 : deleteDialogConfig.labelTwo, progress: deleteDialogConfig === null || deleteDialogConfig === void 0 ? void 0 : deleteDialogConfig.loading })));
};
//# sourceMappingURL=DataBrowserContainer.js.map