use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;

use self::raw::*;
use crate::types::{
    Animation,
    Audio,
    ChatBackground,
    Checklist,
    ChecklistTasksAdded,
    ChecklistTasksDone,
    Contact,
    Dice,
    Document,
    ForumTopicIconColor,
    Game,
    GiftInfo,
    Giveaway,
    GiveawayCompleted,
    GiveawayCreated,
    GiveawayWinners,
    Integer,
    Invoice,
    LivePhoto,
    Location,
    MaybeInaccessibleMessage,
    PaidMediaInfo,
    PassportData,
    PhotoSize,
    Poll,
    RefundedPayment,
    SharedUser,
    Sticker,
    Story,
    SuccessfulPayment,
    SuggestedPostApprovalFailed,
    SuggestedPostApproved,
    SuggestedPostDeclined,
    SuggestedPostPaid,
    SuggestedPostRefunded,
    Text,
    UniqueGiftInfo,
    User,
    Venue,
    Video,
    VideoNote,
    Voice,
    WebAppData,
};

mod raw;

/// Represents a message data.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum MessageData {
    /// Information about the animation.
    Animation(Animation),
    /// Auto-delete timer settings changed.
    #[serde(rename = "message_auto_delete_timer_changed")]
    AutoDeleteTimerChanged(MessageDataAutoDeleteTimer),
    /// Service message: user boosted the chat.
    ///
    /// Contains a number of boosts added by the user.
    #[serde(
        deserialize_with = "RawDataBoostAdded::deserialize_value",
        serialize_with = "RawDataBoostAdded::serialize_value"
    )]
    BoostAdded(Integer),
    /// The channel has been created.
    ///
    /// This field can‘t be received in a message coming through updates,
    /// because bot can’t be a member of a channel when it is created.
    /// It can only be found in the `reply_to` field of the [`crate::types::Message`] struct
    /// if someone replies to a very first message in a channel.
    #[serde(
        deserialize_with = "RawDataFlag::deserialize_value",
        serialize_with = "RawDataFlag::serialize_value"
    )]
    ChannelChatCreated,
    /// Chat background set.
    ChatBackgroundSet(ChatBackground),
    /// Describes a service message about an ownership change in the chat.
    #[serde(
        deserialize_with = "RawDataChatOwnerChanged::deserialize_value",
        serialize_with = "RawDataChatOwnerChanged::serialize_value"
    )]
    ChatOwnerChanged(User),
    /// Describes a service message about the chat owner leaving the chat.
    ///
    /// Optional user is the user which will be the new owner of the chat
    /// if the previous owner does not return to the chat.
    #[serde(
        deserialize_with = "RawDataChatOwnerLeft::deserialize_value",
        serialize_with = "RawDataChatOwnerLeft::serialize_value"
    )]
    ChatOwnerLeft(Option<User>),
    /// A chat was shared with the bot.
    ChatShared(MessageDataChatShared),
    /// Message is a checklist.
    Checklist(Checklist),
    /// Tasks were added to a checklist.
    ChecklistTasksAdded(ChecklistTasksAdded),
    /// Some tasks in a checklist were marked as done or not done.
    ChecklistTasksDone(ChecklistTasksDone),
    /// The domain name of the website on which the user has logged in.
    ConnectedWebsite(String),
    /// Information about the shared contact.
    Contact(Contact),
    /// The chat photo was deleted.
    #[serde(
        deserialize_with = "RawDataFlag::deserialize_value",
        serialize_with = "RawDataFlag::serialize_value"
    )]
    DeleteChatPhoto,
    /// A dice with a random value.
    Dice(Dice),
    /// The price for paid messages in the corresponding direct messages chat of a channel has changed.
    DirectMessagePriceChanged(MessageDataDirectMessagePriceChanged),
    /// Forum topic closed.
    #[serde(
        deserialize_with = "RawDataEmpty::deserialize_value",
        serialize_with = "RawDataEmpty::serialize_value"
    )]
    ForumTopicClosed,
    /// Forum topic created.
    ForumTopicCreated(MessageDataForumTopicCreated),
    /// Forum topic edited.
    ForumTopicEdited(MessageDataForumTopicEdited),
    /// Forum topic reopened.
    #[serde(
        deserialize_with = "RawDataEmpty::deserialize_value",
        serialize_with = "RawDataEmpty::serialize_value"
    )]
    ForumTopicReopened,
    /// Information about the game.
    Game(Box<Game>),
    /// A service message about a sent or received regular gift.
    Gift(Box<GiftInfo>),
    /// A service message about upgrade of a gift was purchased after the gift was sent.
    GiftUpgradeSent(Box<GiftInfo>),
    /// The 'General' forum topic hidden.
    #[serde(
        deserialize_with = "RawDataEmpty::deserialize_value",
        serialize_with = "RawDataEmpty::serialize_value"
    )]
    GeneralForumTopicHidden,
    /// The 'General' forum topic unhidden.
    #[serde(
        deserialize_with = "RawDataEmpty::deserialize_value",
        serialize_with = "RawDataEmpty::serialize_value"
    )]
    GeneralForumTopicUnhidden,
    /// A scheduled giveaway.
    Giveaway(Giveaway),
    /// Service message: a scheduled giveaway was created.
    GiveawayCreated(GiveawayCreated),
    /// Service message: a giveaway without public winners was completed.
    GiveawayCompleted(GiveawayCompleted),
    /// A giveaway with public winners was completed.
    GiveawayWinners(GiveawayWinners),
    /// The group has been created.
    #[serde(
        deserialize_with = "RawDataFlag::deserialize_value",
        serialize_with = "RawDataFlag::serialize_value"
    )]
    GroupChatCreated,
    /// Information about the invoice for a payment.
    Invoice(Invoice),
    /// A member was removed from the group.
    ///
    /// This member may be the bot itself.
    LeftChatMember(User),
    /// Information about the shared location.
    Location(Location),
    /// User created a bot that will be managed by the current bot.
    ManagedBotCreated(MessageDataManagedBotCreated),
    /// The supergroup has been migrated from a group with the specified identifier.
    MigrateFromChatId(Integer),
    /// The group has been migrated to a supergroup with the specified identifier.
    MigrateToChatId(Integer),
    /// New members that were added to the group or supergroup.
    ///
    /// The bot itself may be one of these members.
    NewChatMembers(Vec<User>),
    /// A chat photo was change to this value.
    NewChatPhoto(Vec<PhotoSize>),
    /// A chat title was changed to this value.
    NewChatTitle(String),
    /// Message contains paid media; information about the paid media.
    PaidMedia(PaidMediaInfo),
    /// A service message about the changed price for paid messages.
    PaidMessagePriceChanged(MessageDataPaidMessagePriceChanged),
    /// Telegram Passport data.
    PassportData(PassportData),
    /// Specified message was pinned.
    ///
    /// Note that the Message object in variant will not contain
    /// further `reply_to` field even if it is itself a reply.
    PinnedMessage(MaybeInaccessibleMessage),
    /// Information about the native poll.
    Poll(Box<Poll>),
    /// Answer option was added to a poll.
    PollOptionAdded(MessageDataPollOptionAdded),
    /// Answer option was deleted from a poll.
    PollOptionDeleted(MessageDataPollOptionDeleted),
    /// A user in the chat triggered another user's proximity alert while sharing Live Location.
    ProximityAlertTriggered(MessageDataProximityAlert),
    /// A service message about a refunded payment, information about the payment.
    RefundedPayment(RefundedPayment),
    /// Information about the sticker.
    Sticker(Box<Sticker>),
    /// A forwarded story.
    Story(Story),
    /// Service message: a suggested post was approved.
    SuggestedPostApproved(SuggestedPostApproved),
    /// Service message: approval of a suggested post has failed.
    SuggestedPostApprovalFailed(SuggestedPostApprovalFailed),
    /// Service message: a suggested post was declined.
    SuggestedPostDeclined(SuggestedPostDeclined),
    /// Service message: payment for a suggested post was received.
    SuggestedPostPaid(SuggestedPostPaid),
    /// Service message: payment for a suggested post was refunded.
    SuggestedPostRefunded(SuggestedPostRefunded),
    /// Information about the successful payment.
    SuccessfulPayment(Box<SuccessfulPayment>),
    /// The supergroup has been created.
    ///
    /// This field can‘t be received in a message coming through updates,
    /// because bot can’t be a member of a supergroup when it is created
    /// It can only be found in the `reply_to` field of the [`crate::types::Message`] struct
    /// if someone replies to a very first message
    /// in a directly created supergroup.
    #[serde(
        deserialize_with = "RawDataFlag::deserialize_value",
        serialize_with = "RawDataFlag::serialize_value"
    )]
    SupergroupChatCreated,
    /// A service message about a sent or received unique gift.
    UniqueGift(Box<UniqueGiftInfo>),
    /// A user was shared with the bot.
    UsersShared(MessageDataUsersShared),
    /// Information about the venue.
    Venue(Venue),
    /// Information about the video note.
    VideoNote(VideoNote),
    /// A video chat ended in the chat.
    VideoChatEnded(MessageDataVideoChatEnded),
    /// New members invited to a video chat.
    VideoChatParticipantsInvited(MessageDataVideoChatParticipantsInvited),
    /// A video chat scheduled in the chat.
    VideoChatScheduled(MessageDataVideoChatScheduled),
    /// A video chat started in the chat.
    #[serde(
        deserialize_with = "RawDataEmpty::deserialize_value",
        serialize_with = "RawDataEmpty::serialize_value"
    )]
    VideoChatStarted,
    /// Data sent by a Web App.
    WebAppData(WebAppData),
    /// The user allowed the bot to write messages
    /// after adding it to the attachment or side menu,
    /// launching a Web App from a link,
    /// or accepting an explicit request from a Web App
    /// sent by the method `requestWriteAccess`.
    WriteAccessAllowed(MessageDataWriteAccess),
    /// Describes the audio.
    #[serde(untagged)]
    Audio(Box<MessageDataAudio>),
    /// Describes the document.
    #[serde(untagged)]
    Document(MessageDataDocument),
    /// Information about the live photo.
    #[serde(untagged)]
    LivePhoto(MessageDataLivePhoto),
    /// Available sizes of the photo.
    #[serde(untagged)]
    Photo(MessageDataPhoto),
    /// The actual UTF-8 text of the message; 0-4096 characters.
    #[serde(
        deserialize_with = "RawDataText::deserialize_value",
        serialize_with = "RawDataText::serialize_value",
        untagged
    )]
    Text(Text),
    /// Describes the video.
    #[serde(untagged)]
    Video(Box<MessageDataVideo>),
    /// Describes the voice.
    #[serde(untagged)]
    Voice(MessageDataVoice),
    /// Contains arbitrary data for future variants.
    #[serde(untagged)]
    Unknown(JsonValue),
}

