use serde::{Deserialize, Serialize};
use std::cmp::PartialEq;

/// Represents the state of a Webmention for a client or a server.
#[derive(Clone, Debug, Serialize, Deserialize, Eq)]
#[serde(rename_all = "lowercase")]
pub enum Status {
    /// Used to highlight that a stored Webmention or a response about a Webmention has
    /// been rejected by a remote endpoint or the implementation of a server is informing a client
    /// that it has been rejected.
    Rejected,

    /// Used to highlight that an asynchronous Webmention has been accepted for processing
    /// by a remote endpoint.
    Accepted,

    /// Used to highlight that a stored Webmention or a response about a Webmention has
    /// been stored for later processing. Usually, you can use some sort of URL returned
    /// back in the headers or body to determine how to get a more recent version of its
    /// status.
    Pending,

    /// Used to highlight that a stored Webmention was accepted by an endpoint.
    Sent,
}

impl Default for Status {
    fn default() -> Self {
        Self::Pending
    }
}

impl PartialEq for Status {
    fn eq(&self, other: &Self) -> bool {
        std::mem::discriminant(self) == std::mem::discriminant(other)
    }
}

/// Represents a incoming request to an endpoint for a Webmention.
#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Request {
    /// The endpoint to send the Webmention to. This is conventionally
    /// resolved using `indieweb::link_rel::for_url` with a rel value
    /// of "webmention".
    #[serde(skip)]
    pub endpoint: String,

    /// The URL of the resource that's sending this Webmention.
    pub source: String,

    /// The URL of the resource that's receiving this. Webmention.
    pub target: String,

    /// A optional list of URLs that can be used for vouching this URL.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub vouch: Option<Vec<String>>,
}

/// Represents a outgoing resonse from an endpoint for a Webmention.
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct Response {
    /// The resulting status of a Webmention.
    pub status: Status,

    /// A optional URL presenting the result of this URL. It can also be used
    /// at time to show status information or acceptance information.
    pub location: Option<String>,

    /// A optional body representing the immediate body of the response.
    pub body: Option<String>,
}

impl PartialEq for Response {
    fn eq(&self, other: &Self) -> bool {
        self.status == other.status && self.location == other.location && self.body == other.body
    }
}

pub mod client;
