use std::fs;
use std::thread::sleep;
use br_crypto::{base64, qp, sha};
use chrono::{DateTime, Utc};
use json::{JsonValue, object};

#[derive(Clone, Debug)]
pub struct MailHead {
    email: String,
    email_type: String,
    head_list: Vec<String>,

    from_name: String,
    from_mail: String,
    from_tail: String,
    subject: String,

    to_arr: Vec<JsonValue>,
    cc_arr: Vec<JsonValue>,

    reply_to_name: String,
    reply_to_mail: String,

    version: String,
    date: String,
    timestamp: String,

    content_type: String,
    charset: String,
    encoding: String,
    pub boundary: String,
    mail_sha: String,
}

impl MailHead {
    pub fn new(mail_data: &str, email: &str) -> Self {
        let mail_list: Vec<&str> = mail_data.split("\r\n\r\n").collect();
        let head_list: Vec<String> = mail_list[0].split("\r\n").map(|x| x.to_string()).collect();

        Self {
            email: email.to_string(),
            email_type: "".to_string(),
            head_list,

            from_name: "".to_string(),
            from_mail: "".to_string(),
            from_tail: "".to_string(),
            subject: "".to_string(),

            to_arr: vec![],
            cc_arr: vec![],

            reply_to_name: "".to_string(),
            reply_to_mail: "".to_string(),

            version: "".to_string(),
            date: "".to_string(),
            timestamp: "".to_string(),

            content_type: "".to_string(),
            charset: "".to_string(),
            encoding: "".to_string(),
            boundary: "".to_string(),
            mail_sha: "".to_string(),
        }
    }

    pub fn default() -> Self {
        Self {
            email: "".to_string(),
            email_type: "".to_string(),
            head_list: vec![],
            from_name: "".to_string(),
            from_mail: "".to_string(),
            from_tail: "".to_string(),
            subject: "".to_string(),
            to_arr: vec![],
            cc_arr: vec![],
            reply_to_name: "".to_string(),
            reply_to_mail: "".to_string(),
            version: "".to_string(),
            date: "".to_string(),
            timestamp: "".to_string(),
            content_type: "".to_string(),
            charset: "".to_string(),
            encoding: "".to_string(),
            boundary: "".to_string(),
            mail_sha: "".to_string(),
        }
    }

    /// 对邮件头的第一次格式化处理
    /// 去掉邮件头中的空数组, 以"X-"开头的字段, 以及将以\t或空格开头的字段进行与上一行拼接并删除
    pub fn remove_head_trash(&mut self) {
        let mut item = 0;
        let mut index = 0;
        let temp = self.head_list.clone();
        for cell in temp {
            if cell.trim().is_empty() {
                self.head_list.remove(index);
            } else {
                index += 1;
            }
        }
        index = 0;
        let mut list = "".to_string();
        let data = self.head_list.clone();
        for head in data.iter() {
            if &head.as_str()[0..1] == "\t" {
                list = format!("{} {}", list.clone(), head.trim_start_matches("\t"));
                self.head_list[item] = list.clone();
            } else if &head.as_str()[0..1] == " " {
                list = format!("{} {}", list.clone(), head.trim_start_matches(" "));
                self.head_list[item] = list.clone();
            } else {
                item = index;
                list = head.to_string();
            }
            index += 1;
        }
        self.head_list.retain(|x| &x.as_str()[0..1] != "\t");
        self.head_list.retain(|x| &x.as_str()[0..1] != " ");
        self.head_list.retain(|x| &x.as_str()[0..2] != "X-");
    }

    /// 获取邮件主题 Subject
    pub fn get_subject(&mut self) {
        let mut temp_head = self.head_list.clone();
        let mut all_subject = String::new();
        for item in temp_head.iter_mut() {
            if item.starts_with("Subject:") {
                let data = item.trim_start_matches("Subject:").trim();
                let (state, _) = MailHead::get_charset(item.to_string());
                if state {
                    if data.contains(" ") {
                        let sub_vec: Vec<&str> = data.trim().split(" ").collect();
                        for cell in sub_vec {
                            let temp_vec: Vec<&str> = cell.split("?").collect();
                            let part_subject = MailHead::get_decode_method(temp_vec[1], temp_vec[2], temp_vec[3]);
                            all_subject.push_str(part_subject.as_str());
                        }
                    } else {
                        let temp_vec: Vec<&str> = data.split("?").collect();
                        all_subject = MailHead::get_decode_method(temp_vec[1], temp_vec[2], temp_vec[3]);
                    }
                } else {
                    all_subject = data.to_string();
                }
                self.subject = all_subject.clone();
                item.clear();
                break;
            }
        }
        self.head_list = temp_head;
    }