impl From<Animation> for MessageData {
    fn from(value: Animation) -> Self {
        Self::Animation(value)
    }
}

impl From<MessageDataAutoDeleteTimer> for MessageData {
    fn from(value: MessageDataAutoDeleteTimer) -> Self {
        Self::AutoDeleteTimerChanged(value)
    }
}

impl From<ChatBackground> for MessageData {
    fn from(value: ChatBackground) -> Self {
        Self::ChatBackgroundSet(value)
    }
}

impl From<MessageDataChatShared> for MessageData {
    fn from(value: MessageDataChatShared) -> Self {
        Self::ChatShared(value)
    }
}

impl From<Checklist> for MessageData {
    fn from(value: Checklist) -> Self {
        Self::Checklist(value)
    }
}

impl From<ChecklistTasksAdded> for MessageData {
    fn from(value: ChecklistTasksAdded) -> Self {
        Self::ChecklistTasksAdded(value)
    }
}

impl From<ChecklistTasksDone> for MessageData {
    fn from(value: ChecklistTasksDone) -> Self {
        Self::ChecklistTasksDone(value)
    }
}

impl From<Contact> for MessageData {
    fn from(value: Contact) -> Self {
        Self::Contact(value)
    }
}

impl From<Dice> for MessageData {
    fn from(value: Dice) -> Self {
        Self::Dice(value)
    }
}

