use alloc::{format, rc::Rc, string::String};
use core::{fmt, fmt::Display, iter};
use crate::{
diagrams::class_diagram::{class_edge::multiplicity::Multiplicity, class_node::ClassNode},
shared::{ArrowShape, GenericEdge, LineStyle, NODE_LETTER},
traits::{Edge, node::Node},
};
pub mod builder;
pub mod multiplicity;
pub use builder::ClassEdgeBuilder;
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ClassEdge {
edge: GenericEdge<ClassNode>,
left_multiplicity: Option<Multiplicity>,
right_multiplicity: Option<Multiplicity>,
}
impl Edge for ClassEdge {
type Builder = ClassEdgeBuilder;
type Node = ClassNode;
fn label(&self) -> Option<&str> {
self.edge.label()
}
fn source(&self) -> &Rc<Self::Node> {
self.edge.source()
}
fn destination(&self) -> &Rc<Self::Node> {
self.edge.destination()
}
fn line_style(&self) -> LineStyle {
self.edge.line_style()
}
fn classes(&self) -> impl Iterator<Item = &crate::shared::StyleClass> {
iter::empty()
}
fn left_arrow_shape(&self) -> Option<ArrowShape> {
self.edge.left_arrow_shape()
}
fn right_arrow_shape(&self) -> Option<ArrowShape> {
self.edge.right_arrow_shape()
}
}
impl Display for ClassEdge {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::traits::TabbedDisplay;
self.fmt_tabbed(f, 0)
}
}
impl crate::traits::TabbedDisplay for ClassEdge {
fn fmt_tabbed(&self, f: &mut fmt::Formatter<'_>, tab_count: usize) -> fmt::Result {
let indent = " ".repeat(tab_count * 2);
writeln!(
f,
"{indent}{NODE_LETTER}{} {left_multiplicity}{left_arrow}{segment}{right_arrow}{right_multiplicity} {NODE_LETTER}{}{}",
self.source().id(),
self.destination().id(),
self.label().map_or_else(String::new, |label| format!(" : \"`{label}`\"")),
left_multiplicity =
self.left_multiplicity.as_ref().map_or_else(String::new, |lm| format!("{lm} ")),
left_arrow = self.left_arrow_shape().as_ref().map_or_else(|| "", |shape| shape.left()),
segment = match self.line_style() {
LineStyle::Solid => "--",
LineStyle::Thick => "==",
LineStyle::Dashed => "..",
},
right_arrow =
self.right_arrow_shape().as_ref().map_or_else(|| "", |shape| shape.right()),
right_multiplicity =
self.right_multiplicity.as_ref().map_or_else(String::new, |rm| format!(" {rm}")),
)
}
}