use crate::Network;
use crate::Roots;
use crate::store::Store;

/// A builder for `Network`s, which can be used to configure the
/// properties of the network.
///
/// A `NetworkBuilder` is used to create a specially configured
/// [`Network`].
pub struct NetworkBuilder<S>
    where S: Store
{
    // The underlying network.
    store: S,

    // The trust roots.
    roots: Roots,

    // If this is a certification network (where all certificates are
    // considered tsigs with infiniate depth and no regular
    // expression), or a normal authentication network.
    certification_network: bool,

    /// Whether to constrain the search to paths with a given depth.
    maximum_depth: Option<usize>,
}

impl<S> NetworkBuilder<S>
    where S: Store
{
    /// Returns a new `NetworkBuilder`.
    ///
    /// Returns a `NetworkBuilder` with the specified root.
    ///
    /// By default, the [`NetworkBuilder`] is configured to be an
    /// authentication network, and there is no maximum depth.
    pub fn rooted<R>(store: S, roots: R) -> Self
    where R: Into<Roots>,
    {
        tracer!(TRACE, "NetworkBuilder::rooted");

        Self {
            store,
            roots: roots.into(),
            certification_network: false,
            maximum_depth: None,
        }
    }

    /// Returns a new `NetworkBuilder`.
    ///
    /// Returns a `NetworkBuilder` without any roots.  This is still
    /// useful for querying specific paths.
    ///
    /// By default, the [`NetworkBuilder`] is configured to be an
    /// authentication network, and there is no maximum depth.
    pub fn rootless(store: S) -> Self
    {
        tracer!(TRACE, "NetworkBuilder::rooted");

        Self {
            store,
            roots: Roots::empty(),
            certification_network: false,
            maximum_depth: None,
        }
    }

    /// Configures the `Network` to be a certification network.
    ///
    /// By default, a `Network` is treated as an authentication
    /// network.  In a certification network, all certifications are
    /// considered to be trusted signatures with an infinite trust
    /// depth, and no regular expressions.
    ///
    /// This is how most so-called *web-of-trust path-finder* or *pgp
    /// path-finder* algorithms work: they are interested in
    /// determining whether there is a chain of certifications from
    /// one certificate to another without regard as to whether a
    /// certifier considers the target to be a trusted introducer, or
    /// to have only verified the target's identity.
    pub fn certification_network(mut self) -> Self
    {
        tracer!(TRACE, "NetworkBuilder::certification_network");

        self.certification_network = true;
        self
    }

    /// Configures the `Network` to be an authentication network.
    ///
    /// This is the default mode of operation where plain
    /// certifications are only considered certifications, and the
    /// target is not considered to be a trusted introducer.  An
    /// alternative mode of operation is a certification network.
    /// This can be configured using
    /// [`NetworkBuilder::certification_network`].  See that method's
    /// documentation for more details.
    pub fn authentication_network(mut self) -> Self {
        self.certification_network = false;
        self
    }

    /// Limits all trusted introducers to the given maximum depth.
    ///
    /// Note: With the depth limited to `0`, the maximum lengths of
    /// paths will be two, with the paths containing the certifier and
    /// the target).
    pub fn maximum_depth(mut self, limit: usize) -> Self {
        self.maximum_depth = Some(limit);
        self
    }

    /// Returns a `Network`.
    pub fn build(self) -> Network<S> {
        Network {
            store: self.store,
            roots: self.roots,
            certification_network: self.certification_network,
            maximum_depth: self.maximum_depth,
        }
    }
}