impl From<MessageDataDirectMessagePriceChanged> for MessageData {
    fn from(value: MessageDataDirectMessagePriceChanged) -> Self {
        Self::DirectMessagePriceChanged(value)
    }
}

impl From<MessageDataForumTopicCreated> for MessageData {
    fn from(value: MessageDataForumTopicCreated) -> Self {
        Self::ForumTopicCreated(value)
    }
}

impl From<MessageDataForumTopicEdited> for MessageData {
    fn from(value: MessageDataForumTopicEdited) -> Self {
        Self::ForumTopicEdited(value)
    }
}

impl From<Game> for MessageData {
    fn from(value: Game) -> Self {
        Self::Game(Box::new(value))
    }
}

impl From<Giveaway> for MessageData {
    fn from(value: Giveaway) -> Self {
        Self::Giveaway(value)
    }
}

impl From<GiveawayCreated> for MessageData {
    fn from(value: GiveawayCreated) -> Self {
        Self::GiveawayCreated(value)
    }
}

impl From<GiveawayCompleted> for MessageData {
    fn from(value: GiveawayCompleted) -> Self {
        Self::GiveawayCompleted(value)
    }
}

impl From<GiveawayWinners> for MessageData {
    fn from(value: GiveawayWinners) -> Self {
        Self::GiveawayWinners(value)
    }
}

impl From<Invoice> for MessageData {
    fn from(value: Invoice) -> Self {
        Self::Invoice(value)
    }
}

