//! The SMS plugin allows sending and receiving SMS/MMS messages.
use serde::{Deserialize, Serialize};

#[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec};

/// An object representing a phone number or other contact method.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SmsAddress {
    /// A free-form address string. Usually a phone number or e-mail address.
    pub address: String,
}

/// A file attachment. Send the part_id and unique_identifier with a
/// kdeconnect.sms.request_attachment packet to transfer the full file.
#[derive(Serialize, Deserialize, Debug, Clone)]
// NOTE: in this structure, every field is using snake_case instead of camelCase
pub struct SmsAttachment {
    /// The ID of the attachment.
    pub part_id: u64,

    /// The mime-type of the attachment.
    pub mime_type: String,

    /// A base64 encoded preview of the attachment.
    pub encoded_thumbnail: String,

    /// Unique name of the file.
    pub unique_identifier: String,
}

/// A message attachment which will be sent.
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SmsOutgoingAttachment {
    /// A file name.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub file_name: Option<String>,

    /// Base64 encoded data.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub base64_encoded_file: Option<String>,

    /// A mime-type string.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub mime_type: Option<String>,
}

/// A message object.
#[derive(Serialize, Deserialize, Debug, Clone)]
// NOTE: in this structure, every field is using snake_case instead of camelCase
pub struct SmsMessage {
    /// The message ID.
    #[serde(rename = "_id")]
    pub id: u64,

    /// A list of participating contacts. If the message is incoming, the first Address will be
    /// the sender. If the message is outgoing, every Address will be a recipient.
    pub addresses: Vec<SmsAddress>,

    /// A list of message attachments.
    pub attachments: Vec<SmsAttachment>,

    /// The message body.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub body: Option<String>,

    /// A UNIX epoch timestamp (ms) for the message.
    pub date: u64,

    /// The event type. 1 for 'text', 2 for 'multi-target'.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub event: Option<u8>,

    /// Whether the message is read or not.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub read: Option<u8>,

    /// The SIM card or subscription ID.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub sub_id: Option<u64>,

    /// The thread ID.
    pub thread_id: u64,

    /// The message status. Typically either 1 (inbox) or 2 (sent).
    /// See Android's Telephony.TextBasedSmsColumns message type enumeration.
    #[serde(rename = "type")]
    pub type_: u8,
}

/// This packet is a message attachment transfer.
///
/// <https://invent.kde.org/network/kdeconnect-meta/blob/master/protocol.md#kdeconnectsmsattachment_file>
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SmsAttachmentFilePacket {
    /// The name of the file being transferred.
    pub filename: String,
}

/// This packet is a list of messages.
///
/// <https://invent.kde.org/network/kdeconnect-meta/blob/master/protocol.md#kdeconnectsmsmessages>
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SmsMessagesPacket {
    /// A list of messages.
    pub messages: Vec<SmsMessage>,

    /// The version of SMS protocol in use.
    pub version: u64,
}

/// This packet is a request to send an SMS/MMS message.
///
/// <https://invent.kde.org/network/kdeconnect-meta/blob/master/protocol.md#kdeconnectsmsrequest>
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SmsRequestPacket {
    /// A list of target contacts.
    pub addresses: Vec<SmsAddress>,

    /// A list of message attachments to send.
    pub attachments: Vec<SmsOutgoingAttachment>,

    /// The message body.
    pub message_body: String,

    /// The SIM card or account to send with.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub sub_id: Option<u64>,

    /// The version of SMS protocol in use.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub version: Option<u64>,
}

/// This packet is a request for a message attachment.
///
/// <https://invent.kde.org/network/kdeconnect-meta/blob/master/protocol.md#kdeconnectsmsrequestattachment>
#[derive(Serialize, Deserialize, Debug, Clone)]
// NOTE: in this structure, every field is using snake_case instead of camelCase
pub struct SmsRequestAttachmentPacket {
    /// The ID of the attachment.
    pub part_id: u64,

    /// Unique name of the file.
    pub unique_identifier: String,
}

/// This packet is a request for messages from a thread.
///
/// <https://invent.kde.org/network/kdeconnect-meta/blob/master/protocol.md#kdeconnectsmsrequestconversation>
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SmsRequestConversationPacket {
    /// The thread ID.
    #[serde(rename = "threadID")]
    pub thread_id: u64,

    /// UNIX epoch timestamp (ms) for the earliest message.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub range_start_timestamp: Option<u64>,

    /// The maximum number of messages to return.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub number_to_request: Option<u64>,
}
