import * as React from "react";
import { subscriber } from "@applicaster/zapp-react-native-utils/functionUtils";

const subscriberObjects = Object.create({});

interface UseSubscriberFor {
  (
    eventName: string,
    handler?: (...args: unknown[]) => void
  ): (...args: unknown[]) => ReturnType<typeof subscriber>;
}

/**
 * Invoke event.
 **/
export function postEvent(eventName: string, args: unknown[]) {
  subscriberObjects[eventName]?.invokeHandler(eventName, args);
}

/**
 * Subscribes to eventbus and returns unsubscriber to event.
 **/
export const subscriberFor = (
  eventName: string,
  handler?: (...args: unknown[]) => void
) => {
  if (!subscriberObjects[eventName]) {
    subscriberObjects[eventName] = Object.create(null);
  }

  const subManager = subscriber(subscriberObjects[eventName]);

  if (handler) {
    subManager.on?.(eventName, handler);
  }

  return () => subManager?.removeHandler?.(eventName, handler);
};

/**
 * Subscribes to eventbus and returns event emitter to event.
 * returns emitter to invoke event.
 **/
export const useSubscriberFor: UseSubscriberFor = (eventName, handler) => {
  if (!subscriberObjects[eventName]) {
    subscriberObjects[eventName] = Object.create(null);
  }

  const subManager = React.useMemo(
    () => subscriber(subscriberObjects[eventName]),
    []
  );

  React.useEffect(() => {
    if (handler) {
      subManager?.on?.(eventName, handler);

      return () => {
        subManager?.removeHandler?.(eventName, handler);
      };
    }
  }, [handler]);

  return React.useMemo(
    () => subManager?.invokeHandler?.bind(subManager, eventName),
    [subManager, eventName]
  );
};