impl From<LivePhoto> for MessageData {
    fn from(value: LivePhoto) -> Self {
        Self::LivePhoto(MessageDataLivePhoto::from(value))
    }
}

impl From<Location> for MessageData {
    fn from(value: Location) -> Self {
        Self::Location(value)
    }
}

impl From<MessageDataManagedBotCreated> for MessageData {
    fn from(value: MessageDataManagedBotCreated) -> Self {
        Self::ManagedBotCreated(value)
    }
}

impl From<PaidMediaInfo> for MessageData {
    fn from(value: PaidMediaInfo) -> Self {
        Self::PaidMedia(value)
    }
}

impl From<MessageDataPaidMessagePriceChanged> for MessageData {
    fn from(value: MessageDataPaidMessagePriceChanged) -> Self {
        Self::PaidMessagePriceChanged(value)
    }
}

impl From<PassportData> for MessageData {
    fn from(value: PassportData) -> Self {
        Self::PassportData(value)
    }
}

impl From<Poll> for MessageData {
    fn from(value: Poll) -> Self {
        Self::Poll(Box::new(value))
    }
}

impl From<MessageDataPollOptionAdded> for MessageData {
    fn from(value: MessageDataPollOptionAdded) -> Self {
        Self::PollOptionAdded(value)
    }
}

impl From<MessageDataPollOptionDeleted> for MessageData {
    fn from(value: MessageDataPollOptionDeleted) -> Self {
        Self::PollOptionDeleted(value)
    }
}

impl From<MessageDataProximityAlert> for MessageData {
    fn from(value: MessageDataProximityAlert) -> Self {
        Self::ProximityAlertTriggered(value)
    }
}

impl From<RefundedPayment> for MessageData {
    fn from(value: RefundedPayment) -> Self {
        Self::RefundedPayment(value)
    }
}

impl From<Sticker> for MessageData {
    fn from(value: Sticker) -> Self {
        Self::Sticker(Box::new(value))
    }
}

impl From<Story> for MessageData {
    fn from(value: Story) -> Self {
        Self::Story(value)
    }
}

impl From<SuggestedPostApproved> for MessageData {
    fn from(value: SuggestedPostApproved) -> Self {
        Self::SuggestedPostApproved(value)
    }
}

impl From<SuggestedPostApprovalFailed> for MessageData {
    fn from(value: SuggestedPostApprovalFailed) -> Self {
        Self::SuggestedPostApprovalFailed(value)
    }
}

impl From<SuggestedPostDeclined> for MessageData {
    fn from(value: SuggestedPostDeclined) -> Self {
        Self::SuggestedPostDeclined(value)
    }
}

impl From<SuggestedPostPaid> for MessageData {
    fn from(value: SuggestedPostPaid) -> Self {
        Self::SuggestedPostPaid(value)
    }
}

impl From<SuggestedPostRefunded> for MessageData {
    fn from(value: SuggestedPostRefunded) -> Self {
        Self::SuggestedPostRefunded(value)
    }
}

impl From<SuccessfulPayment> for MessageData {
    fn from(value: SuccessfulPayment) -> Self {
        Self::SuccessfulPayment(Box::new(value))
    }
}

impl From<UniqueGiftInfo> for MessageData {
    fn from(value: UniqueGiftInfo) -> Self {
        Self::UniqueGift(Box::new(value))
    }
}

impl From<MessageDataUsersShared> for MessageData {
    fn from(value: MessageDataUsersShared) -> Self {
        Self::UsersShared(value)
    }
}

impl From<Venue> for MessageData {
    fn from(value: Venue) -> Self {
        Self::Venue(value)
    }
}

impl From<VideoNote> for MessageData {
    fn from(value: VideoNote) -> Self {
        Self::VideoNote(value)
    }
}

impl From<MessageDataVideoChatEnded> for MessageData {
    fn from(value: MessageDataVideoChatEnded) -> Self {
        Self::VideoChatEnded(value)
    }
}

impl From<MessageDataVideoChatParticipantsInvited> for MessageData {
    fn from(value: MessageDataVideoChatParticipantsInvited) -> Self {
        Self::VideoChatParticipantsInvited(value)
    }
}

impl From<MessageDataVideoChatScheduled> for MessageData {
    fn from(value: MessageDataVideoChatScheduled) -> Self {
        Self::VideoChatScheduled(value)
    }
}

impl From<WebAppData> for MessageData {
    fn from(value: WebAppData) -> Self {
        Self::WebAppData(value)
    }
}

impl From<MessageDataWriteAccess> for MessageData {
    fn from(value: MessageDataWriteAccess) -> Self {
        Self::WriteAccessAllowed(value)
    }
}

