#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Request<'a>(pub &'a [u8], pub &'a [u8]);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AttrMacro {
    All,
    Fast,
    Full,
}
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Response<'a> {
    Capabilities(Vec<Capability<'a>>),
    Continue {
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Done {
        tag: RequestId,
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Data {
        status: Status,
        code: Option<ResponseCode<'a>>,
        information: Option<&'a str>,
    },
    Expunge(u32),
    Vanished {
        earlier: bool,
        uids: Vec<std::ops::RangeInclusive<u32>>,
    },
    Fetch(u32, Vec<AttributeValue<'a>>),
    MailboxData(MailboxDatum<'a>),
}
impl<'a> Response<'a> {
    pub fn from_bytes(buf: &'a [u8]) -> crate::ParseResult {
        crate::parser::parse_response(buf)
    }
}
#[derive(Debug, Eq, PartialEq)]
pub enum Status {
    Ok,
    No,
    Bad,
    PreAuth,
    Bye,
}
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ResponseCode<'a> {
    Alert,
    BadCharset(Option<Vec<&'a str>>),
    Capabilities(Vec<Capability<'a>>),
    HighestModSeq(u64), 
    Parse,
    PermanentFlags(Vec<&'a str>),
    ReadOnly,
    ReadWrite,
    TryCreate,
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
}
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum StatusAttribute {
    HighestModSeq(u64), 
    Messages(u32),
    Recent(u32),
    UidNext(u32),
    UidValidity(u32),
    Unseen(u32),
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Metadata {
    pub entry: String,
    pub value: Option<String>,
}
#[derive(Debug, Eq, PartialEq)]
pub enum MailboxDatum<'a> {
    Exists(u32),
    Flags(Vec<&'a str>),
    List {
        flags: Vec<&'a str>,
        delimiter: Option<&'a str>,
        name: &'a str,
    },
    Search(Vec<u32>),
    Status {
        mailbox: &'a str,
        status: Vec<StatusAttribute>,
    },
    Recent(u32),
    MetadataSolicited {
        mailbox: &'a str,
        values: Vec<Metadata>,
    },
    MetadataUnsolicited {
        mailbox: &'a str,
        values: Vec<&'a str>,
    },
}
#[derive(Debug, Eq, PartialEq, Hash)]
pub enum Capability<'a> {
    Imap4rev1,
    Auth(&'a str),
    Atom(&'a str),
}
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Attribute {
    Body,
    Envelope,
    Flags,
    InternalDate,
    ModSeq, 
    Rfc822,
    Rfc822Size,
    Rfc822Text,
    Uid,
}
#[derive(Debug, Eq, PartialEq)]
pub enum MessageSection {
    Header,
    Mime,
    Text,
}
#[derive(Debug, Eq, PartialEq)]
pub enum SectionPath {
    Full(MessageSection),
    Part(Vec<u32>, Option<MessageSection>),
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum AttributeValue<'a> {
    BodySection {
        section: Option<SectionPath>,
        index: Option<u32>,
        data: Option<&'a [u8]>,
    },
    BodyStructure(BodyStructure<'a>),
    Envelope(Box<Envelope<'a>>),
    Flags(Vec<&'a str>),
    InternalDate(&'a str),
    ModSeq(u64), 
    Rfc822(Option<&'a [u8]>),
    Rfc822Header(Option<&'a [u8]>),
    Rfc822Size(u32),
    Rfc822Text(Option<&'a [u8]>),
    Uid(u32),
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Eq, PartialEq)]
pub enum BodyStructure<'a> {
    Basic {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        extension: Option<BodyExtension<'a>>,
    },
    Text {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Message {
        common: BodyContentCommon<'a>,
        other: BodyContentSinglePart<'a>,
        envelope: Envelope<'a>,
        body: Box<BodyStructure<'a>>,
        lines: u32,
        extension: Option<BodyExtension<'a>>,
    },
    Multipart {
        common: BodyContentCommon<'a>,
        bodies: Vec<BodyStructure<'a>>,
        extension: Option<BodyExtension<'a>>,
    },
}
#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentCommon<'a> {
    pub ty: ContentType<'a>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
}
#[derive(Debug, Eq, PartialEq)]
pub struct BodyContentSinglePart<'a> {
    pub id: Option<&'a str>,
    pub md5: Option<&'a str>,
    pub description: Option<&'a str>,
    pub transfer_encoding: ContentEncoding<'a>,
    pub octets: u32,
}
#[derive(Debug, Eq, PartialEq)]
pub struct ContentType<'a> {
    pub ty: &'a str,
    pub subtype: &'a str,
    pub params: BodyParams<'a>,
}
#[derive(Debug, Eq, PartialEq)]
pub struct ContentDisposition<'a> {
    pub ty: &'a str,
    pub params: BodyParams<'a>,
}
#[derive(Debug, Eq, PartialEq)]
pub enum ContentEncoding<'a> {
    SevenBit,
    EightBit,
    Binary,
    Base64,
    QuotedPrintable,
    Other(&'a str),
}
#[derive(Debug, Eq, PartialEq)]
pub enum BodyExtension<'a> {
    Num(u32),
    Str(Option<&'a str>),
    List(Vec<BodyExtension<'a>>),
}
pub type BodyParams<'a> = Option<Vec<(&'a str, &'a str)>>;
#[derive(Debug, Eq, PartialEq)]
pub struct Envelope<'a> {
    pub date: Option<&'a [u8]>,
    pub subject: Option<&'a [u8]>,
    pub from: Option<Vec<Address<'a>>>,
    pub sender: Option<Vec<Address<'a>>>,
    pub reply_to: Option<Vec<Address<'a>>>,
    pub to: Option<Vec<Address<'a>>>,
    pub cc: Option<Vec<Address<'a>>>,
    pub bcc: Option<Vec<Address<'a>>>,
    pub in_reply_to: Option<&'a [u8]>,
    pub message_id: Option<&'a [u8]>,
}
#[derive(Debug, Eq, PartialEq)]
pub struct Address<'a> {
    pub name: Option<&'a [u8]>,
    pub adl: Option<&'a [u8]>,
    pub mailbox: Option<&'a [u8]>,
    pub host: Option<&'a [u8]>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RequestId(pub String);
impl RequestId {
    pub fn as_bytes(&self) -> &[u8] {
        self.0.as_bytes()
    }
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum State {
    NotAuthenticated,
    Authenticated,
    Selected,
    Logout,
}
pub struct BodyFields<'a> {
    pub param: BodyParams<'a>,
    pub id: Option<&'a str>,
    pub description: Option<&'a str>,
    pub transfer_encoding: ContentEncoding<'a>,
    pub octets: u32,
}
pub struct BodyExt1Part<'a> {
    pub md5: Option<&'a str>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
    pub extension: Option<BodyExtension<'a>>,
}
pub struct BodyExtMPart<'a> {
    pub param: BodyParams<'a>,
    pub disposition: Option<ContentDisposition<'a>>,
    pub language: Option<Vec<&'a str>>,
    pub location: Option<&'a str>,
    pub extension: Option<BodyExtension<'a>>,
}