import { createContext, type ReactNode, useContext, useMemo } from "react";
import type { PlatformWebModule } from "../types";
import { moduleInstalled, uiCapabilities, uiCapability } from "./modules";
import { useEffectiveView, useViewSurfaces } from "./ViewContext";
import { isViewSurfaceVisible, moduleViewSurfaceId } from "./views";

const PlatformModulesContext = createContext<PlatformWebModule[]>([]);

export function PlatformModulesProvider({ modules, children }: { modules: PlatformWebModule[]; children: ReactNode }) {
  return <PlatformModulesContext.Provider value={modules}>{children}</PlatformModulesContext.Provider>;
}

export function usePlatformModules(): PlatformWebModule[] {
  return useContext(PlatformModulesContext);
}

export function usePlatformModuleInstalled(moduleId: string): boolean {
  return moduleInstalled(moduleId, usePlatformModules());
}

export function usePlatformUiCapability<T = unknown>(capabilityName: string): T | null {
  const modules = useViewVisibleModules();
  return useMemo(
    () => uiCapability<T>(capabilityName, modules),
    [capabilityName, modules]
  );
}

export function usePlatformUiCapabilities<T = unknown>(capabilityName: string): T[] {
  const modules = useViewVisibleModules();
  return useMemo(
    () => uiCapabilities<T>(capabilityName, modules),
    [capabilityName, modules]
  );
}

function useViewVisibleModules(): PlatformWebModule[] {
  const modules = usePlatformModules();
  const projection = useEffectiveView();
  const surfaces = useViewSurfaces();
  return useMemo(
    () =>
      modules.filter((module) =>
        isViewSurfaceVisible(
          projection,
          moduleViewSurfaceId(module.id),
          surfaces
        )
      ),
    [modules, projection, surfaces]
  );
}
