"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.VectorVisualization = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
/**
 * Vector Visualization Component
 *
 * Interactive visualization for vector embeddings with dimension reduction
 * and clustering capabilities.
 */
const react_1 = require("react");
const ui_1 = require("../ui");
const icons_1 = require("../icons");
// Import visualization libraries
// Note: These would need to be added to dependencies
const d3 = __importStar(require("d3"));
const tsne_js_1 = require("tsne-js");
const umap_js_1 = require("umap-js");
/**
 * Visualization methods for dimension reduction
 */
var VisualizationMethod;
(function (VisualizationMethod) {
    VisualizationMethod["TSNE"] = "tsne";
    VisualizationMethod["UMAP"] = "umap";
    VisualizationMethod["PCA"] = "pca";
})(VisualizationMethod || (VisualizationMethod = {}));
/**
 * Vector Visualization Component
 */
const VectorVisualization = ({ apiEndpoint = '/api/experience-builder/vector/data', collection, initialData = [], maxPoints = 1000, enableControls = true, enableMultipleMethods = true, enableClustering = true, enableSearch = true, enableDownload = true, height = 500, variant = 'default', }) => {
    // Visualization container ref
    const containerRef = (0, react_1.useRef)(null);
    // State
    const [loading, setLoading] = (0, react_1.useState)(true);
    const [error, setError] = (0, react_1.useState)(null);
    const [data, setData] = (0, react_1.useState)(initialData);
    const [processedData, setProcessedData] = (0, react_1.useState)([]);
    const [activeTab, setActiveTab] = (0, react_1.useState)(0);
    const [visualizationMethod, setVisualizationMethod] = (0, react_1.useState)(VisualizationMethod.TSNE);
    const [pointSize, setPointSize] = (0, react_1.useState)(5);
    const [perplexity, setPerplexity] = (0, react_1.useState)(30);
    const [iterations, setIterations] = (0, react_1.useState)(500);
    const [neighbors, setNeighbors] = (0, react_1.useState)(15);
    const [minDist, setMinDist] = (0, react_1.useState)(0.1);
    const [clusterCount, setClusterCount] = (0, react_1.useState)(5);
    const [showLabels, setShowLabels] = (0, react_1.useState)(true);
    const [showClusters, setShowClusters] = (0, react_1.useState)(true);
    const [searchQuery, setSearchQuery] = (0, react_1.useState)('');
    const [isProcessing, setIsProcessing] = (0, react_1.useState)(false);
    const [zoomLevel, setZoomLevel] = (0, react_1.useState)(1);
    const [selectedPoint, setSelectedPoint] = (0, react_1.useState)(null);
    // Fetch vector data
    const fetchVectorData = (0, react_1.useCallback)(async () => {
        if (initialData.length > 0) {
            setData(initialData);
            setLoading(false);
            return;
        }
        if (!collection) {
            setError('No collection specified');
            setLoading(false);
            return;
        }
        try {
            setLoading(true);
            setError(null);
            const response = await fetch(`${apiEndpoint}/${collection}?limit=${maxPoints}`);
            if (!response.ok) {
                throw new Error(`API error: ${response.status}`);
            }
            const result = await response.json();
            if (result.data && Array.isArray(result.data)) {
                setData(result.data);
            }
            else {
                setError('Invalid data format');
            }
        }
        catch (err) {
            setError(err.message);
        }
        finally {
            setLoading(false);
        }
    }, [apiEndpoint, collection, maxPoints, initialData]);
    // Process data with selected method
    const processData = (0, react_1.useCallback)(() => {
        if (data.length === 0) {
            return;
        }
        setIsProcessing(true);
        try {
            // Extract vector data
            const vectors = data.map(item => item.vector);
            // Reduce dimensions based on selected method
            let reducedVectors = [];
            switch (visualizationMethod) {
                case VisualizationMethod.TSNE:
                    // t-SNE implementation
                    const tsne = new tsne_js_1.TSNE({
                        dim: 2,
                        perplexity,
                        iterations,
                    });
                    tsne.init({
                        data: vectors,
                        type: 'dense',
                    });
                    tsne.run();
                    reducedVectors = tsne.getOutputScaled();
                    break;
                case VisualizationMethod.UMAP:
                    // UMAP implementation
                    const umap = new umap_js_1.UMAP({
                        nComponents: 2,
                        nNeighbors: neighbors,
                        minDist,
                    });
                    reducedVectors = umap.fit(vectors);
                    break;
                case VisualizationMethod.PCA:
                    // Simple PCA implementation (for demonstration)
                    // In a real implementation, use a proper PCA library
                    reducedVectors = simplePCA(vectors, 2);
                    break;
            }
            // Apply clustering if enabled
            let clusters = [];
            if (enableClustering && showClusters) {
                clusters = applyKMeansClustering(reducedVectors, clusterCount);
            }
            else {
                clusters = new Array(reducedVectors.length).fill(0);
            }
            // Combine original data with reduced vectors and clusters
            const processed = data.map((item, index) => ({
                ...item,
                x: reducedVectors[index][0],
                y: reducedVectors[index][1],
                cluster: clusters[index],
            }));
            setProcessedData(processed);
        }
        catch (err) {
            console.error('Error processing data:', err);
            setError(`Error processing data: ${err.message}`);
        }
        finally {
            setIsProcessing(false);
        }
    }, [data, visualizationMethod, perplexity, iterations, neighbors, minDist, enableClustering, showClusters, clusterCount]);
    // Apply visualization to container
    const applyVisualization = (0, react_1.useCallback)(() => {
        if (!containerRef.current || processedData.length === 0) {
            return;
        }
        const container = containerRef.current;
        container.innerHTML = '';
        const width = container.clientWidth;
        const containerHeight = height;
        // Set up D3
        const svg = d3.select(container)
            .append('svg')
            .attr('width', width)
            .attr('height', containerHeight);
        // Create zoom behavior
        const zoom = d3.zoom()
            .scaleExtent([0.1, 10])
            .on('zoom', (event) => {
            g.attr('transform', event.transform);
            setZoomLevel(event.transform.k);
        });
        svg.call(zoom);
        // Create container for zoom
        const g = svg.append('g');
        // Find min/max x,y for scaling
        const xExtent = d3.extent(processedData, d => d.x);
        const yExtent = d3.extent(processedData, d => d.y);
        // Create scales
        const xScale = d3.scaleLinear()
            .domain(xExtent)
            .range([50, width - 50]);
        const yScale = d3.scaleLinear()
            .domain(yExtent)
            .range([50, containerHeight - 50]);
        // Define cluster colors
        const clusterColors = d3.scaleOrdinal()
            .domain([...Array(clusterCount).keys()].map(i => i.toString()))
            .range(d3.schemeCategory10);
        // Filter by search query if provided
        const filteredData = searchQuery
            ? processedData.filter(d => {
                // Check if point data contains the search query
                return d.text?.toLowerCase().includes(searchQuery.toLowerCase()) ||
                    d.label?.toLowerCase().includes(searchQuery.toLowerCase()) ||
                    d.id?.toString().includes(searchQuery);
            })
            : processedData;
        // Draw points
        g.selectAll('circle')
            .data(filteredData)
            .enter()
            .append('circle')
            .attr('cx', d => xScale(d.x))
            .attr('cy', d => yScale(d.y))
            .attr('r', pointSize)
            .attr('fill', d => showClusters ? clusterColors(d.cluster.toString()) : '#1976d2')
            .attr('opacity', 0.7)
            .attr('stroke', '#fff')
            .attr('stroke-width', 0.5)
            .on('mouseover', function (event, d) {
            d3.select(this)
                .attr('r', pointSize * 1.5)
                .attr('stroke-width', 1.5);
            // Show tooltip
            tooltip
                .style('opacity', 1)
                .style('left', `${event.pageX + 10}px`)
                .style('top', `${event.pageY - 10}px`)
                .html(`
            <strong>${d.label || 'Point ' + d.id || ''}</strong><br>
            ${d.text ? `<p>${d.text.substring(0, 100)}${d.text.length > 100 ? '...' : ''}</p>` : ''}
            <span>Cluster: ${d.cluster}</span>
          `);
        })
            .on('mouseout', function () {
            d3.select(this)
                .attr('r', pointSize)
                .attr('stroke-width', 0.5);
            tooltip.style('opacity', 0);
        })
            .on('click', (event, d) => {
            setSelectedPoint(d);
        });
        // Draw labels if enabled
        if (showLabels) {
            g.selectAll('text')
                .data(filteredData)
                .enter()
                .append('text')
                .attr('x', d => xScale(d.x))
                .attr('y', d => yScale(d.y) - pointSize - 2)
                .attr('text-anchor', 'middle')
                .attr('font-size', `${Math.max(8, pointSize)}px`)
                .attr('fill', '#333')
                .text(d => d.label || d.id || '');
        }
        // Create a tooltip
        const tooltip = d3.select(container)
            .append('div')
            .attr('class', 'visualization-tooltip')
            .style('opacity', 0)
            .style('position', 'absolute')
            .style('background', 'white')
            .style('border', '1px solid #ddd')
            .style('border-radius', '4px')
            .style('padding', '8px')
            .style('box-shadow', '0 2px 4px rgba(0,0,0,0.1)')
            .style('pointer-events', 'none')
            .style('z-index', '100');
        // Draw cluster centroids if clustering is enabled
        if (enableClustering && showClusters) {
            // Calculate cluster centroids
            const centroids = [];
            const clusterMap = new Map();
            filteredData.forEach(d => {
                const cluster = d.cluster;
                if (!clusterMap.has(cluster)) {
                    clusterMap.set(cluster, {
                        sumX: 0,
                        sumY: 0,
                        count: 0
                    });
                }
                const clusterData = clusterMap.get(cluster);
                clusterData.sumX += d.x;
                clusterData.sumY += d.y;
                clusterData.count += 1;
            });
            clusterMap.forEach((data, cluster) => {
                if (data.count > 0) {
                    centroids.push({
                        x: data.sumX / data.count,
                        y: data.sumY / data.count,
                        cluster,
                    });
                }
            });
            // Draw centroid markers
            g.selectAll('.centroid')
                .data(centroids)
                .enter()
                .append('circle')
                .attr('class', 'centroid')
                .attr('cx', d => xScale(d.x))
                .attr('cy', d => yScale(d.y))
                .attr('r', pointSize * 2.5)
                .attr('fill', 'none')
                .attr('stroke', d => clusterColors(d.cluster.toString()))
                .attr('stroke-width', 2)
                .attr('stroke-dasharray', '4,2');
            // Draw centroid labels
            g.selectAll('.centroid-label')
                .data(centroids)
                .enter()
                .append('text')
                .attr('class', 'centroid-label')
                .attr('x', d => xScale(d.x))
                .attr('y', d => yScale(d.y) - pointSize * 3)
                .attr('text-anchor', 'middle')
                .attr('font-size', `${Math.max(10, pointSize * 1.2)}px`)
                .attr('font-weight', 'bold')
                .attr('fill', d => clusterColors(d.cluster.toString()))
                .text(d => `Cluster ${d.cluster}`);
        }
        // Draw axes
        g.append('line')
            .attr('x1', xScale(xExtent[0]))
            .attr('y1', yScale(0))
            .attr('x2', xScale(xExtent[1]))
            .attr('y2', yScale(0))
            .attr('stroke', '#ccc')
            .attr('stroke-width', 1)
            .attr('stroke-dasharray', '5,5');
        g.append('line')
            .attr('x1', xScale(0))
            .attr('y1', yScale(yExtent[0]))
            .attr('x2', xScale(0))
            .attr('y2', yScale(yExtent[1]))
            .attr('stroke', '#ccc')
            .attr('stroke-width', 1)
            .attr('stroke-dasharray', '5,5');
    }, [processedData, pointSize, showLabels, showClusters, clusterCount, searchQuery, height]);
    // Initial data load
    (0, react_1.useEffect)(() => {
        fetchVectorData();
    }, [fetchVectorData]);
    // Process data when it changes or visualization method changes
    (0, react_1.useEffect)(() => {
        if (data.length > 0 && !isProcessing) {
            processData();
        }
    }, [data, visualizationMethod, perplexity, iterations, neighbors, minDist, clusterCount, showClusters, processData]);
    // Apply visualization when processed data changes
    (0, react_1.useEffect)(() => {
        if (processedData.length > 0) {
            applyVisualization();
        }
    }, [processedData, pointSize, showLabels, showClusters, applyVisualization]);
    // Re-render visualization when container size changes
    (0, react_1.useEffect)(() => {
        const handleResize = () => {
            if (processedData.length > 0) {
                applyVisualization();
            }
        };
        window.addEventListener('resize', handleResize);
        return () => window.removeEventListener('resize', handleResize);
    }, [processedData, applyVisualization]);
    // Reset zoom
    const handleResetZoom = () => {
        if (containerRef.current) {
            const svg = d3.select(containerRef.current).select('svg');
            svg.transition().duration(750).call(d3.zoom().transform, d3.zoomIdentity);
            setZoomLevel(1);
        }
    };
    // Handle zoom in
    const handleZoomIn = () => {
        if (containerRef.current) {
            const svg = d3.select(containerRef.current).select('svg');
            svg.transition().duration(300).call(d3.zoom().scaleBy, 1.5);
            setZoomLevel(zoomLevel * 1.5);
        }
    };
    // Handle zoom out
    const handleZoomOut = () => {
        if (containerRef.current) {
            const svg = d3.select(containerRef.current).select('svg');
            svg.transition().duration(300).call(d3.zoom().scaleBy, 1 / 1.5);
            setZoomLevel(zoomLevel / 1.5);
        }
    };
    // Export visualization as SVG
    const handleExportSvg = () => {
        if (containerRef.current) {
            const svg = containerRef.current.querySelector('svg');
            if (svg) {
                const svgData = new XMLSerializer().serializeToString(svg);
                const blob = new Blob([svgData], { type: 'image/svg+xml' });
                const url = URL.createObjectURL(blob);
                const link = document.createElement('a');
                link.href = url;
                link.download = `vector-visualization-${collection || 'data'}.svg`;
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
                URL.revokeObjectURL(url);
            }
        }
    };
    // Export data as JSON
    const handleExportJson = () => {
        const dataToExport = processedData.map(d => ({
            id: d.id,
            label: d.label,
            text: d.text,
            x: d.x,
            y: d.y,
            cluster: d.cluster,
        }));
        const blob = new Blob([JSON.stringify(dataToExport, null, 2)], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = `vector-data-${collection || 'data'}.json`;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        URL.revokeObjectURL(url);
    };
    // Handle change in visualization method
    const handleMethodChange = (method) => {
        setVisualizationMethod(method);
    };
    // Handle search query change
    const handleSearch = () => {
        applyVisualization();
    };
    // Render component
    return ((0, jsx_runtime_1.jsx)(ui_1.Card, { variant: variant === 'compact' ? 'outlined' : 'elevation', children: (0, jsx_runtime_1.jsxs)(ui_1.CardContent, { children: [(0, jsx_runtime_1.jsx)(ui_1.Typography, { variant: "h5", gutterBottom: true, children: "Vector Embedding Visualization" }), loading ? ((0, jsx_runtime_1.jsx)(ui_1.Box, { display: "flex", justifyContent: "center", alignItems: "center", height: height, children: (0, jsx_runtime_1.jsx)(ui_1.CircularProgress, {}) })) : error ? ((0, jsx_runtime_1.jsx)(ui_1.Alert, { severity: "error", children: error })) : ((0, jsx_runtime_1.jsxs)(ui_1.Grid, { container: true, spacing: 2, children: [enableControls && ((0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, children: (0, jsx_runtime_1.jsxs)(ui_1.Paper, { variant: "outlined", sx: { p: 2, mb: 2 }, children: [(0, jsx_runtime_1.jsxs)(ui_1.Tabs, { value: activeTab, onChange: (_, value) => setActiveTab(value), variant: "scrollable", scrollButtons: "auto", children: [(0, jsx_runtime_1.jsx)(ui_1.Tab, { label: "Visualization" }), (0, jsx_runtime_1.jsx)(ui_1.Tab, { label: "Dimension Reduction" }), enableClustering && (0, jsx_runtime_1.jsx)(ui_1.Tab, { label: "Clustering" }), enableSearch && (0, jsx_runtime_1.jsx)(ui_1.Tab, { label: "Search & Filter" })] }), (0, jsx_runtime_1.jsxs)(ui_1.Box, { sx: { mt: 2 }, children: [activeTab === 0 && ((0, jsx_runtime_1.jsxs)(ui_1.Grid, { container: true, spacing: 2, alignItems: "center", children: [(0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 4, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, size: "small", children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Point Size" }), (0, jsx_runtime_1.jsx)(ui_1.Slider, { min: 1, max: 20, step: 1, value: pointSize, onChange: (_, value) => setPointSize(value), valueLabelDisplay: "auto" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 4, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Show Labels" }), (0, jsx_runtime_1.jsx)(ui_1.Switch, { checked: showLabels, onChange: (e) => setShowLabels(e.target.checked) })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 4, children: (0, jsx_runtime_1.jsxs)(ui_1.Box, { display: "flex", justifyContent: "flex-end", children: [(0, jsx_runtime_1.jsx)(ui_1.Tooltip, { title: "Zoom In", children: (0, jsx_runtime_1.jsx)(ui_1.IconButton, { onClick: handleZoomIn, size: "small", sx: { mr: 1 }, children: (0, jsx_runtime_1.jsx)(icons_1.ZoomIn, {}) }) }), (0, jsx_runtime_1.jsx)(ui_1.Tooltip, { title: "Zoom Out", children: (0, jsx_runtime_1.jsx)(ui_1.IconButton, { onClick: handleZoomOut, size: "small", sx: { mr: 1 }, children: (0, jsx_runtime_1.jsx)(icons_1.ZoomOut, {}) }) }), (0, jsx_runtime_1.jsx)(ui_1.Tooltip, { title: "Reset Zoom", children: (0, jsx_runtime_1.jsx)(ui_1.IconButton, { onClick: handleResetZoom, size: "small", sx: { mr: 1 }, children: (0, jsx_runtime_1.jsx)(icons_1.ViewComfy, {}) }) }), enableDownload && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ui_1.Tooltip, { title: "Export as SVG", children: (0, jsx_runtime_1.jsx)(ui_1.IconButton, { onClick: handleExportSvg, size: "small", sx: { mr: 1 }, children: (0, jsx_runtime_1.jsx)(icons_1.Download, {}) }) }), (0, jsx_runtime_1.jsx)(ui_1.Tooltip, { title: "Export Data as JSON", children: (0, jsx_runtime_1.jsx)(ui_1.IconButton, { onClick: handleExportJson, size: "small", children: (0, jsx_runtime_1.jsx)(icons_1.Download, {}) }) })] }))] }) })] })), activeTab === 1 && ((0, jsx_runtime_1.jsxs)(ui_1.Grid, { container: true, spacing: 2, children: [enableMultipleMethods && ((0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 4, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, size: "small", children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Reduction Method" }), (0, jsx_runtime_1.jsxs)(ui_1.Select, { value: visualizationMethod, onChange: (e) => handleMethodChange(e.target.value), children: [(0, jsx_runtime_1.jsx)(ui_1.MenuItem, { value: VisualizationMethod.TSNE, children: "t-SNE" }), (0, jsx_runtime_1.jsx)(ui_1.MenuItem, { value: VisualizationMethod.UMAP, children: "UMAP" }), (0, jsx_runtime_1.jsx)(ui_1.MenuItem, { value: VisualizationMethod.PCA, children: "PCA" })] }), (0, jsx_runtime_1.jsx)(ui_1.FormHelperText, { children: "Algorithm for reducing high-dimensional data to 2D" })] }) })), visualizationMethod === VisualizationMethod.TSNE && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 4, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, size: "small", children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Perplexity" }), (0, jsx_runtime_1.jsx)(ui_1.Slider, { min: 5, max: 50, step: 1, value: perplexity, onChange: (_, value) => setPerplexity(value), valueLabelDisplay: "auto" }), (0, jsx_runtime_1.jsx)(ui_1.FormHelperText, { children: "Balance between local and global structure (typical range: 5-50)" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 4, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, size: "small", children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Iterations" }), (0, jsx_runtime_1.jsx)(ui_1.Slider, { min: 100, max: 1000, step: 50, value: iterations, onChange: (_, value) => setIterations(value), valueLabelDisplay: "auto" }), (0, jsx_runtime_1.jsx)(ui_1.FormHelperText, { children: "More iterations give better results but take longer" })] }) })] })), visualizationMethod === VisualizationMethod.UMAP && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 4, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, size: "small", children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Neighbors" }), (0, jsx_runtime_1.jsx)(ui_1.Slider, { min: 2, max: 50, step: 1, value: neighbors, onChange: (_, value) => setNeighbors(value), valueLabelDisplay: "auto" }), (0, jsx_runtime_1.jsx)(ui_1.FormHelperText, { children: "Number of neighbors to consider (typical range: 5-50)" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 4, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, size: "small", children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Minimum Distance" }), (0, jsx_runtime_1.jsx)(ui_1.Slider, { min: 0.01, max: 0.5, step: 0.01, value: minDist, onChange: (_, value) => setMinDist(value), valueLabelDisplay: "auto" }), (0, jsx_runtime_1.jsx)(ui_1.FormHelperText, { children: "Minimum distance between points (typical range: 0.1-0.5)" })] }) })] })), (0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, children: (0, jsx_runtime_1.jsx)(ui_1.Box, { display: "flex", justifyContent: "flex-end", children: (0, jsx_runtime_1.jsx)(ui_1.Button, { variant: "contained", onClick: processData, disabled: isProcessing, startIcon: isProcessing ? (0, jsx_runtime_1.jsx)(ui_1.CircularProgress, { size: 20 }) : (0, jsx_runtime_1.jsx)(icons_1.Refresh, {}), children: isProcessing ? 'Processing...' : 'Reprocess Data' }) }) })] })), activeTab === 2 && enableClustering && ((0, jsx_runtime_1.jsxs)(ui_1.Grid, { container: true, spacing: 2, children: [(0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 6, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, size: "small", children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Show Clusters" }), (0, jsx_runtime_1.jsx)(ui_1.Switch, { checked: showClusters, onChange: (e) => setShowClusters(e.target.checked) }), (0, jsx_runtime_1.jsx)(ui_1.FormHelperText, { children: "Color points by cluster and show cluster centers" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 6, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, size: "small", children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Number of Clusters" }), (0, jsx_runtime_1.jsx)(ui_1.Slider, { min: 2, max: 20, step: 1, value: clusterCount, onChange: (_, value) => setClusterCount(value), valueLabelDisplay: "auto", disabled: !showClusters }), (0, jsx_runtime_1.jsx)(ui_1.FormHelperText, { children: "Number of clusters to identify in the data" })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, children: (0, jsx_runtime_1.jsx)(ui_1.Box, { display: "flex", justifyContent: "flex-end", children: (0, jsx_runtime_1.jsx)(ui_1.Button, { variant: "contained", onClick: processData, disabled: isProcessing || !showClusters, startIcon: isProcessing ? (0, jsx_runtime_1.jsx)(ui_1.CircularProgress, { size: 20 }) : (0, jsx_runtime_1.jsx)(icons_1.Refresh, {}), children: isProcessing ? 'Processing...' : 'Recalculate Clusters' }) }) })] })), activeTab === 3 && enableSearch && ((0, jsx_runtime_1.jsxs)(ui_1.Grid, { container: true, spacing: 2, alignItems: "center", children: [(0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 6, children: (0, jsx_runtime_1.jsxs)(ui_1.FormControl, { fullWidth: true, size: "small", children: [(0, jsx_runtime_1.jsx)(ui_1.FormLabel, { children: "Search" }), (0, jsx_runtime_1.jsx)(ui_1.TextField, { value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search by text or id...", size: "small", fullWidth: true, InputProps: {
                                                                        endAdornment: ((0, jsx_runtime_1.jsx)(ui_1.IconButton, { onClick: handleSearch, size: "small", disabled: searchQuery === '', children: (0, jsx_runtime_1.jsx)(icons_1.Search, {}) })),
                                                                    } })] }) }), (0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 6, children: (0, jsx_runtime_1.jsxs)(ui_1.Box, { display: "flex", justifyContent: "flex-end", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(ui_1.Button, { variant: "outlined", onClick: () => {
                                                                        setSearchQuery('');
                                                                        applyVisualization();
                                                                    }, disabled: searchQuery === '', startIcon: (0, jsx_runtime_1.jsx)(icons_1.FilterList, {}), size: "small", sx: { mr: 1 }, children: "Clear Filters" }), (0, jsx_runtime_1.jsx)(ui_1.Button, { variant: "contained", onClick: handleSearch, disabled: searchQuery === '', startIcon: (0, jsx_runtime_1.jsx)(icons_1.Search, {}), size: "small", children: "Search" })] }) })] }))] })] }) })), (0, jsx_runtime_1.jsxs)(ui_1.Grid, { item: true, xs: 12, sm: selectedPoint ? 8 : 12, children: [(0, jsx_runtime_1.jsx)(ui_1.Box, { ref: containerRef, sx: {
                                        width: '100%',
                                        height,
                                        border: '1px solid #eee',
                                        borderRadius: '4px',
                                        overflow: 'hidden',
                                        position: 'relative',
                                        '& .visualization-tooltip': {
                                            position: 'absolute',
                                            padding: '8px',
                                            background: 'white',
                                            border: '1px solid #ddd',
                                            borderRadius: '4px',
                                            pointerEvents: 'none',
                                            zIndex: 100,
                                        }
                                    } }), isProcessing && ((0, jsx_runtime_1.jsx)(ui_1.Box, { sx: {
                                        position: 'absolute',
                                        top: 0,
                                        left: 0,
                                        right: 0,
                                        bottom: 0,
                                        display: 'flex',
                                        justifyContent: 'center',
                                        alignItems: 'center',
                                        background: 'rgba(255, 255, 255, 0.7)',
                                        zIndex: 10,
                                    }, children: (0, jsx_runtime_1.jsxs)(ui_1.Box, { sx: {
                                            background: 'white',
                                            padding: 3,
                                            borderRadius: 1,
                                            boxShadow: 1,
                                            display: 'flex',
                                            flexDirection: 'column',
                                            alignItems: 'center',
                                        }, children: [(0, jsx_runtime_1.jsx)(ui_1.CircularProgress, { sx: { mb: 2 } }), (0, jsx_runtime_1.jsxs)(ui_1.Typography, { children: ["Processing ", data.length, " vectors with ", visualizationMethod, "..."] })] }) }))] }), selectedPoint && ((0, jsx_runtime_1.jsx)(ui_1.Grid, { item: true, xs: 12, sm: 4, children: (0, jsx_runtime_1.jsxs)(ui_1.Paper, { variant: "outlined", sx: { p: 2, height: '100%', overflow: 'auto' }, children: [(0, jsx_runtime_1.jsxs)(ui_1.Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 2, children: [(0, jsx_runtime_1.jsx)(ui_1.Typography, { variant: "h6", children: selectedPoint.label || `Point ${selectedPoint.id || ''}` }), (0, jsx_runtime_1.jsx)(ui_1.IconButton, { size: "small", onClick: () => setSelectedPoint(null), children: "\u00D7" })] }), (0, jsx_runtime_1.jsxs)(ui_1.Box, { mb: 2, children: [(0, jsx_runtime_1.jsx)(ui_1.Typography, { variant: "subtitle2", gutterBottom: true, children: "Details" }), (0, jsx_runtime_1.jsxs)(ui_1.Typography, { variant: "body2", children: [(0, jsx_runtime_1.jsx)("strong", { children: "Cluster:" }), " ", selectedPoint.cluster] }), (0, jsx_runtime_1.jsxs)(ui_1.Typography, { variant: "body2", children: [(0, jsx_runtime_1.jsx)("strong", { children: "Coordinates:" }), " (", selectedPoint.x.toFixed(2), ", ", selectedPoint.y.toFixed(2), ")"] }), selectedPoint.metadata && ((0, jsx_runtime_1.jsxs)(ui_1.Box, { mt: 1, children: [(0, jsx_runtime_1.jsx)(ui_1.Typography, { variant: "subtitle2", gutterBottom: true, children: "Metadata" }), (0, jsx_runtime_1.jsx)("pre", { style: {
                                                            fontSize: '12px',
                                                            whiteSpace: 'pre-wrap',
                                                            background: '#f5f5f5',
                                                            padding: '8px',
                                                            borderRadius: '4px',
                                                            overflowX: 'auto'
                                                        }, children: JSON.stringify(selectedPoint.metadata, null, 2) })] }))] }), selectedPoint.text && ((0, jsx_runtime_1.jsxs)(ui_1.Box, { children: [(0, jsx_runtime_1.jsx)(ui_1.Typography, { variant: "subtitle2", gutterBottom: true, children: "Content" }), (0, jsx_runtime_1.jsx)(ui_1.Paper, { variant: "outlined", sx: { p: 1, maxHeight: 300, overflow: 'auto' }, children: (0, jsx_runtime_1.jsx)(ui_1.Typography, { variant: "body2", children: selectedPoint.text }) })] }))] }) }))] }))] }) }));
};
exports.VectorVisualization = VectorVisualization;
// Helper function for simple PCA
// Note: This is a very simplified implementation for demonstration
function simplePCA(vectors, components = 2) {
    // For a real implementation, use a proper library
    // This is just a placeholder that returns random projections
    return vectors.map(() => {
        return Array(components).fill(0).map(() => Math.random() * 2 - 1);
    });
}
// Helper function for K-means clustering
// Note: This is a very simplified implementation for demonstration
function applyKMeansClustering(points, k) {
    // For a real implementation, use a proper library
    // This is just a placeholder that returns random cluster assignments
    return points.map(() => Math.floor(Math.random() * k));
}
exports.default = exports.VectorVisualization;
//# sourceMappingURL=index.js.map