import React, {
  useState,
  useEffect,
  useCallback,
  useMemo,
  useRef,
} from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";

import { Eye, EyeOff, Split, Layers } from "lucide-react";
import { LoadingSpinner } from "@/components/shared/LoadingSpinner";
import { api } from "@/lib/api";
import {
  AvailableGraph,
  GraphComparisonResults,
  UniversalGraphData,
  GraphDetailsResponse,
} from "@/types";
import { getGraphDataAdapter } from "@/lib/graph-data-adapters";
import { CytoscapeGraphCore } from "@/lib/cytoscape-graph-core";
import { createKnowledgeGraphConfig } from "@/lib/graph-config-factory";
import { GraphSelectionCallbacks } from "@/types/graph-visualization";

const truncateGraphName = (
  name: string,
  maxLength: number = 30
): string => {
  if (!name) return "";
  if (name.length <= maxLength) return name;
  const start = name.substring(0, Math.floor(maxLength * 0.6));
  const end = name.substring(name.length - Math.floor(maxLength * 0.3));
  return `${start}...${end}`;
};

// Prefer human-friendly system name where available
const getGraphDisplayName = (graph?: AvailableGraph | null) => {
  if (!graph) return "";
  return graph.system_name && graph.system_name.trim().length > 0
    ? graph.system_name
    : graph.filename;
};

interface VisualComparisonProps {
  graph1: AvailableGraph;
  graph2: AvailableGraph;
  comparisonResults?: GraphComparisonResults | null;
}

interface MergedGraphData extends UniversalGraphData {
  mergeStats: {
    totalNodes: number;
    totalLinks: number;
    commonNodes: number;
    commonLinks: number;
    graph1UniqueNodes: number;
    graph1UniqueLinks: number;
    graph2UniqueNodes: number;
    graph2UniqueLinks: number;
  };
}

// Component wrapper for CytoscapeGraphCore
const CytoscapeWrapper: React.FC<{
  data: UniversalGraphData;
  width?: number;
  height?: number;
}> = ({ data, width = 800, height = 600 }) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const cytoscapeRef = useRef<CytoscapeGraphCore | null>(null);
  const [isInitialized, setIsInitialized] = useState(false);

  useEffect(() => {
    const initializeVisualization = async () => {
      if (!containerRef.current || !data || data.nodes.length === 0) return;

      try {
        // Wait for layout to settle
        await new Promise((resolve) => setTimeout(resolve, 100));

        const config = createKnowledgeGraphConfig({
          width,
          height,
          showToolbar: false,
          showSidebar: false,
          showStats: false,
          enableSearch: false,
          enableZoom: true,
          enablePan: true,
          enableDrag: true,
          enableSelection: true,
        });

        const selectionCallbacks: GraphSelectionCallbacks = {
          onNodeSelect: (node) => {
            console.log("Node selected:", node);
          },
          onLinkSelect: (link) => {
            console.log("Link selected:", link);
          },
          onClearSelection: () => {
            console.log("Selection cleared");
          },
        };

        // Clean up existing instance
        if (cytoscapeRef.current) {
          cytoscapeRef.current.destroy();
          cytoscapeRef.current = null;
        }

        cytoscapeRef.current = new CytoscapeGraphCore(
          containerRef.current,
          config,
          selectionCallbacks
        );

        cytoscapeRef.current.updateGraph(data, true);
        setIsInitialized(true);
      } catch (err) {
        console.error("Error initializing Cytoscape visualization:", err);
      }
    };

    initializeVisualization();

    return () => {
      if (cytoscapeRef.current) {
        cytoscapeRef.current.destroy();
        cytoscapeRef.current = null;
      }
      setIsInitialized(false);
    };
  }, [data, width, height]);

  return (
    <div
      ref={containerRef}
      className="w-full h-full bg-white border rounded-lg relative overflow-hidden"
      style={{ minHeight: `${height}px` }}
    >
      {!isInitialized && (
        <div className="absolute inset-0 flex items-center justify-center">
          <LoadingSpinner size="sm" />
        </div>
      )}
    </div>
  );
};

