dioxus_router/
navigation.rsuse std::{
    fmt::{Debug, Display},
    str::FromStr,
};
use url::{ParseError, Url};
use crate::{components::child_router::consume_child_route_mapping, routable::Routable, router};
impl<R: Routable> From<R> for NavigationTarget {
    fn from(value: R) -> Self {
        let mapping = consume_child_route_mapping();
        match mapping.as_ref() {
            Some(mapping) => NavigationTarget::Internal(mapping.format_route_as_root_route(value)),
            None => NavigationTarget::Internal(value.to_string()),
        }
    }
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum NavigationTarget<R = String> {
    Internal(R),
    External(String),
}
impl<R: Routable> From<&str> for NavigationTarget<R> {
    fn from(value: &str) -> Self {
        value
            .parse()
            .unwrap_or_else(|_| Self::External(value.to_string()))
    }
}
impl<R: Routable> From<&String> for NavigationTarget<R> {
    fn from(value: &String) -> Self {
        value.as_str().into()
    }
}
impl<R: Routable> From<String> for NavigationTarget<R> {
    fn from(value: String) -> Self {
        value.as_str().into()
    }
}
impl<R: Routable> From<R> for NavigationTarget<R> {
    fn from(value: R) -> Self {
        Self::Internal(value)
    }
}
impl From<&str> for NavigationTarget {
    fn from(value: &str) -> Self {
        let router = router();
        match router.internal_route(value) {
            true => NavigationTarget::Internal(value.to_string()),
            false => NavigationTarget::External(value.to_string()),
        }
    }
}
impl From<String> for NavigationTarget {
    fn from(value: String) -> Self {
        let router = router();
        match router.internal_route(&value) {
            true => NavigationTarget::Internal(value),
            false => NavigationTarget::External(value),
        }
    }
}
impl<R: Routable> From<NavigationTarget<R>> for NavigationTarget {
    fn from(value: NavigationTarget<R>) -> Self {
        match value {
            NavigationTarget::Internal(r) => r.into(),
            NavigationTarget::External(s) => Self::External(s),
        }
    }
}
impl<R: Routable> Display for NavigationTarget<R> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            NavigationTarget::Internal(r) => write!(f, "{}", r),
            NavigationTarget::External(s) => write!(f, "{}", s),
        }
    }
}
pub enum NavigationTargetParseError<R: Routable> {
    InvalidUrl(ParseError),
    InvalidInternalURL(<R as FromStr>::Err),
}
impl<R: Routable> Debug for NavigationTargetParseError<R> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            NavigationTargetParseError::InvalidUrl(e) => write!(f, "Invalid URL: {}", e),
            NavigationTargetParseError::InvalidInternalURL(_) => {
                write!(f, "Invalid internal URL")
            }
        }
    }
}
impl<R: Routable> FromStr for NavigationTarget<R> {
    type Err = NavigationTargetParseError<R>;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match Url::parse(s) {
            Ok(_) => Ok(Self::External(s.to_string())),
            Err(ParseError::RelativeUrlWithoutBase) => {
                Ok(Self::Internal(R::from_str(s).map_err(|e| {
                    NavigationTargetParseError::InvalidInternalURL(e)
                })?))
            }
            Err(e) => Err(NavigationTargetParseError::InvalidUrl(e)),
        }
    }
}