import React, { useCallback, useEffect, useMemo, useReducer, useState } from 'react';
import { createPortal } from 'react-dom';
import { ActionContext } from '../../contexts/ActionContext';
import { ActionDispatchContext } from '../../contexts/ActionDispatchContext';
import { ActionWrapper } from '../../actions/ActionWrapper';
import { apiMutate } from '../useAxiosMutate';
import { NodeActionEnums } from '../../enums/unitySystemEnums';
import { useAuthedUser } from '../auth/useAuthedUser';
import { useAxiosGet } from '../useAxiosGet';
import useDefaultFormValues from '../crud/useDefaultFormValues';
import { ActionLoadingContext } from '../../contexts/ActionLoadingContext';
import { ActionLoadingDispatchContext } from '../../contexts/ActionLoadingDispatchContext';
import LoadingOverlay from '../../UI/loading/LoadingOverlay';
import { useHistory } from 'react-router-dom';
import { usePromotedLookupMethods } from '../../hooks/usePromotedLookupMethods';
import { useCatalogStore } from '../../stores/catalogStore';
import { useActionStore } from '../../stores/actionStore';
import { useShellStore } from '../../stores/shellStore';
import { ConfigService } from '../../configService';
import { usePromotedMethodEntities } from '../../hooks/usePromotedMethodEntities';
const emptyAction = {
    action: {
        actionId: '',
        payload: null
    },
    actionPanels: {},
    catalog: null,
    catalogPromise: null,
    catalogEntities: [],
    catalogPromotedEntities: [],
    menuListState: {
        menuList: [],
        handleRemoveMenuItem: () => { },
        selectedMenuIndex: null
    },
    modal: {
        open: false,
        action: null,
        title: ''
    },
    inquiryParams: {
        0: {
            selectedNode: null,
            selectedNodeParent: null,
            refreshTree: null
        }
    },
    showInquiryHeaderActions: true,
    sideSheet: {
        open: false,
        action: null
    },
    splitScreen: {
        open: false,
        action: null,
        type: null,
        params: null
    },
    pageSplitScreen: {
        open: false,
        action: null,
        type: null,
        params: null
    },
    pageContainerSplitScreen: {
        open: false,
        action: null,
        type: null,
        params: null
    },
    setCurrentEntityName: null
};
const newRouteEmptyAction = {
    action: {
        actionId: '',
        payload: null
    },
    actionPanels: {},
    menuListState: {
        menuList: [],
        handleRemoveMenuItem: () => { },
        selectedMenuIndex: null
    },
    modal: {
        open: false,
        action: null,
        title: ''
    },
    selectedNodeObj: null,
    inquiryParams: {
        0: {
            selectedNode: null,
            selectedNodeParent: null,
            refreshTree: null
        }
    },
    showInquiryHeaderActions: true,
    sideSheet: {
        open: false,
        action: null
    },
    splitScreen: {
        open: false,
        action: null,
        type: null,
        params: null
    },
    pageSplitScreen: {
        open: false,
        action: null,
        type: null,
        params: null
    },
    pageContainerSplitScreen: {
        open: false,
        action: null,
        type: null,
        params: null
    }
};
const emptyActionLoading = {
    loading: false,
    waitingToExecute: ''
};
export const ActionProvider = (props) => {
    var _a;
    const { domRoot, children } = props;
    const user = useAuthedUser();
    const history = useHistory();
    const [apiCatalogId, setApiCatalogId] = useState(null);
    const [foreignKeyData, setForeignKeyData] = useState([]);
    const [actionPanel, setActionPanel] = useState(null);
    const [currentEntityName, setCurrentEntityName] = useState(null);
    const [currentLocationPathname, setCurrentLocationPathname] = useState((_a = history === null || history === void 0 ? void 0 : history.location) === null || _a === void 0 ? void 0 : _a.pathname);
    usePromotedMethodEntities(apiCatalogId);
    const selectedNode = useActionStore((state) => state.selectedNode);
    const currentContainerId = useShellStore((state) => state.currentContainerId);
    // Set the lookup api method Id for the application
    usePromotedLookupMethods(apiCatalogId);
    const setCurrentApiCatalogId = useCatalogStore((state) => state.setCurrentApiCatalogId);
    const [{ data: tpacb, loading: tpacbLoading }] = useAxiosGet(ConfigService.integrationV1ApiUrl, `tenantProductApiCatalogBase/tenant/${user === null || user === void 0 ? void 0 : user.currentTenantId}/product/${ConfigService.config.UNITY_PRODUCT_ID}`, {}, !(user === null || user === void 0 ? void 0 : user.currentTenantId), false);
    const [actionState, dispatch] = useReducer((state, reducerAction) => {
        switch (reducerAction.type) {
            case 'SET_ACTION_PANELS':
                let containerIdToUse = 0;
                if (reducerAction.containerId) {
                    containerIdToUse = reducerAction.containerId;
                }
                const updatedActionPanels = Object.assign({}, state.actionPanels);
                updatedActionPanels[containerIdToUse] = reducerAction.actionPanels;
                state = Object.assign(Object.assign({}, state), { actionPanels: updatedActionPanels });
                break;
            case 'OPEN_SIDESHEET':
                state = Object.assign(Object.assign({}, state), { sideSheet: reducerAction.sideSheet });
                break;
            case 'OPEN_MODAL':
                state = Object.assign(Object.assign({}, state), { modal: reducerAction.modal });
                break;
            case 'CLOSE_ALL_SPLIT_SCREENS':
                state = Object.assign(Object.assign({}, state), { splitScreen: { open: false, action: null, type: null, params: null }, pageSplitScreen: {
                        open: false,
                        action: null,
                        type: null,
                        params: null
                    }, pageContainerSplitScreen: {
                        open: false,
                        action: null,
                        type: null,
                        params: null
                    } });
                break;
            case 'OPEN_SPLIT_SCREEN':
                state = Object.assign(Object.assign({}, state), { splitScreen: reducerAction.splitScreen });
                break;
            case 'OPEN_PAGE_SPLIT_SCREEN':
                state = Object.assign(Object.assign({}, state), { pageSplitScreen: reducerAction.pageSplitScreen });
                break;
            case 'OPEN_PAGE_CONTAINER_SPLIT_SCREEN':
                state = Object.assign(Object.assign({}, state), { pageContainerSplitScreen: reducerAction.pageContainerSplitScreen });
                break;
            case 'SET_CATALOG_ENTITIES':
                state = Object.assign(Object.assign({}, state), { catalogEntities: reducerAction.catalogEntities });
                break;
            case 'SET_CATALOG_PROMOTED_ENTITIES':
                state = Object.assign(Object.assign({}, state), { catalogPromotedEntities: reducerAction.catalogPromotedEntities });
                break;
            case 'SET_INQUIRY_PARAMS':
                let initialContainerId = 0;
                if (reducerAction.containerId) {
                    initialContainerId = reducerAction.containerId;
                }
                const updatedInquiryParams = Object.assign({}, state.inquiryParams);
                updatedInquiryParams[initialContainerId] = reducerAction.inquiryParams;
                state = Object.assign(Object.assign({}, state), { inquiryParams: updatedInquiryParams });
                break;
            case 'SET_SHOW_INQUIRY_HEADER_ACTIONS':
                state = Object.assign(Object.assign({}, state), { showInquiryHeaderActions: reducerAction.showInquiryHeaderActions });
                break;
            case 'SET_MENU_LIST_STATE':
                state = Object.assign(Object.assign({}, state), { menuListState: reducerAction.menuListState });
                break;
            case 'SET_ACTION_STATE_FOR_NEW_ROUTE':
                state = Object.assign(Object.assign({}, state), newRouteEmptyAction);
                break;
            default:
                throw new Error(`Unknown action type ${reducerAction.type}`);
        }
        state = Object.assign(Object.assign({}, state), { setCurrentEntityName: setCurrentEntityName });
        return state;
    }, emptyAction);
    const [actionLoadingState, dispatchActionLoading] = useReducer((state, reducerAction) => {
        switch (reducerAction.type) {
            case 'SET_ACTION_LOADING':
                state = Object.assign(Object.assign({}, state), { loading: reducerAction.loading });
                break;
            case 'SET_ACTION_WAITING_TO_EXECUTE':
                state = Object.assign(Object.assign({}, state), { waitingToExecute: reducerAction.actionId });
                break;
            default:
                throw new Error(`Unknown action loading type ${reducerAction.type}`);
        }
        return state;
    }, emptyActionLoading);
    const action = useMemo(() => {
        var _a, _b, _c, _d, _e;
        let selectedAction = null;
        if (actionState) {
            if ((_a = actionState.modal) === null || _a === void 0 ? void 0 : _a.action) {
                selectedAction = actionState.modal.action;
            }
            if ((_b = actionState.sideSheet) === null || _b === void 0 ? void 0 : _b.action) {
                selectedAction = actionState.sideSheet.action;
            }
            if ((_c = actionState.splitScreen) === null || _c === void 0 ? void 0 : _c.action) {
                selectedAction = actionState.splitScreen.action;
            }
            if ((_d = actionState.pageSplitScreen) === null || _d === void 0 ? void 0 : _d.action) {
                selectedAction = actionState.pageSplitScreen.action;
            }
            if ((_e = actionState.pageContainerSplitScreen) === null || _e === void 0 ? void 0 : _e.action) {
                selectedAction = actionState.pageContainerSplitScreen.action;
            }
        }
        return selectedAction;
    }, [actionState]);
    const entityName = useMemo(() => {
        return actionPanel ? actionPanel.entityName : currentEntityName;
    }, [actionPanel, currentEntityName]);
    const [{ data: catalogObject }] = useAxiosGet(ConfigService.integrationV2ApiUrl, `apiCatalog/${apiCatalogId}/catalogObject/${entityName}`, {}, !!!apiCatalogId || !!!entityName, false);
    const entityAttributes = useMemo(() => {
        var _a;
        return (_a = catalogObject === null || catalogObject === void 0 ? void 0 : catalogObject.properties) !== null && _a !== void 0 ? _a : [];
    }, [catalogObject]);
    const { defaultFormValues } = useDefaultFormValues(entityAttributes);
    const [crudTableFormData, setCrudTableFormData] = useState(defaultFormValues);
    const crudTableEditionData = useMemo(() => {
        let crudData = null;
        if ((selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.nodeObj) &&
            action &&
            action.actionTypeId === NodeActionEnums.Update) {
            crudData = selectedNode.nodeObj;
            setCrudTableFormData(selectedNode.nodeObj);
        }
        else {
            setCrudTableFormData(defaultFormValues);
        }
        return crudData;
    }, [action, selectedNode]);
    const executeAction = useCallback(async (data, id) => apiMutate(ConfigService.integrationV1ApiUrl, `apimethod/executeQueryWithParameters/${id}`, {
        method: 'post'
    }, data), []);
    const inquiryActions = (React.createElement(ActionWrapper, { action: action, actionState: actionState, actionPanel: actionPanel, dispatch: dispatch, apiCatalogId: apiCatalogId, executeAction: executeAction, splitScreenBody: children, entityAttributes: entityAttributes, foreignKeyData: foreignKeyData, setForeignKeyData: setForeignKeyData, crudTableEditionData: crudTableEditionData, crudTableFormData: crudTableFormData }));
    useEffect(() => {
        if (tpacb) {
            setApiCatalogId(tpacb.apiCatalogId);
            setCurrentApiCatalogId(tpacb.apiCatalogId);
        }
    }, [tpacb, setCurrentApiCatalogId]);
    useEffect(() => {
        var _a;
        if (action && actionState) {
            setActionPanel((_a = actionState === null || actionState === void 0 ? void 0 : actionState.actionPanels[currentContainerId || 0]) === null || _a === void 0 ? void 0 : _a.find((ap) => ap.panelActions.find((pa) => pa.actionId === action.actionId)));
        }
    }, [action, actionState, currentContainerId]);
    useEffect(() => dispatchActionLoading({
        type: 'SET_ACTION_LOADING',
        loading: tpacbLoading
    }), [tpacbLoading]);
    // listening to route changes to reset specific properties in the action state
    useEffect(() => {
        if (history) {
            return history.listen((location) => {
                if (currentLocationPathname !== location.pathname) {
                    setCurrentLocationPathname(location.pathname);
                    dispatch({
                        type: 'SET_ACTION_STATE_FOR_NEW_ROUTE'
                    });
                }
            });
        }
    }, [history, currentLocationPathname]);
    const actionLoading = useMemo(() => React.createElement(LoadingOverlay, { open: !!actionLoadingState.waitingToExecute }), [actionLoadingState]);
    return (React.createElement(React.Fragment, null, actionLoading, React.createElement(ActionContext.Provider, { value: actionState }, React.createElement(ActionDispatchContext.Provider, { value: dispatch }, React.createElement(ActionLoadingContext.Provider, { value: actionLoadingState }, React.createElement(ActionLoadingDispatchContext.Provider, { value: dispatchActionLoading }, domRoot ? createPortal(inquiryActions, domRoot) : inquiryActions))))));
};
//# sourceMappingURL=ActionProvider.js.map