#[derive(Debug, Clone, PartialEq)]
pub struct Graph {
    pub nodes: Vec<Node>,
    pub edges: Vec<Edge>,
}

impl Graph {
    pub fn new(nodes: Vec<Node>, edges: Vec<Edge>) -> Self {
        Self { nodes, edges }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Node {
    pub label: Option<String>,
    pub x: f64,
    pub y: f64,
}

impl Default for Node {
    fn default() -> Self {
        Self {
            label: None,
            x: 0.0,
            y: 0.0,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Edge {
    pub source: usize,
    pub target: usize,
}

impl Edge {
    pub fn new(source: usize, target: usize) -> Self {
        Self { source, target }
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

impl Point {
    pub fn new(x: f64, y: f64) -> Self {
        Self { x, y }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EdgeRouteKind {
    Straight,
    Spiral,
    IntraLevel,
}

#[derive(Debug, Clone, PartialEq)]
pub struct EdgeRoute {
    pub original_edge_index: usize,
    pub source: usize,
    pub target: usize,
    pub kind: EdgeRouteKind,
    pub points: Vec<Point>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct RoutedNode {
    pub original_index: Option<usize>,
    pub level: usize,
    pub point: Point,
}

#[derive(Debug, Clone, PartialEq)]
pub struct LayoutArtifacts {
    pub node_levels: Vec<usize>,
    pub edge_offsets: Vec<i32>,
    pub edge_routes: Vec<EdgeRoute>,
    pub routed_nodes: Vec<RoutedNode>,
    pub center: Point,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SvgConfig {
    pub shortest_edges: bool,
    pub show_labels: bool,
}

impl Default for SvgConfig {
    fn default() -> Self {
        Self {
            shortest_edges: false,
            show_labels: true,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RingDistribution {
    Packed,
    Distributed,
    Adaptive,
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct LayoutConfig {
    pub min_radius: f64,
    pub level_distance: f64,
    pub align_positive_coords: bool,
    pub spiral_quality: usize,
    pub left_border: f64,
    pub upper_border: f64,
    pub node_distance: f64,
    pub ring_distribution: RingDistribution,
}

impl Default for LayoutConfig {
    fn default() -> Self {
        Self {
            min_radius: 1.0,
            level_distance: 1.0,
            align_positive_coords: true,
            spiral_quality: 500,
            left_border: 80.0,
            upper_border: 80.0,
            node_distance: 80.0,
            ring_distribution: RingDistribution::Packed,
        }
    }
}
