///|
/// One role, user, or channel permission override for an application command.
#derive(ToJson(fields(typ(rename="type"))), FromJson(fields(typ(rename="type"))), Debug)
pub(all) struct ApplicationCommandPermission {
  id : GenericId
  typ : ApplicationCommandPermissionType
  permission : Bool
}

///|
/// The target kind of an application-command permission override.
#derive(Eq, Debug)
#non_exhaustive
pub(all) enum ApplicationCommandPermissionType {
  Role
  User
  Channel
  Unknown(Int32)
}

///|
/// The Discord integer value of this `ApplicationCommandPermissionType`.
pub fn ApplicationCommandPermissionType::to_int(
  self : ApplicationCommandPermissionType,
) -> Int32 {
  match self {
    Role => 1
    User => 2
    Channel => 3
    Unknown(value) => value
  }
}

///|
/// The `ApplicationCommandPermissionType` for its Discord integer value; unknown values become `Unknown(n)`.
pub fn ApplicationCommandPermissionType::from_int(
  value : Int32,
) -> ApplicationCommandPermissionType {
  match value {
    1 => Role
    2 => User
    3 => Channel
    value => Unknown(value)
  }
}

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

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

///|
/// Guild-scoped permission overrides for one application command.
#derive(ToJson, FromJson, Debug)
pub(all) struct GuildApplicationCommandPermissions {
  id : CommandId
  application_id : ApplicationId
  guild_id : GuildId
  permissions : Array[ApplicationCommandPermission]
}