import { produce } from "immer";
import { MenuActions } from "../actions/menuActions";
export const initialState = {
    openMenuId: null,
    pendingBlurId: null,
};
/**
 * Algorithm for managing "toggle/blur" race condition
 *
 * When a user clicks the  for an open window it triggers two events which end up in a race.
 * A blur event will close the menu. A toggle event will also close the menu.
 * However, if the blur event arrives *before* the toggle event then the menu would (1) close, (2) toggle back open
 *
 * The algorithm to address this race condition is to instead use three events. These are the two races
 * (1) BLUR_MENU - sets pendingBlurId to the id of the menu
 * (2) TOGGLE_MENU - closes the menu if it is open (true), and clears pendingBlurId
 * (3) CLOSE_IF_PENDING - closes the menu only if pendingBlurId is still set, and clears pendingBlurId
 *
 * (1) TOGGLE_MENU - closes the menu if it is open (pendingBlurId will not be set)
 * (2) BLUR_MENU - sets pendingBlurId to the id of the menu
 * (3) CLOSE_IF_PENDING - menu is already closed. clears pendingBlurId.
 *
 * menuHook() is responsible for triggering each of these events.
 * This algorithm depends on the time delay between BLUR_MENU and CLOSE_IF_PENDING to be long enough that TOGGLE_MENU is assured to trigger.
 */
export const menuReducer = produce((state, action) => {
    MenuActions.match(action, {
        /**
         * If the menu is open then close it. If it's closed then open it.
         */
        TOGGLE_MENU: (id) => {
            state.pendingBlurId = null;
            state.openMenuId = state.openMenuId === id ? null : id;
        },
        /**
         * Opens the menu. If it is already open then state won't actually change.
         */
        OPEN_MENU: (id) => {
            state.pendingBlurId = null;
            state.openMenuId = id;
        },
        /**
         * Closes the menu iff it is open
         */
        CLOSE_MENU: (id) => {
            state.pendingBlurId = null;
            state.openMenuId = state.openMenuId === id ? null : state.openMenuId;
        },
        /**
         * Sets the menu to be pending close
         */
        BLUR_MENU: (id) => {
            state.pendingBlurId = id;
        },
        /**
         * Closes the menu iff it is open and pending close
         */
        CLOSE_MENU_IF_PENDING: (id) => {
            if (state.pendingBlurId === id && state.openMenuId === id)
                state.openMenuId = null;
            state.pendingBlurId = null;
        },
        default: () => state,
    });
}, initialState);
//# sourceMappingURL=menuReducer.js.map