///|
/// A Discord standard or guild sticker.
#derive(ToJson(fields(typ(rename="type"))), FromJson(fields(typ(rename="type"))), Debug)
pub(all) struct Sticker {
  id : StickerId
  pack_id : StickerPackId?
  name : String
  description : Nullable[String]
  /// A comma-separated expression list, kept in Discord's wire representation.
  tags : String
  asset : String?
  typ : StickerType
  format_type : StickerFormatType
  available : Bool?
  guild_id : GuildId?
  user : User?
  sort_value : Int32?
}

///|
/// The origin category of a sticker.
#derive(Eq, Debug)
#non_exhaustive
pub(all) enum StickerType {
  Standard
  Guild
  Unknown(Int32)
}

///|
/// The Discord integer value of this `StickerType`.
pub fn StickerType::to_int(self : StickerType) -> Int32 {
  match self {
    Standard => 1
    Guild => 2
    Unknown(value) => value
  }
}

///|
/// The `StickerType` for its Discord integer value; unknown values become `Unknown(n)`.
pub fn StickerType::from_int(value : Int32) -> StickerType {
  match value {
    1 => Standard
    2 => Guild
    value => Unknown(value)
  }
}

///|
/// Encodes the `StickerType` as its Discord integer value.
pub impl ToJson for StickerType with fn to_json(self) {
  Json::number(self.to_int().to_double())
}

///|
/// Decodes the `StickerType` from a JSON number; unknown values become `Unknown(n)`.
pub impl @json.FromJson for StickerType with fn from_json(json, path) {
  match json {
    Number(value, ..) => StickerType::from_int(value.to_int())
    _ => raise JsonDecodeError((path, "expected a sticker type (number)"))
  }
}

///|
/// The media format used by a sticker asset.
#derive(Eq, Debug)
#non_exhaustive
pub(all) enum StickerFormatType {
  Png
  Apng
  Lottie
  Gif
  Unknown(Int32)
}

///|
/// The Discord integer value of this `StickerFormatType`.
pub fn StickerFormatType::to_int(self : StickerFormatType) -> Int32 {
  match self {
    Png => 1
    Apng => 2
    Lottie => 3
    Gif => 4
    Unknown(value) => value
  }
}

///|
/// The `StickerFormatType` for its Discord integer value; unknown values become `Unknown(n)`.
pub fn StickerFormatType::from_int(value : Int32) -> StickerFormatType {
  match value {
    1 => Png
    2 => Apng
    3 => Lottie
    4 => Gif
    value => Unknown(value)
  }
}

///|
/// Encodes the `StickerFormatType` as its Discord integer value.
pub impl ToJson for StickerFormatType with fn to_json(self) {
  Json::number(self.to_int().to_double())
}

///|
/// Decodes the `StickerFormatType` from a JSON number; unknown values become `Unknown(n)`.
pub impl @json.FromJson for StickerFormatType with fn from_json(json, path) {
  match json {
    Number(value, ..) => StickerFormatType::from_int(value.to_int())
    _ => raise JsonDecodeError((path, "expected a sticker format (number)"))
  }
}

///|
/// The compact sticker representation included in messages.
#derive(ToJson, FromJson, Debug)
pub(all) struct StickerItem {
  id : StickerId
  name : String
  format_type : StickerFormatType
}

///|
/// A purchasable collection of standard stickers.
#derive(ToJson, FromJson, Debug)
pub(all) struct StickerPack {
  id : StickerPackId
  stickers : Array[Sticker]
  name : String
  sku_id : SkuId
  cover_sticker_id : StickerId?
  description : String
  banner_asset_id : GenericId?
}

///|
/// The envelope returned by the sticker-packs listing endpoint.
#derive(ToJson, FromJson, Debug)
pub(all) struct StickerPacksResponse {
  sticker_packs : Array[StickerPack]
}