    /// 获取邮件的发送人 From
    pub fn get_from(&mut self) {
        let mut temp_head = self.head_list.clone();
        for item in temp_head.iter_mut() {
            if item.starts_with("From:") {
                let data = item.trim_start_matches("From:").trim();
                if data.contains("<") {
                    let mut from_list: Vec<&str> = data.trim().split("<").collect();
                    if from_list[0].is_empty() {
                        self.from_mail = from_list[1].trim().trim_end_matches(">").to_string();
                        self.from_name = self.from_mail.clone();
                    } else {
                        let (state, _) = MailHead::get_charset(from_list[0].to_string());
                        if state {
                            let name_vec: Vec<&str> = from_list[0].split("?").collect();
                            self.from_name = MailHead::get_decode_method(name_vec[1], name_vec[2], name_vec[3]);
                        } else {
                            self.from_name = from_list[0].trim().trim_start_matches('"').trim_end_matches('"').to_string();
                        }
                        self.from_mail = from_list[1].trim().trim_end_matches(">").to_string();
                    }
                } else {
                    self.from_mail = data.trim().to_string();
                    self.from_name = self.from_mail.clone();
                }
                item.clear();
                let tail: Vec<&str> = self.from_mail.split("@").collect();
                self.from_tail = tail[tail.len() - 1].to_string();
                break;
            }
        }
        self.head_list = temp_head;
    }

    /// 获取该封邮件对于该账号是收件还是发件
    pub fn get_email_type(&mut self) {
        if self.email.eq(&self.from_mail) {
            self.email_type = "发件".to_string();
        } else {
            self.email_type = "收件".to_string();
        }
    }

    /// 获取邮件的收件人 To
    pub fn get_to(&mut self) {
        let mut temp_head = self.head_list.clone();
        for item in temp_head.iter_mut() {
            if item.starts_with("To:") {
                let data = item.trim_start_matches("To:").trim();
                let mut to_vec: Vec<&str> = Vec::new();
                if data.contains(",") {
                    to_vec = data.split(",").collect();
                } else {
                    to_vec.push(data);
                }
                for cell in to_vec {
                    if !cell.contains("<") {
                        let to_mail = cell.trim();
                        let temp = object! { [&to_mail]: to_mail };
                        self.to_arr.push(temp);
                    } else {
                        let mut to_list: Vec<&str> = cell.split("<").collect();
                        let (state, _) = MailHead::get_charset(to_list[0].to_string());
                        let mut to_name = String::new();
                        if state {
                            let name_vec: Vec<&str> = to_list[0].split("?").collect();
                            to_name = MailHead::get_decode_method(name_vec[1], name_vec[2], name_vec[3]);
                        } else {
                            to_name = to_list[0].trim().trim_start_matches('"').trim_end_matches('"').to_string();
                        }
                        let to_mail = to_list[1].trim().trim_end_matches(">").to_string();
                        let temp = object! { [&to_name]: to_mail };
                        self.to_arr.push(temp);
                    }
                    item.clear();
                    break;
                }
            }
        }
        self.head_list = temp_head;
    }

    /// 获取邮件的抄送人 Cc
    pub fn get_cc(&mut self) {
        let mut temp_head = self.head_list.clone();
        for item in temp_head.iter_mut() {
            if item.starts_with("Cc:") {
                let data = item.trim_start_matches("Cc:").trim();
                let mut cc_vec: Vec<&str> = Vec::new();
                if data.contains(",") {
                    cc_vec = data.split(",").collect();
                } else {
                    cc_vec.push(data);
                }
                for cell in cc_vec {
                    let mut cc_list: Vec<&str> = cell.split("<").collect();
                    let (state, _) = MailHead::get_charset(cc_list[0].to_string());
                    let mut cc_name = String::new();
                    if state {
                        let name_vec: Vec<&str> = cc_list[0].split("?").collect();
                        cc_name = MailHead::get_decode_method(name_vec[1], name_vec[2], name_vec[3]);
                    } else {
                        cc_name = cc_list[0].trim().trim_start_matches('"').trim_end_matches('"').to_string();
                    }
                    let cc_mail = cc_list[1].trim().trim_end_matches(">").to_string();
                    let temp = object! { [&cc_name]: cc_mail };
                    self.cc_arr.push(temp);
                }
                item.clear();
                break;
            }
        }
        self.head_list = temp_head;
    }

    /// 获取邮件格式版本 Version
    pub fn get_version(&mut self) {
        for item in self.head_list.iter_mut() {
            if item.to_lowercase().starts_with("mime-version:") {
                self.version = item.to_lowercase().trim_start_matches("mime-version:").trim().to_string();
                item.clear();
                break;
            }
        }
    }

    /// 获取邮件时间,时间戳 Date,Timestamp
    pub fn get_date(&mut self) {
        for item in self.head_list.iter_mut() {
            if item.to_lowercase().starts_with("date:") {
                self.date = item.to_lowercase().trim_start_matches("date:").trim().to_string();
                item.clear();
                break;
            }
        }
        match DateTime::parse_from_rfc2822(self.date.as_str()) {
            Ok(e) => {
                //将获取到的时间转换为utc标准时间, 显示标准时间转换后的时间戳
                self.timestamp = e.with_timezone(&Utc).timestamp_millis().to_string();
            }
            Err(_) => {
                println!("Error parsing date string: {}", self.date);
            }
        }
    }

