"use client" import React, { useEffect, useRef, useState, useCallback } from 'react' import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Switch } from '@/components/ui/switch' import { Alert, AlertDescription } from '@/components/ui/alert' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Loader2, Cpu, Server, Monitor, Wifi, RotateCcw } from 'lucide-react' import { useToast } from '@/hooks/use-toast' import { EnhancedWebGPUClusteringEngine, RemoteWebGPUClusteringClient } from '@/utils/remote-webgpu-clustering' import { WebRTCGraphViewer } from './webrtc-graph-viewer' import { ForceGraphWrapper } from './force-graph-wrapper' interface PerformanceMetrics { renderingTime: number clusteringTime?: number totalNodes: number totalLinks: number memoryUsage?: number } interface WebGPU3DViewerProps { graphData: { nodes: any[] links: any[] } | null remoteServiceUrl?: string enableClustering?: boolean onClusteringUpdate?: (metrics: PerformanceMetrics) => void onError?: (error: string) => void } interface RenderingMode { id: 'local' | 'hybrid' | 'webrtc' name: string description: string available: boolean recommended?: boolean } export function WebGPU3DViewer({ graphData, remoteServiceUrl = 'http://localhost:8083', enableClustering = true, onClusteringUpdate, onError }: WebGPU3DViewerProps) { const [activeMode, setActiveMode] = useState('local') const [isInitializing, setIsInitializing] = useState(true) const [renderingModes, setRenderingModes] = useState([]) const [clusteringEngine, setClusteringEngine] = useState(null) const [remoteClient, setRemoteClient] = useState(null) const [capabilities, setCapabilities] = useState(null) const { toast } = useToast() // Initialize rendering modes and capabilities useEffect(() => { const initializeCapabilities = async () => { try { setIsInitializing(true) // Initialize enhanced clustering engine const engine = new EnhancedWebGPUClusteringEngine([32, 18, 24], remoteServiceUrl) await new Promise(resolve => setTimeout(resolve, 200)) // Give time to initialize // Initialize remote client for WebRTC capabilities const client = new RemoteWebGPUClusteringClient(remoteServiceUrl, false) // Disable proxy mode for WebSocket const remoteAvailable = await client.checkAvailability() const remoteCaps = client.getCapabilities() setClusteringEngine(engine) if (remoteAvailable) { console.log('Remote client available, setting client state') setRemoteClient(client) setCapabilities(remoteCaps) } else { console.log('Remote client not available') setRemoteClient(null) setCapabilities(null) } // Determine available rendering modes const modes: RenderingMode[] = [ { id: 'local', name: 'Local WebGPU', description: 'Client-side WebGPU clustering and Three.js rendering', available: Boolean(engine.isAvailable() && !engine.isUsingRemote()), recommended: Boolean(engine.isAvailable() && !engine.isUsingRemote()) }, { id: 'hybrid', name: 'Hybrid GPU/CPU', description: 'Server GPU clustering, client CPU rendering', available: Boolean(remoteAvailable && remoteCaps?.modes?.hybrid?.available), recommended: Boolean(!engine.isAvailable() || engine.isUsingRemote()) }, { id: 'webrtc', name: 'WebRTC Streaming', description: 'Full server GPU rendering streamed to browser', available: Boolean(remoteAvailable && remoteCaps?.modes?.webrtc_stream?.available) } ] setRenderingModes(modes) // Auto-select best available mode const recommendedMode = modes.find(m => m.recommended && m.available) const fallbackMode = modes.find(m => m.available) if (recommendedMode) { setActiveMode(recommendedMode.id) toast({ title: "Rendering Mode Selected", description: `Using ${recommendedMode.name} for optimal performance`, }) } else if (fallbackMode) { setActiveMode(fallbackMode.id) toast({ title: "Fallback Mode", description: `Using ${fallbackMode.name} as fallback`, variant: "destructive" }) } else { onError?.('No rendering modes available') } } catch (error) { console.error('Failed to initialize 3D viewer capabilities:', error) onError?.(`Initialization failed: ${error}`) } finally { setIsInitializing(false) } } initializeCapabilities() return () => { if (clusteringEngine) { clusteringEngine.dispose() } if (remoteClient) { remoteClient.dispose() } } }, [remoteServiceUrl]) // Handle clustering updates and performance metrics useEffect(() => { if (graphData && onClusteringUpdate) { const startTime = performance.now() // Simulate clustering time for performance metrics // In a real implementation, this would come from the actual clustering engine const nodeCount = graphData.nodes?.length || 0 const linkCount = graphData.links?.length || 0 if (nodeCount > 0) { // Simulate clustering processing time based on node count const clusteringTime = enableClustering ? Math.max(10, nodeCount * 0.01) : 0 const renderingTime = performance.now() - startTime setTimeout(() => { onClusteringUpdate({ renderingTime, clusteringTime, totalNodes: nodeCount, totalLinks: linkCount, }) }, clusteringTime) } } }, [graphData, enableClustering, onClusteringUpdate]) // Handle mode change const handleModeChange = useCallback((mode: string) => { const selectedMode = renderingModes.find(m => m.id === mode) if (selectedMode && selectedMode.available) { setActiveMode(mode) toast({ title: "Rendering Mode Changed", description: `Switched to ${selectedMode.name}`, }) } }, [renderingModes]) if (isInitializing) { return ( Initializing 3D GPU Viewer

Detecting WebGPU capabilities and remote services...

) } if (renderingModes.length === 0 || !renderingModes.some(m => m.available)) { return ( No Rendering Options Available Neither local WebGPU nor remote GPU services are available. Please ensure WebGPU is supported in your browser or that the remote service is running. ) } return (
{/* Rendering Mode Tabs */} {renderingModes.map((mode) => ( {mode.id === 'local' && } {mode.id === 'hybrid' && } {mode.id === 'webrtc' && } {mode.name} ))} {/* Local WebGPU Mode */} Local WebGPU Clustering + Three.js Rendering Uses your browser's WebGPU for clustering and Three.js for 3D rendering {clusteringEngine && !clusteringEngine.isUsingRemote() ? (
Local WebGPU is available. This provides the best performance with no network latency. {/* Clustering Controls */}
{ // Handle clustering toggle if (onClusteringUpdate && graphData) { const nodeCount = graphData.nodes?.length || 0 const linkCount = graphData.links?.length || 0 onClusteringUpdate({ renderingTime: performance.now() % 100, clusteringTime: checked ? Math.max(10, nodeCount * 0.01) : 0, totalNodes: nodeCount, totalLinks: linkCount, }) } }} />
{enableClustering ? "Enabled" : "Disabled"}
{/* Standard 3D Force Graph */}
{graphData ? ( onError?.(err.message)} /> ) : (

No graph data available

Load graph data to see WebGPU clustering
)}
) : ( Local WebGPU is not available in this browser or environment. )}
{/* Hybrid Mode */} Hybrid GPU/CPU Rendering Server performs GPU clustering, client handles CPU-based Three.js rendering {remoteClient ? (
Remote GPU clustering is available. Clustering will be performed on the server GPU, with results sent to your browser for 3D rendering. {/* Clustering Controls */}
{ // Handle clustering toggle if (onClusteringUpdate && graphData) { const nodeCount = graphData.nodes?.length || 0 const linkCount = graphData.links?.length || 0 onClusteringUpdate({ renderingTime: performance.now() % 100, clusteringTime: checked ? Math.max(15, nodeCount * 0.02) : 0, totalNodes: nodeCount, totalLinks: linkCount, }) } }} />
{enableClustering ? "Server GPU" : "Disabled"}
{/* Enhanced ForceGraphWrapper with remote GPU clustering */}
{graphData ? ( onError?.(err.message)} /> ) : (

No graph data available

Load graph data to see hybrid GPU clustering
)}
) : ( Remote GPU clustering service is not available. )}
{/* WebRTC Streaming Mode */}
{/* Service Status */} {capabilities && ( Service Status

Local WebGPU

{clusteringEngine?.isAvailable() && !clusteringEngine?.isUsingRemote() ? 'Available' : 'Not Available'}

Remote Service

{remoteClient ? 'Connected' : 'Disconnected'}

Server GPU

{capabilities?.gpuAcceleration?.rapidsAvailable ? 'RAPIDS' : 'CPU Only'}

WebRTC

{capabilities?.modes?.webrtc_stream?.available ? 'Available' : 'Not Available'}
{capabilities && (

Cluster dimensions: {capabilities.clusterDimensions?.join(' × ')} ({capabilities.maxClusterCount?.toLocaleString()} total clusters)

)}
)}
) }