impl From<MessageDataAudio> for MessageData {
    fn from(value: MessageDataAudio) -> Self {
        Self::Audio(Box::new(value))
    }
}

impl From<MessageDataDocument> for MessageData {
    fn from(value: MessageDataDocument) -> Self {
        Self::Document(value)
    }
}

impl From<MessageDataPhoto> for MessageData {
    fn from(value: MessageDataPhoto) -> Self {
        Self::Photo(value)
    }
}

impl From<Text> for MessageData {
    fn from(value: Text) -> Self {
        Self::Text(value)
    }
}

impl From<MessageDataVideo> for MessageData {
    fn from(value: MessageDataVideo) -> Self {
        Self::Video(Box::new(value))
    }
}

impl From<MessageDataVoice> for MessageData {
    fn from(value: MessageDataVoice) -> Self {
        Self::Voice(value)
    }
}

/// Represents a service message about a change in auto-delete timer settings.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct MessageDataAutoDeleteTimer {
    /// New auto-delete time for messages in the chat; in seconds.
    #[serde(rename = "message_auto_delete_time")]
    pub time: Integer,
}

impl MessageDataAutoDeleteTimer {
    /// Creates a new `MessageDataAutoDeleteTimer`.
    ///
    /// # Arguments
    ///
    /// * `time` - Time in seconds.
    pub fn new(time: Integer) -> Self {
        Self { time }
    }
}

/// Represents an audio message data.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde_with::skip_serializing_none]
pub struct MessageDataAudio {
    /// Audio data.
    #[serde(rename = "audio")]
    pub data: Audio,
    /// Audio caption.
    #[serde(
        flatten,
        deserialize_with = "RawCaption::deserialize_value",
        serialize_with = "RawCaption::serialize_value"
    )]
    pub caption: Option<Text>,
}

impl From<Audio> for MessageDataAudio {
    fn from(value: Audio) -> Self {
        Self {
            data: value,
            caption: None,
        }
    }
}

impl MessageDataAudio {
    /// Sets a new caption.
    ///
    /// # Arguments
    ///
    /// * `value` - Caption; 0-1024 characters.
    pub fn with_caption<T>(mut self, value: T) -> Self
    where
        T: Into<Text>,
    {
        self.caption = Some(value.into());
        self
    }
}

/// Represents an information about the chat
/// whose identifier was shared with the bot
/// using a [`crate::types::KeyboardButtonRequestChat`] button.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct MessageDataChatShared {
    /// Identifier of the shared chat.
    ///
    /// The bot may not have access to the chat and could be unable to use this identifier,
    /// unless the chat is already known to the bot by some other means.
    pub chat_id: Integer,
    /// Identifier of the request.
    pub request_id: Integer,
    /// Available sizes of the chat photo, if the photo was requested by the bot.
    pub photo: Option<Vec<PhotoSize>>,
    /// Title of the chat, if the title was requested by the bot.
    pub title: Option<String>,
    /// Username of the chat, if the username was requested by the bot and available.
    pub username: Option<String>,
}

impl MessageDataChatShared {
    /// Creates a new `MessageDataChatShared`.
    ///
    /// # Arguments
    ///
    /// * `chat_id` - Identifier of the shared chat.
    /// * `request_id` - Identifier of the request.
    pub fn new(chat_id: Integer, request_id: Integer) -> Self {
        Self {
            chat_id,
            request_id,
            title: None,
            username: None,
            photo: None,
        }
    }

    /// Sets a new photo.
    ///
    /// # Arguments
    ///
    /// * `value` - Available sizes of the chat photo.
    pub fn with_photo<T>(mut self, value: T) -> Self
    where
        T: IntoIterator<Item = PhotoSize>,
    {
        self.photo = Some(value.into_iter().collect());
        self
    }

    /// Sets a new title.
    ///
    /// # Arguments
    ///
    /// * `value` - Title.
    pub fn with_title<T>(mut self, value: T) -> Self
    where
        T: Into<String>,
    {
        self.title = Some(value.into());
        self
    }

    /// Sets a new username.
    ///
    /// # Arguments
    ///
    /// * `value` - Username.
    pub fn with_username<T>(mut self, value: T) -> Self
    where
        T: Into<String>,
    {
        self.username = Some(value.into());
        self
    }
}

/// Represents an document message data.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct MessageDataDocument {
    /// Document data.
    #[serde(rename = "document")]
    pub data: Document,
    /// Document caption.
    #[serde(
        flatten,
        deserialize_with = "RawCaption::deserialize_value",
        serialize_with = "RawCaption::serialize_value"
    )]
    pub caption: Option<Text>,
}

