import { useDispatch, useSelector } from "../components/FinsembleProvider";
import { useEffect } from "react";
import { LinkerActions } from "../actions/linkerActions";
import { MAXIMUM_ALLOWED_ACTIVE_CHANNELS } from "../types/linkerTypes";
import { FEAGlobals } from "../../common/Globals";
// Encapsulate the linker initialization and Redux dispatch functions inside the hook
export const useLinker = () => {
    const dispatch = useDispatch();
    const linkerState = useSelector((state) => state.linker);
    const hideWindow = () => {
        // Must blur or you end up having to click twice to show the window.
        // If you just hide, the first time the user clicks
        // on the linker button, the blur will trigger, which will hide the window.
        FEAGlobals.finsembleWindow.blur();
        FEAGlobals.finsembleWindow.hide();
    };
    useEffect(() => {
        const setInitialChannels = () => {
            const channels = FEAGlobals.FSBL.Clients.LinkerClient.getAllChannels();
            dispatch(LinkerActions.SET_CHANNELS({ channels }));
        };
        const focusWindow = () => {
            FEAGlobals.finsembleWindow.focus();
        };
        const initAccessibleLinkerMode = () => {
            const accessibilityCallback = (err, value) => {
                if (err) {
                    FEAGlobals.FSBL.Clients.Logger.system.error(`Failed to get accessibleLinker value: ${err}`);
                    return;
                }
                dispatch(LinkerActions.SET_ACCESSIBILITY({
                    isAccessibleLinker: Boolean(value),
                }));
            };
            FEAGlobals.FSBL.Clients.ConfigClient.get(["finsemble", "accessibleLinker"], accessibilityCallback);
        };
        /** If user switches the linker channel for different components, this function would be invoked. It will dispatch another
         *  action to update the linker's state according to the linker setup on the switched component.
         *
         * @param err  error from FEAGlobals.FSBL
         * @param msg  msg from FEAGlobals.FSBL
         */
        const onActiveChannelsChanged = (err, msg) => {
            const componentLinkerState = FEAGlobals.FSBL.Clients.LinkerClient.getState(msg.data.windowIdentifier);
            if (err) {
                FEAGlobals.FSBL.Clients.Logger.system.error("Failed to update the linker state.");
                return;
            }
            dispatch(LinkerActions.UPDATE_ACTIVE_CHANNELS({
                channelNames: componentLinkerState.channels,
                windowIdentifier: msg.data.windowIdentifier,
            }));
            msg.sendQueryResponse(null, null);
        };
        FEAGlobals.FSBL.Clients.Logger.system.log("Linker component is mounted. Initializing.");
        FEAGlobals.finsembleWindow.addEventListener("blurred", hideWindow);
        FEAGlobals.finsembleWindow.addEventListener("shown", focusWindow);
        setInitialChannels();
        initAccessibleLinkerMode();
        FEAGlobals.FSBL.Clients.RouterClient.addResponder("Finsemble.LinkerWindow.SetActiveChannels", onActiveChannelsChanged);
        return () => {
            FEAGlobals.FSBL.Clients.Logger.system.log("Linker component is unmounted. Cleaning up the event listeners.");
            FEAGlobals.finsembleWindow.removeEventListener("blurred", hideWindow);
            FEAGlobals.finsembleWindow.removeEventListener("shown", focusWindow);
            FEAGlobals.FSBL.Clients.RouterClient.removeResponder("Finsemble.LinkerWindow.SetActiveChannels");
        };
    }, []);
    useEffect(() => {
        FEAGlobals.FSBL.Clients.WindowClient.fitToDOM();
    }, [linkerState]);
    const toggleChannel = (channelId) => {
        const channel = linkerState.channels[channelId];
        if (!channel) {
            FEAGlobals.FSBL.Clients.Logger.system.error("Targeted channel to toggle is not found.");
            return;
        }
        const channelName = channel.name;
        const channelActive = channel.active;
        const { windowIdentifier } = linkerState;
        const updateActivationTo = (isActive) => (err) => {
            if (err) {
                FEAGlobals.FSBL.Clients.Logger.system.error("Error in linkerHook, linkCallback", err);
                return;
            }
            dispatch(LinkerActions.UPDATE_CHANNEL_STATUS({
                channelId,
                active: isActive,
            }));
        };
        // @ts-ignore
        const numberOfActiveChannels = Object.values(linkerState.channels).filter((c) => c === null || c === void 0 ? void 0 : c.active).length;
        // We're activating if the channel is currently inactive
        const activating = !channelActive;
        const deactivating = channelActive;
        const allowedToActivateAnotherChannel = numberOfActiveChannels < MAXIMUM_ALLOWED_ACTIVE_CHANNELS;
        // if we're toggling a channel to be inactive OR
        // we're trying to toggle one to be active AND we have not hit our maximum,
        // let the call go through. Otherwise log an error.
        if (deactivating) {
            FEAGlobals.FSBL.Clients.LinkerClient.unlinkFromChannel(channelName, windowIdentifier, updateActivationTo(false));
        }
        else if (activating && allowedToActivateAnotherChannel) {
            FEAGlobals.FSBL.Clients.LinkerClient.linkToChannel(channelName, windowIdentifier, updateActivationTo(true));
        }
        else {
            FEAGlobals.FSBL.Clients.Logger.system.error(`Attempted to toggle more than ${MAXIMUM_ALLOWED_ACTIVE_CHANNELS} channels. This could result in an unacceptable UX. Please contact finsemble support if you would like to render more than ${MAXIMUM_ALLOWED_ACTIVE_CHANNELS} linker channels in the window title bar.`);
        }
        hideWindow();
    };
    return { state: linkerState, toggleChannel };
};
//# sourceMappingURL=useLinker.js.map