/**
 * @license MIT
 * author: Cube Dev Team
 * @cube-dev/ui-kit v0.0.0-canary-9f08182
 * Released under the MIT license.
 */

import React, { createContext, useCallback, useContext, useEffect, useRef, } from 'react';
const EventBusContext = createContext(null);
/**
 * EventBusProvider provides a global event system for the application.
 *
 * @example
 * ```tsx
 * function App() {
 *   return (
 *     <EventBusProvider>
 *       <YourComponents />
 *     </EventBusProvider>
 *   );
 * }
 * ```
 */
export function EventBusProvider({ children }) {
    const listeners = useRef({});
    const off = useCallback((event, listener) => {
        const eventListeners = listeners.current[event];
        if (eventListeners) {
            listeners.current[event] = eventListeners.filter((l) => l !== listener);
            // Clean up empty event arrays
            if (listeners.current[event].length === 0) {
                delete listeners.current[event];
            }
        }
    }, []);
    const emitSync = useCallback((event, data) => {
        const eventListeners = listeners.current[event];
        if (eventListeners) {
            eventListeners.forEach((listener) => listener(data));
        }
    }, []);
    const emit = useCallback((event, data) => {
        // Use setTimeout to ensure async emission after current render cycle
        setTimeout(() => {
            emitSync(event, data);
        }, 0);
    }, []);
    const on = useCallback((event, listener) => {
        if (!listeners.current[event]) {
            listeners.current[event] = [];
        }
        listeners.current[event].push(listener);
        // Return cleanup function
        return () => {
            off(event, listener);
        };
    }, [off]);
    const contextValue = {
        emit,
        emitSync,
        on,
        off,
    };
    return React.createElement(EventBusContext.Provider, { value: contextValue }, children);
}
/**
 * Hook to access the event bus functionality.
 * Must be used within an EventBusProvider.
 *
 * @example
 * ```tsx
 * function Component() {
 *   const { emit, emitSync, on } = useEventBus();
 *
 *   const handleClick = () => {
 *     emit('user-action', { type: 'click', target: 'button' });
 *   };
 *
 *   const handleSyncAction = () => {
 *     emitSync('sync-action', { immediate: true });
 *   };
 *
 *   useEffect(() => {
 *     const unsubscribe = on('data-updated', (data) => {
 *       console.log('Data updated:', data);
 *     });
 *
 *     return unsubscribe;
 *   }, [on]);
 *
 *   return (
 *     <div>
 *       <button onClick={handleClick}>Async Event</button>
 *       <button onClick={handleSyncAction}>Sync Event</button>
 *     </div>
 *   );
 * }
 * ```
 */
export function useEventBus() {
    const context = useContext(EventBusContext);
    if (!context) {
        throw new Error('useEventBus must be used within an EventBusProvider');
    }
    return context;
}
/**
 * Convenience hook for subscribing to events with automatic cleanup.
 * The listener will be automatically unsubscribed when the component unmounts
 * or when the dependencies change.
 *
 * @param event - The event name to listen for
 * @param listener - The callback function to execute when the event is emitted
 * @param deps - Dependency array for the effect (similar to useEffect)
 *
 * @example
 * ```tsx
 * function NotificationComponent() {
 *   const [message, setMessage] = useState('');
 *
 *   useEventListener('notification', (data) => {
 *     setMessage(data.message);
 *   }, []);
 *
 *   return <div>{message}</div>;
 * }
 * ```
 */
export function useEventListener(event, listener, deps = []) {
    const { on } = useEventBus();
    useEffect(() => {
        const unsubscribe = on(event, listener);
        return unsubscribe;
    }, [event, on, ...deps]);
}

        