import React, { createContext, useCallback, useContext } from 'react';

import { NavElement } from '../types';

/**
 * Represents the globally accessible event tracking callback.
 */
export type OnElementClickType = (
  type: NavElement,
  additionalWork?: (e: React.MouseEvent) => void,
) => (e: React.MouseEvent) => void;

interface OnElementClickProviderProps {
  children: React.ReactNode;
  onElementClick: (type: NavElement, e: React.MouseEvent) => void;
}

const OnElementClickContext = createContext<OnElementClickType>(
  (_navElement: NavElement, additionalWork?: (e: React.MouseEvent) => void) =>
    (e: React.MouseEvent) => {
      return additionalWork?.(e);
    },
);

/**
 * Provides a globally accessible callback (`onElementClick`)
 * to allow users of `MongoNav` to attach a global function to all
 * navigation elements. This is typically used to provide a logging funciton
 * for analytics purposes.
 *
 * `onElementClick` accepts a NavElement string, and a callback.
 * For any navigation element, pass this funciton in as the `onClick` prop,
 * and handle any click handling logic as the callback to `onElementClick`
 *
 * @returns `onEventClick`
 */
export function useOnElementClick() {
  return useContext(OnElementClickContext);
}

export default function OnElementClickProvider({
  children,
  onElementClick,
}: OnElementClickProviderProps) {
  const wrappedOnElementClick = (
    navElement: NavElement,
    additionalWork?: (e: React.MouseEvent) => void,
  ) => {
    return (e: React.MouseEvent) => {
      onElementClick(navElement, e);
      return additionalWork?.(e);
    };
  };

  const callbackWrapper = useCallback(wrappedOnElementClick, [onElementClick]);

  return (
    <OnElementClickContext.Provider value={callbackWrapper}>
      {children}
    </OnElementClickContext.Provider>
  );
}