impl From<Document> for MessageDataDocument {
    fn from(value: Document) -> Self {
        Self {
            data: value,
            caption: None,
        }
    }
}

impl MessageDataDocument {
    /// Sets a new caption.
    ///
    /// # Arguments
    ///
    /// * `value` - Caption; 0-1024 characters.
    pub fn with_caption<T>(mut self, value: T) -> Self
    where
        T: Into<Text>,
    {
        self.caption = Some(value.into());
        self
    }
}

/// Represents a service message about a new forum topic created in the chat.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct MessageDataForumTopicCreated {
    /// Color of the icon of the topic.
    pub icon_color: ForumTopicIconColor,
    /// Name of the topic.
    pub name: String,
    /// Unique identifier of the custom emoji shown as the topic icon.
    pub icon_custom_emoji_id: Option<String>,
    /// Whether the name of the topic wasn't specified explicitly by its creator
    /// and likely needs to be changed by the bot.
    pub is_name_implicit: Option<bool>,
}

impl MessageDataForumTopicCreated {
    /// Creates a new `MessageDataForumTopicCreated`.
    ///
    /// # Arguments
    ///
    /// * `icon_color` - Color of the icon.
    /// * `name` - Name of the topic.
    pub fn new<A, B>(icon_color: A, name: B) -> Self
    where
        A: Into<ForumTopicIconColor>,
        B: Into<String>,
    {
        Self {
            icon_color: icon_color.into(),
            name: name.into(),
            icon_custom_emoji_id: None,
            is_name_implicit: None,
        }
    }

    /// Sets a new icon custom emoji ID.
    ///
    /// # Arguments
    ///
    /// * `value` - Emoji ID.
    pub fn with_icon_custom_emoji_id<T>(mut self, value: T) -> Self
    where
        T: Into<String>,
    {
        self.icon_custom_emoji_id = Some(value.into());
        self
    }

    /// Sets a new value for the `is_name_implicit` flag.
    ///
    /// # Arguments
    ///
    /// `value` - Whether the name of the topic wasn't specified explicitly by its creator.
    pub fn with_is_name_implicit(mut self, value: bool) -> Self {
        self.is_name_implicit = Some(value);
        self
    }
}

/// Represents a service message about an edited forum topic.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct MessageDataForumTopicEdited {
    /// New name, if it was edited.
    pub name: Option<String>,
    /// New identifier of the custom emoji shown as the topic icon,
    /// if it was edited; an empty string if the icon was removed.
    pub icon_custom_emoji_id: Option<String>,
}

impl MessageDataForumTopicEdited {
    /// Sets a new name.
    ///
    /// # Arguments
    ///
    /// * `value` - The name of the topic.
    pub fn with_name<T>(mut self, value: T) -> Self
    where
        T: Into<String>,
    {
        self.name = Some(value.into());
        self
    }

    /// Sets a new icon custom emoji ID.
    ///
    /// # Arguments
    ///
    /// * `value` - Emoji ID.
    pub fn with_icon_custom_emoji_id<T>(mut self, value: T) -> Self
    where
        T: Into<String>,
    {
        self.icon_custom_emoji_id = Some(value.into());
        self
    }
}

/// Contains information about the bot that was created to be managed by the current bot.
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct MessageDataManagedBotCreated {
    /// Information about the bot.
    pub user: User,
}

/// Describes a service message about a change in the price of paid messages within a chat.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct MessageDataPaidMessagePriceChanged {
    /// The new number of Telegram Stars
    /// that must be paid by non-administrator users of the supergroup chat for each sent message.
    pub paid_message_star_count: Integer,
}

/// Describes a service message about a change in the price of direct messages sent to a channel chat.
#[serde_with::skip_serializing_none]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct MessageDataDirectMessagePriceChanged {
    /// Whether the direct messages are enabled for the channel chat.
    pub are_direct_messages_enabled: bool,
    /// The new number of Telegram Stars that must be paid by users for each direct message sent to the channel.
    ///
    /// Does not apply to users who have been exempted by administrators.
    /// Defaults to 0.
    pub direct_message_star_count: Option<Integer>,
}

impl MessageDataDirectMessagePriceChanged {
    /// Creates a new `MessageDataDirectMessagePriceChanged`.
    ///
    /// # Arguments
    ///
    /// * `are_direct_messages_enabled` - Whether the direct messages are enabled for the channel chat.
    pub fn new(are_direct_messages_enabled: bool) -> Self {
        Self {
            are_direct_messages_enabled,
            direct_message_star_count: None,
        }
    }

