#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
use json::{Null};
use json::{object, JsonValue};
#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
use lazy_static::lazy_static;
#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
use std::sync::Mutex;
#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
use std::collections::HashMap;
#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
use std::fs;
#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
use std::path::PathBuf;
#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
use crate::config::{Config, Connection};
#[cfg(any(feature = "db-mssql"))]
use crate::mssql::Mssql;
#[cfg(any(feature = "db-mysql"))]
use crate::mysql::Mysql;
#[cfg(any(feature = "db-sqlite"))]
use crate::sqlite::Sqlite;
#[cfg(any(feature = "db-mysqls"))]
use crate::mysqls::Mysqls;
pub mod config;
pub mod pools;
#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
lazy_static! {
    pub static ref DB: Mutex<HashMap<String,Db>> =Mutex::new(HashMap::new());
    static ref CONNECTION: Mutex<HashMap<String,Connection>> =Mutex::new(HashMap::new());
    static ref DEFAULT: Mutex<HashMap<usize,String>> =Mutex::new(HashMap::new());
}
#[cfg(any(feature = "db-sqlite"))]
mod sqlite;
#[cfg(any(feature = "db-mysql"))]
mod mysql;
#[cfg(any(feature = "db-mysqls"))]
mod mysqls;
#[cfg(any(feature = "db-mssql"))]
mod mssql;
#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
pub trait Mode {
    fn conn_info(&mut self) -> Connection {
        todo!()
    }
    fn database_tables(&mut self) -> JsonValue;
    fn database_create(&mut self, name: &str) -> bool;
    fn table_create(&mut self, data: Table) -> JsonValue;
    fn table_update(&mut self, data: Table) -> JsonValue;
    fn table_info(&mut self, table: &str) -> JsonValue;
    fn table_is_exist(&mut self, name: &str) -> bool;
    fn table(&mut self, name: &str) -> &mut Self;
    fn change_table(&mut self, name: &str) -> &mut Self;
    fn autoinc(&mut self) -> &mut Self;
    fn fetch_sql(&mut self) -> &mut Self;
    fn order(&mut self, field: &str, by: bool) -> &mut Self;
    fn group(&mut self, field: &str) -> &mut Self;
    fn distinct(&mut self) -> &mut Self;
    fn json(&mut self, field: &str) -> &mut Self;
    fn column(&mut self, field: &str) -> JsonValue;
    fn where_and(&mut self, field: &str, compare: &str, value: JsonValue) -> &mut Self;
    fn where_or(&mut self, field: &str, compare: &str, value: JsonValue) -> &mut Self;
    fn where_column(&mut self, field_a: &str, compare: &str, field_b: &str) -> &mut Self;
    fn count(&mut self) -> JsonValue;
    fn max(&mut self, field: &str) -> JsonValue;
    fn min(&mut self, field: &str) -> JsonValue;
    fn sum(&mut self, field: &str) -> JsonValue;
    fn avg(&mut self, field: &str) -> JsonValue;
    fn select(&mut self) -> JsonValue;
    fn find(&mut self) -> JsonValue;
    fn value(&mut self, field: &str) -> JsonValue;
    fn insert(&mut self, data: JsonValue) -> JsonValue;
    fn insert_all(&mut self, data: JsonValue) -> JsonValue;
    fn page(&mut self, page: i32, limit: i32) -> &mut Self;
    fn update(&mut self, data: JsonValue) -> JsonValue;
    fn update_all(&mut self, data: JsonValue) -> JsonValue;
    fn delete(&mut self) -> JsonValue;
    fn field(&mut self, field: &str) -> &mut Self;
    fn hidden(&mut self, name: &str) -> &mut Self;
    fn transaction(&mut self) -> bool;
    fn commit(&mut self) -> bool;
    fn rollback(&mut self) -> bool;
    fn sql(&mut self, sql: &str) -> Result<JsonValue, String>;
    fn inc(&mut self, field: &str, num: f64) -> &mut Self;
    fn dec(&mut self, field: &str, num: f64) -> &mut Self;
    fn buildsql(&mut self) -> String;
    fn join(&mut self, table: &str, main_fields: &str, right_fields: &str) -> &mut Self;
    fn join_inner(&mut self, table: &str, main_fields: &str, second_fields: &str) -> &mut Self;
}
#[derive(Clone, Debug)]
pub enum Db {
    #[cfg(any(feature = "db-mysqls"))]
    Mysqls(Mysqls),
    #[cfg(any(feature = "db-mysql"))]
    Mysql(Mysql),
    #[cfg(any(feature = "db-sqlite"))]
    Sqlite(Sqlite),
    #[cfg(any(feature = "db-mssql"))]
    Mssql(Mssql),
    None,
}
#[cfg(any(feature = "db-mysql", feature = "db-sqlite", feature = "db-mssql", feature = "db-mysqls"))]
impl Db {
    pub fn load(path: &str) -> Self {
        let conf = fs::read_to_string(path);
        match conf {
            Ok(str) => {
                match json::parse(str.as_str()) {
                    Ok(config) => {
                        Db::new(config)
                    }
                    Err(_) => {
                        let config = Config::default().json();
                        let path_buf = PathBuf::from(path);
                        fs::create_dir_all(path.trim_end_matches(path_buf.file_name().unwrap().to_str().unwrap())).unwrap();
                        fs::write(path, config.to_string()).unwrap();
                        Db::new(config)
                    }
                }
            }
            Err(_) => {
                let config = Config::default().json();
                let path_buf = PathBuf::from(path);
                fs::create_dir_all(path.trim_end_matches(path_buf.file_name().unwrap().to_str().unwrap())).unwrap();
                fs::write(path, config.to_string()).unwrap();
                Db::new(config)
            }
        }
    }
    pub fn new(conf: JsonValue) -> Db {
        let config = Config::from(conf);
        let connection = config.connections.get(&*config.default).unwrap().clone();
        for (name, conn) in config.connections.clone() {
            CONNECTION.lock().unwrap().insert(name, conn);
        }
        let connections = CONNECTION.lock().unwrap().clone();
        DEFAULT.lock().unwrap().insert(0, config.default.clone());
        let db = Db::setlist(connections.clone(), connection.clone(), config.default.clone());
        DB.lock().unwrap().insert(config.default.clone(), db.clone());
        DB.lock().unwrap().get(&*config.default.clone()).unwrap().clone()
    }
    fn setlist(connections: HashMap<String, Connection>, mut connection: Connection, default: String) -> Db {
        match connection.mode.str() {
            #[cfg(any(feature = "db-mysqls"))]
            "mysqls" => {
                let mut db = Mysqls::connect(connection.clone(), default.clone()).unwrap();
                db.connections = connections.clone();
                Db::Mysqls(db)
            }
            #[cfg(any(feature = "db-mysql"))]
            "mysql" => {
                let mut db = Mysql::connect(connection.clone(), default.clone()).unwrap();
                db.connections = connections.clone();
                Db::Mysql(db)
            }
            #[cfg(any(feature = "db-sqlite"))]
            "sqlite" => {
                Sqlite::connect(connection.clone(), default.clone());
                Db::Sqlite(Sqlite {
                    connections: connections.clone(),
                    connection: connection.clone(),
                    default: default.clone(),
                    params: Params::default("sqlite"),
                })
            }
            #[cfg(any(feature = "db-mssql"))]
            "mssql" => {
                Db::Mssql(Mssql {
                    connections: connections.clone(),
                    connection: connection.clone(),
                    default: default.clone(),
                    params: Params::default("mssql"),
                })
            }
            _ => Db::None
        }
    }
    pub fn connection(&mut self, name: &str) -> Db {
        let default = DEFAULT.lock().unwrap();
        let default = default.get(&0).unwrap();
        let connections = CONNECTION.lock().unwrap().clone();
        let name = {
            if name == "" {
                default
            } else {
                name
            }
        };
        let dbmode = DB.lock().unwrap().get(&*name).is_none();
        if !dbmode {
            let db = DB.lock().unwrap().get(&*name).unwrap().clone();
            return db;
        }
        let connection = connections.get(&*name).unwrap().clone();
        let db = Db::setlist(connections.clone(), connection.clone(), name.to_string().clone());
        DB.lock().unwrap().insert((&*name).parse().unwrap(), db.clone());
        db
    }
    pub fn connection_add(&mut self, config_name: &str, connection: Connection) -> Db {
        let default = DEFAULT.lock().unwrap();
        let default = default.get(&0).unwrap();
        let mut connections = CONNECTION.lock().unwrap().clone();
        let name = {
            if config_name == "" {
                default.clone()
            } else {
                config_name.to_string()
            }
        }.clone();
        let dbmode = DB.lock().unwrap().get(&*name.clone()).is_none();
        if !dbmode {
            let db = DB.lock().unwrap().get(&*name.clone()).unwrap().clone();
            return db;
        } else {
            CONNECTION.lock().unwrap().insert(name.clone().to_string(), connection.clone());
            connections.insert(name.clone().to_string(), connection.clone());
        }
        let connection = connections.get(&*name.clone()).unwrap().clone();
        let db = Db::setlist(connections.clone(), connection.clone(), name.clone());
        DB.lock().unwrap().insert((&*name.clone()).parse().unwrap(), db.clone());
        db
    }
    pub fn conn_info(&mut self) -> Connection {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.connection.clone()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.connection.clone()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.connection.clone()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.connection.clone()
            }
            _ => Connection::default()
        }
    }
    pub fn database_tables(&mut self) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.database_tables()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.database_tables()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.database_tables()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.database_tables()
            }
            _ => JsonValue::Array(vec![])
        }
    }
    pub fn database_create(&mut self, name: &str) -> bool {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.database_create(name)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.database_create(name)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.database_create(name)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.database_create(name)
            }
            _ => false
        }
    }
    pub fn table_create(&mut self, data: Table) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.table_create(data)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.table_create(data)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.table_create(data)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.table_create(data)
            }
            _ => JsonValue::from(0)
        }
    }
    pub fn table_update(&mut self, data: Table) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.table_update(data)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.table_update(data)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.table_update(data)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.table_update(data)
            }
            _ => JsonValue::from(false)
        }
    }
    pub fn table_info(&mut self, table: &str) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.table_info(table)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.table_info(table)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.table_info(table)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.table_info(table)
            }
            _ => object! {}
        }
    }
    pub fn table_is_exist(&mut self, name: &str) -> bool {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.table_is_exist(name)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.table_is_exist(name)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.table_is_exist(name)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.table_is_exist(name)
            }
            _ => false
        }
    }
    pub fn table(&mut self, name: &str) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.table(name);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.table(name);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.table(name);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.table(name);
            }
            _ => {}
        };
        self
    }
    pub fn change_table(&mut self, name: &str) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.change_table(name);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.change_table(name);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.change_table(name);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.change_table(name);
            }
            _ => {}
        };
        self
    }
    pub fn autoinc(&mut self) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.autoinc();
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.autoinc();
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.autoinc();
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.autoinc();
            }
            _ => {}
        };
        self
    }
    pub fn fetch_sql(&mut self) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.fetch_sql();
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.fetch_sql();
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.fetch_sql();
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.fetch_sql();
            }
            _ => {}
        };
        self
    }
    pub fn order(&mut self, field: &str, by: bool) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.order(field, by);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.order(field, by);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.order(field, by);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.order(field, by);
            }
            _ => {}
        }
        self
    }
    pub fn group(&mut self, field: &str) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.group(field);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.group(field);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.group(field);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.group(field);
            }
            _ => {}
        }
        self
    }
    pub fn distinct(&mut self) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.distinct();
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.distinct();
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.distinct();
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.distinct();
            }
            _ => {}
        }
        self
    }
    pub fn json(&mut self, field: &str) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.json(field);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.json(field);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.json(field);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.json(field);
            }
            _ => {}
        }
        self
    }
    pub fn column(&mut self, field: &str) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.column(field)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.column(field)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.column(field)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.column(field)
            }
            _ => object! {}
        }
    }
    pub fn where_and(&mut self, field: &str, compare: &str, value: JsonValue) -> &mut Self {
        if field.contains("|") {
            let fields: Vec<&str> = field.split("|").collect();
            for field in fields.iter() {
                self.where_or(format!("{}", field).as_str(), compare, value.clone());
            }
            return self;
        }
        let compare = compare.to_lowercase();
        let compare = compare.replace(" ", "");
        let compare = compare.as_str();
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.where_and(field, compare, value);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.where_and(field, compare, value);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.where_and(field, compare, value);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.where_and(field, compare, value);
            }
            _ => {}
        };
        self
    }
    pub fn where_or(&mut self, field: &str, compare: &str, value: JsonValue) -> &mut Self {
        if field.contains("|") {
            let fields: Vec<&str> = field.split("|").collect();
            for field in fields.iter() {
                self.where_or(format!("{}", field).as_str(), compare, value.clone());
            }
            return self;
        }
        let compare = compare.to_lowercase();
        let compare = compare.replace(" ", "");
        let compare = compare.as_str();
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.where_or(field, compare, value);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.where_or(field, compare, value);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.where_or(field, compare, value);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.where_or(field, compare, value);
            }
            _ => {}
        };
        self
    }
    pub fn where_column(&mut self, field_a: &str, compare: &str, field_b: &str) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.where_column(field_a, compare, field_b);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.where_column(field_a, compare, field_b);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.where_column(field_a, compare, field_b);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.where_column(field_a, compare, field_b);
            }
            _ => {}
        };
        self
    }
    pub fn count(&mut self) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.count()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.count()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.count()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.count()
            }
            _ => JsonValue::from(0)
        }
    }
    pub fn max(&mut self, field: &str) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.max(field)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.max(field)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.max(field)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.max(field)
            }
            _ => object! {}
        }
    }
    pub fn min(&mut self, field: &str) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.min(field)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.min(field)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.min(field)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.min(field)
            }
            _ => object! {}
        }
    }
    pub fn sum(&mut self, field: &str) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.sum(field)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.sum(field)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.sum(field)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.sum(field)
            }
            _ => object! {}
        }
    }
    pub fn avg(&mut self, field: &str) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.avg(field)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.avg(field)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.avg(field)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.avg(field)
            }
            _ => object! {}
        }
    }
    pub fn select(&mut self) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.select()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.select()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.select()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.select()
            }
            _ => object! {}
        }
    }
    pub fn find(&mut self) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.find()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.find()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.find()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.find()
            }
            _ => object! {}
        }
    }
    pub fn value(&mut self, field: &str) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.value(field)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.value(field)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.value(field)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.value(field)
            }
            _ => JsonValue::from(Null)
        }
    }
    pub fn insert(&mut self, data: JsonValue) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.insert(data.clone())
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.insert(data.clone())
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.insert(data.clone())
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.insert(data.clone())
            }
            _ => JsonValue::from("")
        }
    }
    pub fn insert_all(&mut self, data: JsonValue) -> JsonValue {
        let data = if data[0].is_empty() {
            JsonValue::from(vec![data])
        } else {
            data
        };
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.insert_all(data.clone())
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.insert_all(data.clone())
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.insert_all(data.clone())
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.insert_all(data.clone())
            }
            _ => object! {}
        }
    }
    pub fn page(&mut self, mut page: i32, limit: i32) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                if page <= 0 {
                    page = 1;
                }
                db.page(page.clone(), limit.clone());
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                if page <= 0 {
                    page = 1;
                }
                db.page(page.clone(), limit.clone());
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.page(page.clone(), limit.clone());
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                if page <= 0 {
                    page = 1;
                }
                db.page(page.clone(), limit.clone());
            }
            _ => {}
        };
        self
    }
    pub fn update(&mut self, data: JsonValue) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.update(data.clone())
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.update(data.clone())
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.update(data.clone())
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.update(data.clone())
            }
            _ => JsonValue::from(0)
        }
    }
    pub fn update_all(&mut self, data: JsonValue) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.update_all(data.clone())
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.update_all(data.clone())
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.update_all(data.clone())
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.update_all(data.clone())
            }
            _ => JsonValue::from(0)
        }
    }
    pub fn delete(&mut self) -> JsonValue {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.delete()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.delete()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.delete()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.delete()
            }
            _ => JsonValue::from(0)
        }
    }
    pub fn field(&mut self, name: &str) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.field(name);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.field(name);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.field(name);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.field(name);
            }
            _ => {}
        };
        self
    }
    pub fn hidden(&mut self, name: &str) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.hidden(name.clone());
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.hidden(name);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.hidden(name);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.hidden(name);
            }
            _ => {}
        };
        self
    }
    pub fn transaction(&mut self) -> bool {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.transaction()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.transaction()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.transaction()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.transaction()
            }
            _ => false
        }
    }
    pub fn commit(&mut self) -> bool {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.commit()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.commit()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.commit()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.commit()
            }
            _ => false
        }
    }
    pub fn rollback(&mut self) -> bool {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.rollback()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.rollback()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.rollback()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.rollback()
            }
            _ => false
        }
    }
    pub fn sql(&mut self, sql: &str) -> Result<JsonValue, String> {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.sql(sql)
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.sql(sql)
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.sql(sql)
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.sql(sql)
            }
            _ => Err("".to_string())
        }
    }
    pub fn inc(&mut self, field: &str, num: f64) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.inc(field, num);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.inc(field, num);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.inc(field, num);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.inc(field, num);
            }
            _ => {}
        }
        self
    }
    pub fn dec(&mut self, field: &str, num: f64) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.dec(field, num);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.dec(field, num);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.dec(field, num);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.dec(field, num);
            }
            _ => {}
        }
        self
    }
    pub fn buildsql(&mut self) -> String {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.buildsql()
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.buildsql()
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.buildsql()
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.buildsql()
            }
            _ => "".to_string()
        }
    }
    pub fn join(&mut self, table: &str, main_fields: &str, right_fields: &str) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.join(table, main_fields, right_fields);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.join(table, main_fields, right_fields);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.join(table, main_fields, right_fields);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.join(table, main_fields, right_fields);
            }
            _ => {}
        }
        self
    }
    pub fn join_inner(&mut self, table: &str, main_fields: &str, second_fields: &str) -> &mut Self {
        match self {
            #[cfg(any(feature = "db-mysqls"))]
            Db::Mysqls(db) => {
                db.join_inner(table, main_fields, second_fields);
            }
            #[cfg(any(feature = "db-mysql"))]
            Db::Mysql(db) => {
                db.join_inner(table, main_fields, second_fields);
            }
            #[cfg(any(feature = "db-sqlite"))]
            Db::Sqlite(db) => {
                db.join_inner(table, main_fields, second_fields);
            }
            #[cfg(any(feature = "db-mssql"))]
            Db::Mssql(db) => {
                db.join_inner(table, main_fields, second_fields);
            }
            _ => {}
        }
        self
    }
}
#[derive(Clone, Debug)]
pub struct Table {
    pub version: String,
    pub table: String,
    pub title: String,
    pub primary_key: String,
    pub unique: Vec<String>,
    pub index: Vec<Vec<String>>,
    pub fields: JsonValue,
    pub partition: bool,
    pub partition_columns: JsonValue,
}
impl Table {
    pub fn to_string(self) -> String {
        let data = object! {
            version:self.version,
            table:self.table,
            title:self.title,
            primary_key:self.primary_key,
            unique:self.unique,
            index:self.index,
            fields:self.fields,
            partition:self.partition,
            partition_columns:self.partition_columns,
        };
        data.to_string()
    }
    pub fn parse(mut data: JsonValue) -> Table {
        let mut unique = vec![];
        for item in 0..data["unique"].len() {
            let str = data["unique"][item].clone().to_string();
            unique.push(str);
        }
        let mut index = vec![];
        for item in data["index"].members_mut() {
            let mut row = vec![];
            for col in item.members_mut() {
                row.push(col.to_string());
            }
            if row.len() > 0 {
                index.push(row);
            }
        }
        Self {
            version: data["version"].to_string(),
            table: data["table"].to_string(),
            title: data["title"].to_string(),
            primary_key: data["primary_key"].to_string(),
            unique,
            index,
            fields: data["fields"].clone(),
            partition: data["partition"].as_bool().unwrap_or(false),
            partition_columns: data["partition_columns"].clone()
        }
    }
}
#[derive(Clone, Debug)]
pub struct Params {
    pub mode: String,
    pub autoinc: bool,
    pub table: String,
    pub where_and: Vec<String>,
    pub where_or: Vec<String>,
    pub where_column: String,
    pub inc_dec: JsonValue,
    pub page: i32,
    pub limit: i32,
    pub fields: JsonValue,
    pub top: String,
    pub top2: String,
    pub order: JsonValue,
    pub group: JsonValue,
    pub distinct: bool,
    pub json: JsonValue,
    pub sql: bool,
    pub join: Vec<String>,
    pub join_inner: Vec<String>,
    pub join_table: String,
}
impl Params {
    pub fn default(mode: &str) -> Self {
        Self {
            mode: mode.to_string(),
            autoinc: false,
            table: "".to_string(),
            where_and: vec![],
            where_or: vec![],
            where_column: "".to_string(),
            inc_dec: object! {},
            page: -1,
            limit: 10,
            fields: object! {},
            top: String::new(),
            top2: String::new(),
            order: object! {},
            group: object! {},
            distinct: false,
            json: object! {},
            sql: false,
            join: Vec::new(),
            join_inner: Vec::new(),
            join_table: "".to_string(),
        }
    }
    pub fn where_sql(&mut self) -> String {
        let mut where_and_sql = vec![];
        let mut where_or_sql = vec![];
        let mut sql = vec![];
        for item in self.where_or.iter() {
            where_or_sql.push(item.clone());
        }
        if where_or_sql.len() > 0 {
            sql.push(format!(" ( {} ) ", where_or_sql.join(" OR ")));
        }
        for item in self.where_and.iter() {
            where_and_sql.push(item.clone());
        }
        if where_and_sql.len() > 0 {
            sql.push(where_and_sql.join(" AND "));
        }
        if self.where_column != "" {
            sql.push(self.where_column.clone());
        }
        if sql.len() > 0 {
            return format!("WHERE {}", sql.join(" AND "));
        }
        return format!("");
    }
    pub fn page_limit_sql(&mut self) -> String {
        if self.page == -1 {
            return format!("");
        }
        match self.mode.as_str() {
            "mysql" => {
                return format!("LIMIT {},{}", self.page * self.limit - self.limit, self.limit);
            }
            "sqlite" => {
                return format!("LIMIT {} OFFSET {}", self.limit, self.page * self.limit - self.limit);
            }
            "mssql" => {
                return "".to_string();
            }
            _ => return format!("")
        }
    }
    pub fn fields(&mut self) -> String {
        let mut fields = vec![];
        for (_, value) in self.fields.entries() {
            match self.mode.as_str() {
                "mssql" => {
                    fields.push(format!("{}", value));
                }
                _ => {
                    fields.push(format!("{}", value));
                }
            }
        }
        let fields = {
            if fields.len() == 0 {
                "*".into()
            } else {
                fields.join(",")
            }
        };
        match self.mode.as_str() {
            "mysql" => {
                return format!("{}", fields);
            }
            "sqlite" => {
                return format!("{}", fields);
            }
            "mssql" => {
                return format!("{}", fields);
            }
            _ => return format!("{}", fields)
        }
    }
    pub fn top(&mut self) -> String {
        match self.mode.as_str() {
            "mssql" => {
                let wheres = self.where_sql();
                if !self.top2.is_empty() {
                    let order = self.order();
                    if order.is_empty() {
                        self.top = format!("(select ROW_NUMBER() OVER(ORDER BY rand()) as ROW,* from {} {}) as ", self.table, wheres);
                    } else {
                        self.top = format!("(select ROW_NUMBER() OVER({}) as ROW,* from {} {}) as ", order, self.table, wheres);
                    }
                    return format!("{}", self.top);
                }
                return format!("{}", self.top);
            }
            "mysql" | "sqlite" | _ => {
                return format!("");
            }
        }
    }
    pub fn top2(&mut self) -> String {
        match self.mode.as_str() {
            "mssql" => {
                if self.where_and.len() == 0 && self.where_or.len() == 0 {
                    if self.top2 != "" {
                        return format!("where {}", self.top2);
                    }
                }
                if (self.where_and.len() > 0 || self.where_or.len() > 0) && self.top2 != "" {
                    return format!("AND {}", self.top2);
                }
                return format!("{}", self.top2);
            }
            "mysql" | "sqlite" | _ => {
                return format!("");
            }
        }
    }
    pub fn table(&mut self) -> String {
        match self.mode.as_str() {
            "mssql" => {
                if self.top2 != "" {
                    return format!("t");
                }
                return format!("{}", self.table);
            }
            "mysql" | "sqlite" | _ => {
                return format!("{}", self.table);
            }
        }
    }
    pub fn join(&mut self) -> String {
        match self.mode.as_str() {
            "mssql" => {
                let mut join = "".to_string();
                for item in self.join.iter() {
                    join = format!("{} {}", join, item);
                }
                return format!("{}", join);
            }
            "mysql" | "sqlite" | _ => {
                let mut join = "".to_string();
                for item in self.join.iter() {
                    join = format!("{} {}", join, item);
                }
                return format!("{}", join);
            }
        }
    }
    pub fn join_inner(&mut self) -> String {
        match self.mode.as_str() {
            "mysql" => {
                let mut join_inner = "".to_string();
                for item in self.join_inner.iter() {
                    join_inner = format!("{} {}", join_inner, item);
                }
                return format!("{}", join_inner);
            }
            _ => {
                "".to_string()
            }
        }
    }
    pub fn order(&mut self) -> String {
        let mut sql = vec![];
        for (field, item) in self.order.entries() {
            match self.mode.as_str() {
                "mssql" => {
                    sql.push(format!("{} {}", field, item));
                }
                _ => {
                    sql.push(format!("`{}` {}", field, item));
                }
            }
        }
        if sql.len() > 0 {
            return format!("ORDER BY {}", sql.join(","));
        }
        return format!("");
    }
    pub fn group(&mut self) -> String {
        let mut sql = vec![];
        for (_, field) in self.group.entries() {
            match self.mode.as_str() {
                "mssql" => {
                    sql.push(format!("{}.{}", self.join_table, field));
                }
                _ => {
                    sql.push(format!("{}.`{}`", self.join_table, field));
                }
            }
        }
        if sql.len() > 0 {
            return format!("GROUP BY {}", sql.join(","));
        }
        return format!("");
    }
    pub fn distinct(&self) -> String {
        if self.distinct {
            return "DISTINCT".to_string();
        } else {
            return "".to_string();
        }
    }
    pub fn select_sql(&mut self) -> String {
        return format!("SELECT {} {} FROM {} {} {} {} {} {} {} {} {}", self.distinct(), self.fields(), self.top(), self.table(), self.join(), self.join_inner(), self.where_sql(), self.top2(), self.group(), self.order(), self.page_limit_sql());
    }
}
#[derive(Clone, Debug)]
pub enum Charset {
    Utf8mb4,
    Utf8,
}
impl Charset {
    pub fn from(str: &str) -> Charset {
        match str {
            "utf8" => Charset::Utf8,
            "utf8mb4" => Charset::Utf8mb4,
            _ => Charset::Utf8mb4
        }
    }
}