use std::io;
use std::io::Error;
use crate::analyze::AnalyzeEmails;
#[cfg(any(feature = "imap"))]
use crate::imap::Imap;
#[cfg(any(feature = "pop3"))]
use crate::pop3::Pop3;
#[cfg(any(feature = "smtp"))]
use crate::smtp::Smtp;

#[cfg(any(feature = "pop3"))]
mod pop3;
#[cfg(any(feature = "imap"))]
mod imap;
#[cfg(any(feature = "smtp"))]
mod smtp;

pub mod analyze;


#[derive(Clone, Debug)]
pub struct Mail {
    /// 协议
    protocol: Protocol,
    /// 邮件地址
    host: String,
    /// 邮件端口
    port: u16,
    /// 邮件名称
    name: String,
    /// 邮件账号
    mail: String,
    /// 邮件密码
    pass: String,
}

impl Mail {
    pub fn new(protocol: &str, host: &str, port: u16, name: &str, mail: &str, pass: &str) -> Self {
        Self {
            protocol: Protocol::from(protocol),
            host: host.to_string(),
            port,
            name: name.to_string(),
            mail: mail.to_string(),
            pass: pass.to_string(),
        }
    }
    /// 解析邮件
    pub fn analyze(data: Vec<u8>, debug: bool) -> io::Result<AnalyzeEmails> {
        AnalyzeEmails::new(data, debug)
    }
    /// 接收
    pub fn receive(&mut self) -> Box<dyn Receive> {
        match self.protocol {
            #[cfg(any(feature = "pop3"))]
            Protocol::POP3 => Box::new(Pop3::new(self.host.clone(), self.port.clone(), self.name.clone(), self.mail.clone(), self.pass.clone())),
            #[cfg(any(feature = "smtp"))]
            Protocol::SMTP => Box::new(Smtp::new(self.host.clone(), self.port.clone(), self.name.clone(), self.mail.clone(), self.pass.clone())),
            #[cfg(any(feature = "imap"))]
            Protocol::IMAP => Box::new(Imap::new(self.host.clone(), self.port.clone(), self.name.clone(), self.mail.clone(), self.pass.clone())),
            _ => todo!()
        }
    }
    /// 发送
    pub fn sender(&mut self) -> Box<dyn Sender> {
        match self.protocol {
            #[cfg(any(feature = "pop3"))]
            Protocol::POP3 => Box::new(Pop3::new(self.host.clone(), self.port.clone(), self.name.clone(), self.mail.clone(), self.pass.clone())),
            #[cfg(any(feature = "smtp"))]
            Protocol::SMTP => Box::new(Smtp::new(self.host.clone(), self.port.clone(), self.name.clone(), self.mail.clone(), self.pass.clone())),
            #[cfg(any(feature = "imap"))]
            Protocol::IMAP => Box::new(Imap::new(self.host.clone(), self.port.clone(), self.name.clone(), self.mail.clone(), self.pass.clone())),
            _ => todo!()
        }
    }
}

pub trait Receive {
    /// 获取邮件总数
    fn get_total(&mut self) -> Result<usize, Error>;
    /// 获取指定量ID列表
    fn get_id_list(&mut self) -> Result<Vec<String>, Error>;
    /// 获取指定ID邮件
    /// 返回 (邮件内容,邮件尺寸,邮件指纹)
    fn get_id_info(&mut self, id: &str) -> Result<(Vec<u8>, usize, String), Error>;
    /// 删除指定邮件
    fn del_id(&mut self, id: &str) -> Result<bool, Error>;
}

pub trait Sender {
    /// 发送邮件
    /// 返回 (邮件内容,邮件尺寸,邮件指纹)
    fn send(&mut self) -> Result<(Vec<u8>, usize, String), Error>;

    /// 设置发件人信息
    /// * name 发件人名称
    /// * mail 发件箱
    fn set_from(&mut self, name: &str) -> &mut dyn Sender;

    /// 收件人
    /// * name 收件人名称
    /// * mail 收件箱
    fn set_to(&mut self, name: &str, mail: &str) -> &mut dyn Sender;
    /// 抄送人
    /// * name 抄送人名称
    /// * mail 收件箱
    fn set_cc(&mut self, name: &str, mail: &str) -> &mut dyn Sender;
    /// 设置主题
    fn set_subject(&mut self, subject: &str) -> &mut dyn Sender;
    /// 设置内容
    fn set_body(&mut self, text: &str, html: &str) -> &mut dyn Sender;
    /// 设置文件
    fn set_file(&mut self, name: &str, data: Vec<u8>, content_type: &str) -> &mut dyn Sender;
}

#[derive(Clone, Debug)]
enum Protocol {
    POP3,
    SMTP,
    IMAP,
    None,
}

impl Protocol {
    pub fn from(name: &str) -> Self {
        let name = name.to_lowercase();
        match name.as_str() {
            "pop3" => Protocol::POP3,
            "imap" => Protocol::IMAP,
            "smtp" => Protocol::SMTP,
            _ => Protocol::None,
        }
    }
}