Documentation
use std::fs;
use json::{array, JsonValue, object};
use lazy_static::lazy_static;
use crate::Connection;
use crate::mode::{OcrMode};

use std::sync::Mutex;
use std::collections::HashMap;
use br_crypto::encoding::urlencoding_encode;
use br_http::FormData;
use chrono::Local;
lazy_static! {
    static ref ACCESS_TOKEN: Mutex<HashMap<String,JsonValue>> =Mutex::new(HashMap::new());
}

#[derive(Clone)]
pub struct Baidu {
    pub appid: String,
    pub secret: String,
    pub access_token: String,
    pub expires_in: i64,
}

impl Baidu {
    pub fn new(connection: Connection) -> Self {
        Self {
            appid: connection.appid,
            secret: connection.secret,
            access_token: "".to_string(),
            expires_in: 0,
        }
    }
    pub fn get_access_token(&mut self) -> String {
        let dt = Local::now();
        let timestamp = dt.timestamp_millis();
        if self.expires_in > timestamp {
            return self.access_token.clone();
        }

        let url = format!("https://aip.baidubce.com/oauth/2.0/token?client_id={}&client_secret={}&grant_type=client_credentials", self.appid, self.secret);

        let mut http = br_http::Http::new();
        let http = http.post(url.as_str()).header("Accept", "application/json").form_urlencoded(object! {});
        let res = http.json().unwrap();
        if res["access_token"].is_empty() {
            return self.access_token.clone();
        }
        self.access_token = res["access_token"].to_string();
        self.expires_in = timestamp + res["expires_in"].as_i64().unwrap();
        ACCESS_TOKEN.lock().unwrap().insert(self.appid.clone(), object! {
               access_token: self.access_token.clone(),
               expires_in:self.expires_in
            });
        self.access_token.clone()
    }
}

impl OcrMode for Baidu {
    fn ocr(&mut self, file_path: &str, file_b64: &str) -> JsonValue {
        self.get_access_token();

        // let file_base64 = fs::read(file_path).unwrap();
        // let file_base64 = br_crypto::base64::encode_file(file_base64);

        // 文件地址和文件加密后的b64字符串这两个参数二选一
        let file_base64: String = if file_b64.is_empty() {
            let file_data = fs::read(file_path).unwrap();
            br_crypto::base64::encode_file(file_data)
        } else {
            file_b64.to_string()
        };

        let _image = urlencoding_encode(file_base64.as_str());

        let url = format!("https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token={}", self.access_token);

        let mut http = br_http::Http::new();

        let tt = vec![
            FormData::File("image".to_string(), file_base64,"".to_string()),
            FormData::Text("detect_direction".parse().unwrap(), "true".into(),"".to_string()),
            FormData::Text("paragraph".parse().unwrap(), "false".into(),"".to_string()),
            FormData::Text("probability".parse().unwrap(), "false".into(),"".to_string())
        ];

        let http = http.post(url.as_str())
            .header("Accept", "application/json")
            .form_data(tt);
        let res = http.json().unwrap();
        if res["words_result"].is_empty() {
            return array![];
        }
        let mut list = vec![];
        for item in res["words_result"].members() {
            list.push(item["words"].as_str().unwrap());
        }
        list.into()
    }

    fn translate(&mut self, text: &str) -> JsonValue {
        self.get_access_token();

        let url = format!("https://aip.baidubce.com/rpc/2.0/mt/texttrans/v1?access_token={}", self.access_token);
        let mut http = br_http::Http::new();
        let http = http.post(url.as_str()).header("Content-Type", "application/json;charset=utf-8").raw_json(object! {
            "from": "auto",
            "to": "zh",
            "q": text
        });
        let res = http.json().unwrap();
        if res["result"]["trans_result"].is_empty() {
            return array![];
        }
        res["result"]["trans_result"].clone()
        // 返回值格式为 array[obj{"dst":""}, obj{"src"}:""] dst为译文, src为原文
    }
}