    /// Sets a new direct message star count.
    ///
    /// # Arguments
    ///
    /// * `value` - The new number of Telegram Stars.
    pub fn with_direct_message_star_count(mut self, value: Integer) -> Self {
        self.direct_message_star_count = Some(value);
        self
    }
}

/// Represents a live photo.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MessageDataLivePhoto {
    /// The live photo.
    #[serde(rename = "live_photo")]
    pub data: LivePhoto,
}

impl From<LivePhoto> for MessageDataLivePhoto {
    fn from(value: LivePhoto) -> Self {
        Self { data: value }
    }
}

impl From<MessageDataLivePhoto> for LivePhoto {
    fn from(value: MessageDataLivePhoto) -> Self {
        value.data
    }
}

/// Represents a list of available sizes of the photo.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct MessageDataPhoto {
    /// Photo sizes.
    #[serde(rename = "photo")]
    pub data: Vec<PhotoSize>,
    /// Photo caption.
    #[serde(
        flatten,
        deserialize_with = "RawCaption::deserialize_value",
        serialize_with = "RawCaption::serialize_value"
    )]
    pub caption: Option<Text>,
}

impl<T> From<T> for MessageDataPhoto
where
    T: IntoIterator<Item = PhotoSize>,
{
    fn from(value: T) -> Self {
        Self {
            data: value.into_iter().collect(),
            caption: None,
        }
    }
}

impl MessageDataPhoto {
    /// Sets a new caption.
    ///
    /// # Arguments
    ///
    /// * `value` - Caption; 0-1024 characters.
    pub fn with_caption<T>(mut self, value: T) -> Self
    where
        T: Into<Text>,
    {
        self.caption = Some(value.into());
        self
    }
}

/// Describes a service message about an option added to a poll.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MessageDataPollOptionAdded {
    /// Unique identifier of the added option.
    pub option_persistent_id: String,
    /// Option text.
    #[serde(
        flatten,
        deserialize_with = "RawPollOptionText::deserialize_value",
        serialize_with = "RawPollOptionText::serialize_value"
    )]
    pub option: Text,
    /// Message containing the poll to which the option was added, if known.
    pub poll_message: Option<MaybeInaccessibleMessage>,
}

/// Desribes a service message about an option deleted from a poll.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MessageDataPollOptionDeleted {
    /// Unique identifier of the deleted option.
    pub option_persistent_id: String,
    /// Option text.
    #[serde(
        flatten,
        deserialize_with = "RawPollOptionText::deserialize_value",
        serialize_with = "RawPollOptionText::serialize_value"
    )]
    pub option: Text,
    /// Message containing the poll from which the option was deleted, if known.
    pub poll_message: Option<MaybeInaccessibleMessage>,
}

/// Represents a content of a service message,
/// sent whenever a user in the chat triggers
/// a proximity alert set by another user.
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct MessageDataProximityAlert {
    /// The distance between the users.
    pub distance: Integer,
    /// User that triggered the alert.
    pub traveler: User,
    /// User that set the alert.
    pub watcher: User,
}

impl MessageDataProximityAlert {
    /// Creates a new `MessageDataProximityAlert`.
    ///
    /// # Arguments
    ///
    /// * `distance` - Distance between users.
    /// * `traveler` - User that triggered the alert.
    /// * `watcher` - User that set the alert.
    pub fn new(distance: Integer, traveler: User, watcher: User) -> Self {
        Self {
            distance,
            traveler,
            watcher,
        }
    }
}

/// Contains information about the users
/// whose identifiers were shared with the bot
/// using a [`crate::types::KeyboardButton::with_request_users`] button.
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct MessageDataUsersShared {
    /// Identifier of the request.
    pub request_id: Integer,
    /// Information about users shared with the bot.
    pub users: Vec<SharedUser>,
}

impl MessageDataUsersShared {
    /// Creates a new `MessageDataUsersShared`.
    ///
    /// # Arguments
    ///
    /// * `request_id` - Identifier of the request.
    /// * `users` - Information about users shared with the bot.
    pub fn new<T>(request_id: Integer, users: T) -> Self
    where
        T: IntoIterator<Item = SharedUser>,
    {
        Self {
            request_id,
            users: users.into_iter().collect(),
        }
    }
}

/// Represents a video message data.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct MessageDataVideo {
    /// Video data.
    #[serde(rename = "video")]
    pub data: Video,
    /// Video caption.
    #[serde(
        flatten,
        deserialize_with = "RawCaption::deserialize_value",
        serialize_with = "RawCaption::serialize_value"
    )]
    pub caption: Option<Text>,
}

impl From<Video> for MessageDataVideo {
    fn from(value: Video) -> Self {
        Self {
            data: value,
            caption: None,
        }
    }
}

