import React, {createContext, useCallback, useContext, useRef} from 'react';
import {ExtendedMessage} from '@modules/chats/interfaces';

import type {ViewToken} from '@legendapp/list/react-native';

type ViewPortValue = ViewToken<ExtendedMessage>[];
type ViewPortListener = (value: ViewPortValue) => void;

interface ViewPortContextType {
  getViewPort: () => ViewPortValue;
  subscribe: (listener: ViewPortListener) => () => void;
}

type ViewPortSetterContextType = (value: ViewPortValue) => void;

const ViewPortContextSetter = createContext<ViewPortSetterContextType>(
  () => null,
);

const ViewPortContext = createContext<ViewPortContextType>({
  getViewPort: () => [],
  subscribe: () => () => {},
});

export const useViewPortSetter = () => useContext(ViewPortContextSetter);
export const useViewPort = () => useContext(ViewPortContext);

export const ViewPortProvider: React.FC<{children: React.ReactNode}> = ({
  children,
}) => {
  const viewPortRef = useRef<ViewPortValue>([]);
  const listenersRef = useRef<Set<ViewPortListener>>(new Set());

  const setViewPort = useCallback((value: ViewPortValue) => {
    viewPortRef.current = value;
    listenersRef.current.forEach(listener => listener(value));
  }, []);

  const contextValue = useRef<ViewPortContextType>({
    getViewPort: () => viewPortRef.current,
    subscribe: (listener: ViewPortListener) => {
      listenersRef.current.add(listener);
      return () => {
        listenersRef.current.delete(listener);
      };
    },
  }).current;

  return (
    <ViewPortContextSetter.Provider value={setViewPort}>
      <ViewPortContext.Provider value={contextValue}>
        {children}
      </ViewPortContext.Provider>
    </ViewPortContextSetter.Provider>
  );
};
