///|
/// The Atom namespace URI.
pub const ATOM_NAMESPACE : String = "http://www.w3.org/2005/Atom"

///|
/// How a `Text` construct is encoded.
pub(all) enum TextType {
  /// Plain text (default).
  Text
  /// Escaped HTML.
  Html
  /// Inline XHTML wrapped in a `div`.
  Xhtml
} derive(Debug, Eq)

///|
/// A text construct (`title`, `subtitle`, `rights`, `summary`).
pub(all) struct Text {
  /// Encoding of the payload.
  typ : TextType
  /// Payload value.
  value : String
} derive(Debug, Eq)

///|
/// Construct a plain-text construct.
pub fn Text::plain(value : String) -> Text {
  { typ: TextType::Text, value }
}

///|
/// Construct an HTML text construct.
pub fn Text::html(value : String) -> Text {
  { typ: TextType::Html, value }
}

///|
/// Construct an XHTML text construct.
pub fn Text::xhtml(value : String) -> Text {
  { typ: TextType::Xhtml, value }
}

///|
/// Entry content per RFC 4287 §4.1.3.
pub(all) enum Content {
  /// `type="text"` — plain text.
  Text(String)
  /// `type="html"` — escaped HTML.
  Html(String)
  /// `type="xhtml"` — inline XHTML.
  Xhtml(String)
  /// Out-of-line content referenced by `src`.
  Src(src~ : String, media_type~ : String?)
} derive(Debug, Eq)

///|
/// An Atom person construct, RFC 4287 §3.2.
pub(all) struct Person {
  /// Human-readable name (required).
  name : String
  /// Email address.
  email : String?
  /// IRI associated with the person.
  uri : String?
} derive(Debug, Eq)

///|
/// An Atom link, RFC 4287 §4.2.7.
pub(all) struct Link {
  /// Target IRI (required).
  href : String
  /// Link relationship type, e.g. `"self"`, `"alternate"`, `"enclosure"`.
  rel : String?
  /// Media type of the target.
  media_type : String?
  /// Language of the target.
  hreflang : String?
  /// Human-readable title.
  title : String?
  /// Length in bytes, when known.
  length : String?
} derive(Debug, Eq)

///|
/// Construct an `alternate` link.
pub fn Link::alternate(href : String) -> Link {
  {
    href,
    rel: None,
    media_type: None,
    hreflang: None,
    title: None,
    length: None,
  }
}

///|
/// Construct an enclosure-style link.
pub fn Link::enclosure(
  href~ : String,
  media_type~ : String,
  length~ : String,
) -> Link {
  {
    href,
    rel: Some("enclosure"),
    media_type: Some(media_type),
    hreflang: None,
    title: None,
    length: Some(length),
  }
}

///|
/// An Atom category, RFC 4287 §4.2.2.
pub(all) struct Category {
  /// Category identifier (required).
  term : String
  /// IRI identifying the categorisation scheme.
  scheme : String?
  /// Human-readable label.
  label : String?
} derive(Debug, Eq)

///|
/// The software agent that generated the feed.
pub(all) struct Generator {
  value : String?
  uri : String?
  version : String?
} derive(Debug, Eq)

///|
/// Metadata about the original source feed of an entry.
pub(all) struct Source {
  id : String?
  title : Text?
  updated : String?
} derive(Debug, Eq)

///|
/// An Atom entry, RFC 4287 §4.1.2.
pub(all) struct Entry {
  /// Permanent, universally unique identifier (required).
  id : String
  /// Title (required).
  title : Text
  /// Last modification instant (required, RFC 3339).
  updated : String
  /// Authors; inherits feed-level authors when absent.
  authors : Array[Person]
  contributors : Array[Person]
  categories : Array[Category]
  links : Array[Link]
  /// Initial publication or availability instant.
  published : String?
  rights : Text?
  summary : Text?
  content : Content?
  /// Original source metadata when the entry was copied from another feed.
  source : Source?
} derive(Debug, Eq)

///|
/// A minimal Atom 1.0 feed modelled on RFC 4287.
pub(all) struct Feed {
  /// Permanent, universally unique identifier (required).
  id : String
  /// Title (required).
  title : Text
  /// Last modification instant (required, RFC 3339).
  updated : String
  authors : Array[Person]
  contributors : Array[Person]
  categories : Array[Category]
  links : Array[Link]
  generator : Generator?
  icon : String?
  logo : String?
  rights : Text?
  subtitle : Text?
  entries : Array[Entry]
} derive(Debug, Eq)

///|
/// Create a feed skeleton with the required elements filled and everything
/// else empty.
pub fn Feed::new(id~ : String, title~ : String, updated~ : String) -> Feed {
  {
    id,
    title: Text::plain(title),
    updated,
    authors: [],
    contributors: [],
    categories: [],
    links: [],
    generator: None,
    icon: None,
    logo: None,
    rights: None,
    subtitle: None,
    entries: [],
  }
}

///|
/// Create an entry skeleton with the required elements filled and everything
/// else empty.
pub fn Entry::new(id~ : String, title~ : String, updated~ : String) -> Entry {
  {
    id,
    title: Text::plain(title),
    updated,
    authors: [],
    contributors: [],
    categories: [],
    links: [],
    published: None,
    rights: None,
    summary: None,
    content: None,
    source: None,
  }
}