//! Contains helper types used to represent bounded values, with and without defaults.
//!
//! Mainly used to represent settings on the server and parameter bounds in requests.

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::fmt::Debug;

/// A set of bounds on a value.
///
/// Used in the API to return bounds settings.
pub struct BoundedValue<T> {
    /// Minimum allowed value for this parameter.
    pub min: T,
    /// Maximum allowed value for this parameter.
    pub max: T,
}

impl<T> BoundedValue<T> {
    /// Creates a new value with the given bounds.
    pub const fn new(min: T, max: T) -> Self {
        Self { min, max }
    }

    /// Returns whether the given value is within the bounds.
    #[inline]
    pub fn contains<V>(&self, value: V) -> bool
    where
        V: PartialOrd<T>,
    {
        (value >= self.min) && (value <= self.max)
    }
}

/// Implement [`Debug`] if inner type implements it.
impl<T> Debug for BoundedValue<T>
where
    T: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("BoundedValue")
            .field("min", &self.min)
            .field("max", &self.max)
            .finish()
    }
}

/// Implement [`Default`] if inner type implements it.
impl<T> Default for BoundedValue<T>
where
    T: Default,
{
    fn default() -> Self {
        Self {
            min: Default::default(),
            max: Default::default(),
        }
    }
}

/// Implement [`Clone`] if inner type implements it.
impl<T> Clone for BoundedValue<T>
where
    T: Clone,
{
    fn clone(&self) -> Self {
        Self {
            min: self.min.clone(),
            max: self.max.clone(),
        }
    }
}

/// Implement [`Copy`] if inner type implements it.
impl<T> Copy for BoundedValue<T> where T: Copy {}

/// Implement [`PartialEq`] if inner type implements it.
impl<T> PartialEq for BoundedValue<T>
where
    T: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        (self.min == other.min) && (self.max == other.max)
    }
}

impl<T> Eq for BoundedValue<T> where T: Eq {}

/// A set of bounds and default value.
///
/// Used in the API to return bounds and defaults for optional settings.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BoundedValueWithDefault<T> {
    /// Minimum allowed value for this parameter.
    pub min: T,
    /// Maximum allowed value for this parameter.
    pub max: T,
    /// Default value for this parameter.
    pub default: T,
}

impl<T> BoundedValueWithDefault<T> {
    /// Creates a new value with the given bounds and default.
    pub const fn new(min: T, max: T, default: T) -> Self {
        Self { min, max, default }
    }

    /// Returns whether the given value is within the bounds.
    #[inline]
    pub fn contains<V>(&self, value: V) -> bool
    where
        V: PartialOrd<T>,
    {
        (value >= self.min) && (value <= self.max)
    }
}

/// Implement [`Debug`] if inner type implements it.
impl<T> Debug for BoundedValueWithDefault<T>
where
    T: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("BoundedValueWithDefault")
            .field("min", &self.min)
            .field("max", &self.max)
            .field("default", &self.default)
            .finish()
    }
}

/// Implement [`Default`] if inner type implements it.
impl<T> Default for BoundedValueWithDefault<T>
where
    T: Default,
{
    fn default() -> Self {
        Self {
            min: Default::default(),
            max: Default::default(),
            default: Default::default(),
        }
    }
}

/// Implement [`Clone`] if inner type implements it.
impl<T> Clone for BoundedValueWithDefault<T>
where
    T: Clone,
{
    fn clone(&self) -> Self {
        Self {
            min: self.min.clone(),
            max: self.max.clone(),
            default: self.default.clone(),
        }
    }
}

/// Implement [`Copy`] if inner type implements it.
impl<T> Copy for BoundedValueWithDefault<T> where T: Copy {}

/// Implement [`PartialEq`] if inner type implements it.
impl<T> PartialEq for BoundedValueWithDefault<T>
where
    T: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        (self.min == other.min) && (self.max == other.max) && (self.default == other.default)
    }
}

impl<T> Eq for BoundedValueWithDefault<T> where T: Eq {}