    /// 获取邮件头中的格式相关信息 Content-Type,Charset
    pub fn get_content_type(&mut self) {
        let mut temp_head = self.head_list.clone();
        for item in temp_head.iter_mut() {
            if item.starts_with("Content-Type:") {
                let data = item.trim_start_matches("Content-Type:").trim().to_string();
                let temp_vec: Vec<&str> = data.split(";").collect();
                self.content_type = temp_vec[0].to_lowercase().trim().to_string();
                self.charset = MailHead::get_charset(temp_vec[temp_vec.len() - 1].to_string()).1.to_string();
                if item.contains("boundary") {
                    self.boundary = temp_vec[temp_vec.len() - 1].trim().trim_start_matches("boundary=").trim_start_matches('"').trim_end_matches('"').to_string();
                }
                item.clear();
                break;
            }
        }
        self.head_list = temp_head;
    }

    /// 获取邮件头中的加密方式 Content-Transfer-Encoding
    pub fn get_head_encoding(&mut self) {
        for item in self.head_list.iter_mut() {
            if item.starts_with("Content-Transfer-Encoding:") {
                self.encoding = item.trim_start_matches("Content-Transfer-Encoding:").trim().to_string();
                item.clear();
                break;
            }
        }
    }

    /// 获取邮件发件人IP并将其转为哈希编码 Mail-Sha
    pub fn get_mail_sha(&mut self) {
        let mut temp_head = self.head_list.clone();
        for item in temp_head.iter_mut() {
            if item.starts_with("Received:") && item.contains("[") {
                let mut temp_vec: Vec<&str> = item.split("[").collect();
                temp_vec = temp_vec[temp_vec.len() - 1].split("]").collect();
                self.mail_sha = sha::str_to_sha256(temp_vec[0]);
                item.clear();
                break;
            }
        }
        self.head_list = temp_head;
    }

    /// 获取邮件的回复地址 Reply-To (暂时不写)
    pub fn get_reply(&mut self) {}

    /// 获取解码格式
    /// * text: String
    /// * 需要传入包含解码格式的字段
    /// * 返回值为字符数组(解码格式, 是否可解)
    /// * 解码格式other为在判断外的其他格式, none则是未发现解码格式
    fn get_charset(text: String) -> (bool, &'static str) {
        let t1 = text.to_lowercase();
        return if t1.contains("utf-8") || t1.contains("utf8") {
            (true, "utf-8")
        } else if t1.contains("gb2312") {
            (true, "gb2312")
        } else if t1.contains("gbk") {
            (true, "gbk")
        } else if t1.contains("gb18030") {
            (true, "gb18030")
        } else {
            if t1.contains("charset") {
                (false, "other")
            } else {
                (false, "none")
            }
        };
    }

    /// 根据加密方式指定解码某一段文字
    /// * charset: String, code: String, body: String
    /// * 编码方式, 加密方式, 待解码解密的内容
    /// * 返回值为解码后的String类型字符串
    fn get_decode_method(charset: &str, code: &str, body: &str) -> String { // =?utf-8?B?5p2o5rab?=
        let mut final_result = String::new();
        match code.to_lowercase().as_str() {
            "quoted-printable" | "q" => final_result = qp::decode(body),
            "base64" | "b" => {
                let mut temp: Vec<&str> = body.trim().split("\r\n").collect();
                let text = temp.join("");
                final_result = base64::decode_code(text.to_string(), charset)
            }
            _ => println!("can't find decode method!")
        }
        final_result
    }
}

pub struct Mail {
    head: MailHead,

    all_body: String,
    body_set: String,
    body_charset: String,
    final_body: Vec<String>,
    by: String,
    message_id: String,

    boundary: String,
    boundary_mid: String,
    boundary_end: String,

    encoding: String,

    attachment: Vec<String>,
    attachment_body: Vec<Vec<String>>,
    bd_flag: i32,
}

impl Mail {
    pub fn new(mail_data: &str) -> Self {
        let mail_list: Vec<&str> = mail_data.split("\r\n\r\n").collect();
        let head_list: Vec<String> = mail_list[0].split("\r\n").map(|x| x.to_string()).collect();

        Self {
            head: MailHead::default(),
            all_body: "".to_string(),
            body_set: "".to_string(),
            body_charset: "".to_string(),
            final_body: vec![],
            by: "".to_string(),
            message_id: "".to_string(),
            boundary: "".to_string(),
            boundary_mid: "".to_string(),
            boundary_end: "".to_string(),
            encoding: "".to_string(),
            attachment: vec![],
            attachment_body: vec![],
            bd_flag: 0,
        }
    }
}