export const VisualComparison: React.FC<VisualComparisonProps> = ({
  graph1,
  graph2,
  comparisonResults,
}) => {
  const [graph1Data, setGraph1Data] = useState<UniversalGraphData | null>(null);
  const [graph2Data, setGraph2Data] = useState<UniversalGraphData | null>(null);
  const [mergedData, setMergedData] = useState<MergedGraphData | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [viewMode, setViewMode] = useState<"side-by-side" | "overlay">(
    "side-by-side"
  );
  const [highlightMode, setHighlightMode] = useState<
    "none" | "common" | "unique"
  >("none");

  // Function to merge two graphs for overlay visualization
  const mergeGraphsForOverlay = useCallback(
    (
      graph1Data: UniversalGraphData,
      graph2Data: UniversalGraphData
    ): MergedGraphData => {
      const entityMap = new Map<string, any>();
      const relationMap = new Map<string, any>();

      // Add graph1 entities
      graph1Data.nodes.forEach((entity) => {
        const key = `${entity.type || "unknown"}:${
          entity.label || entity.name || entity.id
        }`.toLowerCase();
        if (!entityMap.has(key)) {
          entityMap.set(key, {
            ...entity,
            id: `merged-${entity.id}`,
            originalId: entity.id,
            source: "graph1",
            isCommon: false,
            graphSource: "graph1",
          });
        }
      });

      // Add graph2 entities and mark common ones
      graph2Data.nodes.forEach((entity) => {
        const key = `${entity.type || "unknown"}:${
          entity.label || entity.name || entity.id
        }`.toLowerCase();
        if (entityMap.has(key)) {
          const existing = entityMap.get(key);
          existing.isCommon = true;
          existing.source = "common";
          existing.graphSource = "common";
        } else {
          entityMap.set(key, {
            ...entity,
            id: `merged-${entity.id}`,
            originalId: entity.id,
            source: "graph2",
            isCommon: false,
            graphSource: "graph2",
          });
        }
      });

      const allEntities = Array.from(entityMap.values());

      // Create mapping from original IDs to merged entities
      const originalToMergedMap = new Map<string, any>();
      allEntities.forEach((entity) => {
        originalToMergedMap.set(entity.originalId, entity);
      });

      // Add graph1 relations
      graph1Data.links.forEach((relation) => {
        const sourceId =
          typeof relation.source === "string"
            ? relation.source
            : relation.source.id;
        const targetId =
          typeof relation.target === "string"
            ? relation.target
            : relation.target.id;

        const sourceEntity = originalToMergedMap.get(sourceId);
        const targetEntity = originalToMergedMap.get(targetId);

        if (sourceEntity && targetEntity) {
          const key = `${relation.type || relation.label || "unknown"}:${
            sourceEntity.label
          }:${targetEntity.label}`.toLowerCase();
          if (!relationMap.has(key)) {
            relationMap.set(key, {
              ...relation,
              id: `merged-${relation.id}`,
              originalId: relation.id,
              source: sourceEntity.id,
              target: targetEntity.id,
              graphSource: "graph1",
              isCommon: false,
            });
          }
        }
      });

      // Add graph2 relations and mark common ones
      graph2Data.links.forEach((relation) => {
        const sourceId =
          typeof relation.source === "string"
            ? relation.source
            : relation.source.id;
        const targetId =
          typeof relation.target === "string"
            ? relation.target
            : relation.target.id;

        const sourceEntity = originalToMergedMap.get(sourceId);
        const targetEntity = originalToMergedMap.get(targetId);

        if (sourceEntity && targetEntity) {
          const key = `${relation.type || relation.label || "unknown"}:${
            sourceEntity.label
          }:${targetEntity.label}`.toLowerCase();
          if (relationMap.has(key)) {
            const existing = relationMap.get(key);
            existing.isCommon = true;
            existing.graphSource = "common";
          } else {
            relationMap.set(key, {
              ...relation,
              id: `merged-${relation.id}`,
              originalId: relation.id,
              source: sourceEntity.id,
              target: targetEntity.id,
              graphSource: "graph2",
              isCommon: false,
            });
          }
        }
      });

      const allRelations = Array.from(relationMap.values());

      // Calculate statistics
      const commonNodes = allEntities.filter((e) => e.isCommon).length;
      const graph1UniqueNodes = allEntities.filter(
        (e) => e.graphSource === "graph1"
      ).length;
      const graph2UniqueNodes = allEntities.filter(
        (e) => e.graphSource === "graph2"
      ).length;
      const commonLinks = allRelations.filter((r) => r.isCommon).length;
      const graph1UniqueLinks = allRelations.filter(
        (r) => r.graphSource === "graph1"
      ).length;
      const graph2UniqueLinks = allRelations.filter(
        (r) => r.graphSource === "graph2"
      ).length;

      return {
        nodes: allEntities,
        links: allRelations,
        metadata: {
          ...graph1Data.metadata,
          merged: true,
          graph1Name: getGraphDisplayName(graph1),
          graph2Name: getGraphDisplayName(graph2),
        },
        mergeStats: {
          totalNodes: allEntities.length,
          totalLinks: allRelations.length,
          commonNodes,
          commonLinks,
          graph1UniqueNodes,
          graph1UniqueLinks,
          graph2UniqueNodes,
          graph2UniqueLinks,
        },
      };
    },
    [graph1.filename, graph2.filename, graph1.system_name, graph2.system_name]
  );

  // Function to apply overlay coloring based on element source
  const applyOverlayColoring = useCallback(
    (data: MergedGraphData, mode: string): UniversalGraphData => {
      return {
        ...data,
        nodes: data.nodes.map((node) => ({
          ...node,
          color: getOverlayNodeColor(node, mode),
        })),
        links: data.links.map((link) => ({
          ...link,
          color: getOverlayLinkColor(link, mode),
        })),
      };
    },
    []
  );

  const getOverlayNodeColor = (node: any, mode: string): string => {
    if (mode === "none") return "#4f46e5"; // Default blue

    if (node.isCommon) {
      return mode === "common" ? "#22c55e" : "#94a3b8"; // Green for common, gray when highlighting unique
    } else {
      if (mode === "unique") {
        return node.graphSource === "graph1" ? "#3b82f6" : "#f59e0b"; // Blue for graph1, orange for graph2
      } else {
        return "#94a3b8"; // Gray when highlighting common
      }
    }
  };

  const getOverlayLinkColor = (link: any, mode: string): string => {
    if (mode === "none") return "#64748b"; // Default gray

    if (link.isCommon) {
      return mode === "common" ? "#22c55e" : "#94a3b8";
    } else {
      if (mode === "unique") {
        return link.graphSource === "graph1" ? "#3b82f6" : "#f59e0b";
      } else {
        return "#94a3b8";
      }
    }
  };

  const loadGraphData = useCallback(async () => {
    try {
      setIsLoading(true);
      setError(null);

      const [data1, data2] = (await Promise.all([
        api.graphComparison.getGraphDetails(graph1.id),
        api.graphComparison.getGraphDetails(graph2.id),
      ])) as [GraphDetailsResponse, GraphDetailsResponse];

      // Convert to UniversalGraphData format using auto-detecting adapters
      const adapter1 = getGraphDataAdapter(undefined, data1);
      const adapter2 = getGraphDataAdapter(undefined, data2);

      const universalData1 = adapter1.adapt(data1);
      const universalData2 = adapter2.adapt(data2);

      console.log("VisualComparison: Graph data loaded successfully", {
        graph1: {
          nodes: universalData1.nodes.length,
          links: universalData1.links.length,
        },
        graph2: {
          nodes: universalData2.nodes.length,
          links: universalData2.links.length,
        },
      });

      setGraph1Data(universalData1);
      setGraph2Data(universalData2);

      // Create merged data for overlay
      const merged = mergeGraphsForOverlay(universalData1, universalData2);
      setMergedData(merged);

      console.log("VisualComparison: Merged data created", {
        totalNodes: merged.mergeStats.totalNodes,
        totalLinks: merged.mergeStats.totalLinks,
        commonNodes: merged.mergeStats.commonNodes,
        commonLinks: merged.mergeStats.commonLinks,
      });
    } catch (err) {
      setError(
        err instanceof Error ? err.message : "Failed to load graph data"
      );
    } finally {
      setIsLoading(false);
    }
  }, [graph1.id, graph2.id, mergeGraphsForOverlay]);

  useEffect(() => {
    // Add a small delay to ensure the layout has settled before loading data
    const timer = setTimeout(loadGraphData, 100);
    return () => clearTimeout(timer);
  }, [loadGraphData]);

  // Define getHighlightedData before using it in useMemo hooks
  const getHighlightedData = useCallback(
    (
      originalData: UniversalGraphData,
      otherData: UniversalGraphData,
      mode: string
    ): UniversalGraphData => {
      if (mode === "none") return originalData;

      // Compare nodes by label (normalized)
      const otherNodeLabels = new Set(
        otherData.nodes.map((n) =>
          (n.label || n.name || n.id || "").toLowerCase()
        )
      );

      // Compare links by normalized source label, link label, and target label
      const otherLinkKeys = new Set(
        otherData.links.map((link) => {
          const sourceId =
            typeof link.source === "string" ? link.source : link.source.id;
          const targetId =
            typeof link.target === "string" ? link.target : link.target.id;

          // Find the actual node labels for source and target
          const sourceNode = otherData.nodes.find((n) => n.id === sourceId);
          const targetNode = otherData.nodes.find((n) => n.id === targetId);

          const sourceLabel = (
            sourceNode?.label ||
            sourceNode?.name ||
            sourceId ||
            ""
          ).toLowerCase();
          const targetLabel = (
            targetNode?.label ||
            targetNode?.name ||
            targetId ||
            ""
          ).toLowerCase();
          const linkLabel = (link.label || link.type || "").toLowerCase();

          return `${sourceLabel}-${linkLabel}-${targetLabel}`;
        })
      );

      return {
        ...originalData,
        nodes: originalData.nodes.map((node) => {
          const nodeLabel = (
            node.label ||
            node.name ||
            node.id ||
            ""
          ).toLowerCase();
          const isCommon = otherNodeLabels.has(nodeLabel);

          return {
            ...node,
            color:
              mode === "common"
                ? isCommon
                  ? "#22c55e"
                  : "#94a3b8"
                : isCommon
                ? "#94a3b8"
                : "#3b82f6",
          };
        }),
        links: originalData.links.map((link) => {
          const sourceId =
            typeof link.source === "string" ? link.source : link.source.id;
          const targetId =
            typeof link.target === "string" ? link.target : link.target.id;

          // Find the actual node labels for source and target
          const sourceNode = originalData.nodes.find((n) => n.id === sourceId);
          const targetNode = originalData.nodes.find((n) => n.id === targetId);

          const sourceLabel = (
            sourceNode?.label ||
            sourceNode?.name ||
            sourceId ||
            ""
          ).toLowerCase();
          const targetLabel = (
            targetNode?.label ||
            targetNode?.name ||
            targetId ||
            ""
          ).toLowerCase();
          const linkLabel = (link.label || link.type || "").toLowerCase();

          const linkKey = `${sourceLabel}-${linkLabel}-${targetLabel}`;
          const isCommon = otherLinkKeys.has(linkKey);

          return {
            ...link,
            color:
              mode === "common"
                ? isCommon
                  ? "#22c55e"
                  : "#94a3b8"
                : isCommon
                ? "#94a3b8"
                : "#3b82f6",
          };
        }),
      };
    },
    []
  );

  // Memoize highlighted data to prevent unnecessary re-renders
  const highlightedGraph1Data = useMemo(() => {
    if (!graph1Data || !graph2Data) return graph1Data;
    return getHighlightedData(graph1Data, graph2Data, highlightMode);
  }, [graph1Data, graph2Data, highlightMode, getHighlightedData]);

  const highlightedGraph2Data = useMemo(() => {
    if (!graph1Data || !graph2Data) return graph2Data;
    return getHighlightedData(graph2Data, graph1Data, highlightMode);
  }, [graph1Data, graph2Data, highlightMode, getHighlightedData]);

  const overlayData = useMemo(() => {
    if (!mergedData) return null;
    return applyOverlayColoring(mergedData, highlightMode);
  }, [mergedData, highlightMode, applyOverlayColoring]);

  if (isLoading) {
    return (
      <div className="flex items-center justify-center h-64">
        <LoadingSpinner size="lg" />
      </div>
    );
  }

  if (error) {
    return (
      <Card className="m-4">
        <CardContent className="p-8 text-center">
          <p className="text-destructive">{error}</p>
          <Button onClick={loadGraphData} className="mt-4">
            Retry
          </Button>
        </CardContent>
      </Card>
    );
  }

  if (!graph1Data || !graph2Data) {
    return (
      <Card className="m-4">
        <CardContent className="p-8 text-center">
          <p className="text-muted-foreground">No graph data available</p>
        </CardContent>
      </Card>
    );
  }

  return (
    <div className="h-full flex flex-col">
      {/* Controls */}
      <div className="border-b p-4 bg-background">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-4">
            <div className="flex items-center gap-2">
              <span className="text-sm font-medium">View:</span>
              <Button
                variant={viewMode === "side-by-side" ? "default" : "outline"}
                size="sm"
                onClick={() => setViewMode("side-by-side")}
              >
                <Split className="h-4 w-4 mr-1" />
                Side by Side
              </Button>
              <Button
                variant={viewMode === "overlay" ? "default" : "outline"}
                size="sm"
                onClick={() => setViewMode("overlay")}
              >
                <Layers className="h-4 w-4 mr-1" />
                Overlay
              </Button>
            </div>

            <div className="flex items-center gap-2">
              <span className="text-sm font-medium">Highlight:</span>
              <Button
                variant={highlightMode === "none" ? "default" : "outline"}
                size="sm"
                onClick={() => setHighlightMode("none")}
                className="transition-all duration-200"
              >
                <EyeOff className="h-4 w-4 mr-1" />
                None
              </Button>
              <Button
                variant={highlightMode === "common" ? "default" : "outline"}
                size="sm"
                onClick={() => setHighlightMode("common")}
                className="transition-all duration-200"
              >
                <Eye className="h-4 w-4 mr-1" />
                Common
              </Button>
              <Button
                variant={highlightMode === "unique" ? "default" : "outline"}
                size="sm"
                onClick={() => setHighlightMode("unique")}
                className="transition-all duration-200"
              >
                <Eye className="h-4 w-4 mr-1" />
                Unique
              </Button>
            </div>
          </div>

          {comparisonResults && comparisonResults.overall_metrics && (
            <Badge variant="secondary">
              {(
                comparisonResults.overall_metrics.overall_similarity * 100
              ).toFixed(1)}
              % Similar
            </Badge>
          )}
        </div>
      </div>

      {/* Visualization */}
      <div className="flex-1 overflow-hidden">
        {viewMode === "side-by-side" ? (
          <div className="h-full grid grid-cols-2 gap-4 p-4">
            {/* Graph 1 */}
            <Card className="h-full">
              <CardHeader className="pb-2">
                <CardTitle className="text-base flex items-start justify-between gap-2">
                  <span
                    title={getGraphDisplayName(graph1)}
                    className="min-w-0 flex-1 whitespace-normal break-words"
                  >
                    {getGraphDisplayName(graph1)}
                  </span>
                  <div className="flex gap-1 flex-shrink-0">
                    <Badge variant="outline" className="text-xs">
                      {graph1Data.nodes.length} nodes
                    </Badge>
                    <Badge variant="outline" className="text-xs">
                      {graph1Data.links.length} links
                    </Badge>
                  </div>
                </CardTitle>
              </CardHeader>
              <CardContent className="h-full p-2">
                <div className="h-full" style={{ minHeight: "650px" }}>
                  {highlightedGraph1Data && (
                    <CytoscapeWrapper
                      data={highlightedGraph1Data}
                      width={400} // Adjust width for side-by-side
                      height={650}
                    />
                  )}
                </div>
              </CardContent>
            </Card>

            {/* Graph 2 */}
            <Card className="h-full">
              <CardHeader className="pb-2">
                <CardTitle className="text-base flex items-start justify-between gap-2">
                  <span
                    title={getGraphDisplayName(graph2)}
                    className="min-w-0 flex-1 whitespace-normal break-words"
                  >
                    {getGraphDisplayName(graph2)}
                  </span>
                  <div className="flex gap-1 flex-shrink-0">
                    <Badge variant="outline" className="text-xs">
                      {graph2Data.nodes.length} nodes
                    </Badge>
                    <Badge variant="outline" className="text-xs">
                      {graph2Data.links.length} links
                    </Badge>
                  </div>
                </CardTitle>
              </CardHeader>
              <CardContent className="h-full p-2">
                <div className="h-full" style={{ minHeight: "650px" }}>
                  {highlightedGraph2Data && (
                    <CytoscapeWrapper
                      data={highlightedGraph2Data}
                      width={400} // Adjust width for side-by-side
                      height={650}
                    />
                  )}
                </div>
              </CardContent>
            </Card>
          </div>
        ) : (
          <div className="h-full p-2">
            <Card className="h-full">
              <CardHeader className="pb-2">
                <CardTitle className="text-base flex items-start justify-between gap-2">
                  <span
                    title={`${getGraphDisplayName(graph1)} + ${getGraphDisplayName(graph2)}`}
                    className="min-w-0 flex-1 whitespace-normal break-words"
                  >
                    Overlay Comparison
                  </span>
                  {mergedData && (
                    <div className="flex gap-1 flex-shrink-0">
                      <Badge variant="outline" className="text-xs">
                        {mergedData.mergeStats.totalNodes} nodes
                      </Badge>
                      <Badge variant="outline" className="text-xs">
                        {mergedData.mergeStats.totalLinks} links
                      </Badge>
                    </div>
                  )}
                </CardTitle>
              </CardHeader>

              <CardContent className="h-full p-1">
                {overlayData ? (
                  <div className="h-full" style={{ minHeight: "750px" }}>
                    <CytoscapeWrapper
                      data={overlayData}
                      width={800} // Full width for overlay
                      height={750}
                    />
                  </div>
                ) : (
                  <div className="flex items-center justify-center h-64">
                    <LoadingSpinner size="lg" />
                  </div>
                )}
              </CardContent>
            </Card>
          </div>
        )}
      </div>

      {/* Legend */}
      {highlightMode !== "none" && (
        <div className="border-t p-4 bg-muted/50 transition-all duration-300">
          <div className="flex items-center gap-6">
            <span className="text-sm font-semibold">Legend:</span>
            {viewMode === "overlay" ? (
              // Overlay-specific legend
              highlightMode === "common" ? (
                <>
                  <div className="flex items-center gap-2">
                    <div className="w-4 h-4 rounded-full bg-green-500 shadow-sm"></div>
                    <span className="text-sm font-medium">Common elements</span>
                  </div>
                  <div className="flex items-center gap-2">
                    <div className="w-4 h-4 rounded-full bg-gray-400 shadow-sm"></div>
                    <span className="text-sm font-medium">Unique elements</span>
                  </div>
                </>
              ) : (
                <>
                  <div className="flex items-center gap-2">
                    <div className="w-4 h-4 rounded-full bg-blue-500 shadow-sm"></div>
                    <span className="text-sm font-medium">Graph 1 unique</span>
                  </div>
                  <div className="flex items-center gap-2">
                    <div className="w-4 h-4 rounded-full bg-orange-500 shadow-sm"></div>
                    <span className="text-sm font-medium">Graph 2 unique</span>
                  </div>
                  <div className="flex items-center gap-2">
                    <div className="w-4 h-4 rounded-full bg-gray-400 shadow-sm"></div>
                    <span className="text-sm font-medium">Common elements</span>
                  </div>
                </>
              )
            ) : // Side-by-side legend
            highlightMode === "common" ? (
              <>
                <div className="flex items-center gap-2">
                  <div className="w-4 h-4 rounded-full bg-green-500 shadow-sm"></div>
                  <span className="text-sm font-medium">Common elements</span>
                </div>
                <div className="flex items-center gap-2">
                  <div className="w-4 h-4 rounded-full bg-gray-400 shadow-sm"></div>
                  <span className="text-sm font-medium">Unique elements</span>
                </div>
              </>
            ) : (
              <>
                <div className="flex items-center gap-2">
                  <div className="w-4 h-4 rounded-full bg-blue-500 shadow-sm"></div>
                  <span className="text-sm font-medium">Unique elements</span>
                </div>
                <div className="flex items-center gap-2">
                  <div className="w-4 h-4 rounded-full bg-gray-400 shadow-sm"></div>
                  <span className="text-sm font-medium">Common elements</span>
                </div>
              </>
            )}
          </div>
        </div>
      )}
    </div>
  );
};