impl MessageDataVideo {
    /// Sets a new caption.
    ///
    /// # Arguments
    ///
    /// * `value` - Caption; 0-1024 characters.
    pub fn with_caption<T>(mut self, value: T) -> Self
    where
        T: Into<Text>,
    {
        self.caption = Some(value.into());
        self
    }
}

/// Represents a service message about a video chat ended in the chat.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct MessageDataVideoChatEnded {
    /// Video chat duration; in seconds.
    pub duration: Integer,
}

impl MessageDataVideoChatEnded {
    /// Creates a new `MessageDataVideoChatEnded`.
    ///
    /// # Arguments
    ///
    /// * `duration` - Video chat duration; in seconds.
    pub fn new(duration: Integer) -> Self {
        Self { duration }
    }
}

/// A service message about new members invited to a video chat.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct MessageDataVideoChatParticipantsInvited {
    /// New members that were invited to the voice chat.
    pub users: Option<Vec<User>>,
}

impl<T> From<T> for MessageDataVideoChatParticipantsInvited
where
    T: IntoIterator<Item = User>,
{
    fn from(value: T) -> Self {
        Self::default().with_users(value)
    }
}

impl MessageDataVideoChatParticipantsInvited {
    /// Sets a new list of users.
    ///
    /// # Arguments
    ///
    /// * `value` - New members that were invited to the voice chat.
    pub fn with_users<T>(mut self, value: T) -> Self
    where
        T: IntoIterator<Item = User>,
    {
        self.users = Some(value.into_iter().collect());
        self
    }
}

/// A service message about a video chat scheduled in the chat.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct MessageDataVideoChatScheduled {
    /// Point in time (Unix timestamp) when the video chat
    /// is supposed to be started by a chat administrator.
    pub start_date: Integer,
}

impl MessageDataVideoChatScheduled {
    /// Creates a new `MessageDataVideoChatScheduled`
    ///
    /// # Arguments
    ///
    /// * `start_date` - Point in time (Unix timestamp).
    pub fn new(start_date: Integer) -> Self {
        Self { start_date }
    }
}

/// Message is a voice message, information about the file.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct MessageDataVoice {
    /// Voice data.
    #[serde(rename = "voice")]
    pub data: Voice,
    /// Voice caption.
    #[serde(
        flatten,
        deserialize_with = "RawCaption::deserialize_value",
        serialize_with = "RawCaption::serialize_value"
    )]
    pub caption: Option<Text>,
}

impl From<Voice> for MessageDataVoice {
    fn from(value: Voice) -> Self {
        Self {
            data: value,
            caption: None,
        }
    }
}

impl MessageDataVoice {
    /// Sets a new caption.
    ///
    /// # Arguments
    ///
    /// * `value` - Caption; 0-1024 characters.
    pub fn with_caption<T>(mut self, value: T) -> Self
    where
        T: Into<Text>,
    {
        self.caption = Some(value.into());
        self
    }
}

/// Represents a service message about a user allowing a bot to write messages
/// after adding it to the attachment menu,
/// launching a Web App from a link,
/// or accepting an explicit request from a Web App
/// sent by the method `requestWriteAccess`.
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Default, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct MessageDataWriteAccess {
    /// Indicates whether access was granted when the bot was added to the attachment or side menu.
    pub from_attachment_menu: Option<bool>,
    /// Indicates whether access was granted after the user accepted an explicit request
    /// from a Web App sent by the method `requestWriteAccess`.
    pub from_request: Option<bool>,
    /// Name of the Web App,
    /// if the access was granted when the Web App was launched from a link.
    pub web_app_name: Option<String>,
}

impl MessageDataWriteAccess {
    /// Sets a new value of the `from_attachment_menu` flag.
    ///
    /// * `value` - Indicates whether access was granted
    ///   when the bot was added to the attachment
    ///   or side menu.
    pub fn with_from_attachment_menu(mut self, value: bool) -> Self {
        self.from_attachment_menu = Some(value);
        self
    }

    /// Sets a new value of the `from_request` flag.
    ///
    /// * `value` - Indicates whether access was granted after the user accepted an explicit request
    ///   from a Web App sent by the method `requestWriteAccess`.
    pub fn with_from_request(mut self, value: bool) -> Self {
        self.from_request = Some(value);
        self
    }

    /// Sets a new name of the Web App.
    ///
    /// # Arguments
    ///
    /// * `value` - Name of the Web App.
    pub fn with_web_app_name<T>(mut self, value: T) -> Self
    where
        T: Into<String>,
    {
        self.web_app_name = Some(value.into());
        self
    }
}
