use json::{JsonValue};
use log::info;
pub mod str;
pub mod int;
pub mod text;
pub mod float;
pub mod select;
pub mod datetime;
pub mod files;
pub mod location;
pub trait Field {
    fn sql(&mut self, model: &str) -> String;
    fn hide(&mut self) -> &mut Self;
    fn describe(&mut self, text: &str) -> &mut Self;
    fn field(&mut self) -> JsonValue;
    fn verify(&mut self, data: JsonValue) -> JsonValue {
        data
    }
}
pub enum FieldMode {
    Key,
    Pass,
    Color,
    String,
    Tel,
    Code,
    Email,
    Table,
    Text,
    Editor,
    Url,
    Files,
    Json,
    Array,
    Object,
    Float,
    Int,
    Switch,
    Datetime,
    Year,
    Date,
    Time,
    Timestamp,
    Select,
    Radio,
    Location,
}
impl FieldMode {
    pub fn from(name: &str) -> FieldMode {
        match name {
            "key" => FieldMode::Key,
            "pass" => FieldMode::Pass,
            "string" => FieldMode::String,
            "color" => FieldMode::Color,
            "tel" => FieldMode::Tel,
            "email" => FieldMode::Email,
            "table" => FieldMode::Table,
            "text" => FieldMode::Text,
            "editor" => FieldMode::Editor,
            "url" => FieldMode::Url,
            "file" => FieldMode::Files,
            "json" => FieldMode::Json,
            "array" => FieldMode::Array,
            "object" => FieldMode::Object,
            "float" => FieldMode::Float,
            "int" => FieldMode::Int,
            "switch" => FieldMode::Switch,
            "datetime" => FieldMode::Datetime,
            "year" => FieldMode::Year,
            "date" => FieldMode::Date,
            "time" => FieldMode::Time,
            "timestamp" => FieldMode::Timestamp,
            "select" => FieldMode::Select,
            "radio" => FieldMode::Radio,
            "code" => FieldMode::Code,
            "location" => FieldMode::Location,
            _ => {
                info!("未知 mode: {}", name);
                FieldMode::String
            }
        }
    }
}
pub fn field(model: &str, field: &str, data: JsonValue) -> String {
    let mode = data["mode"].as_str().unwrap();
    let require = data["require"].as_bool().unwrap_or(false);
    let title = data["title"].as_str().unwrap_or("未知标题");
    let field_mode = FieldMode::from(mode);
    let row = match field_mode {
        FieldMode::Key => {
            let length = data["length"].as_i32().unwrap();
            let auto = data["auto"].as_bool().unwrap();
            if auto {
                str::Key::new(true, field.clone(), title.clone(), length.clone()).auto().sql(model)
            } else {
                str::Key::new(true, field.clone(), title.clone(), length.clone()).sql(model)
            }
        }
        FieldMode::Pass => {
            let default = data["def"].as_str().unwrap();
            let length = data["length"].as_i32().unwrap();
            str::Pass::new(require.clone(), field.clone(), title.clone(), length.clone(), default.clone()).sql(model)
        }
        FieldMode::String => {
            let default = data["def"].as_str().unwrap_or("");
            let length = data["length"].as_i32().unwrap_or(20);
            str::Str::new(require.clone(), field.clone(), title.clone(), length.clone(), default.clone()).sql(model)
        }
        FieldMode::Color => {
            let default = data["def"].as_str().unwrap_or("");
            str::Color::new(require.clone(), field.clone(), title.clone(), default.clone()).sql(model)
        }
        FieldMode::Tel => {
            let default = data["def"].as_str().unwrap_or("");
            str::Tel::new(require.clone(), field.clone(), title.clone(), default.clone()).sql(model)
        }
        FieldMode::Email => {
            let default = data["def"].as_str().unwrap_or("");
            str::Email::new(require.clone(), field.clone(), title.clone(), default.clone()).sql(model)
        }
        FieldMode::Table => {
            let table = data["table"].as_str().unwrap();
            let fields: Vec<&str> = data["fields"].members().map(|x| x.as_str().unwrap()).collect();
            let api = data["api"].as_str().unwrap();
            text::Table::new(require.clone(), field.clone(), title.clone(),
                             table.clone(), fields.clone(), api.clone()).sql(model)
        }
        FieldMode::Text => {
            let default = data["def"].as_str().unwrap_or("");
            text::Text::new(require.clone(), field.clone(), title.clone(), default.clone()).sql(model)
        }
        FieldMode::Editor => {
            let default = data["def"].as_str().unwrap_or("");
            text::Editor::new(require.clone(), field.clone(), title.clone(), default.clone()).sql(model)
        }
        FieldMode::Url => {
            let default = data["def"].as_str().unwrap_or("");
            text::Url::new(require.clone(), field.clone(), title.clone(), default.clone()).sql(model)
        }
        FieldMode::Files => {
            let length = data["length"].as_i32().unwrap_or(1);
            let encrypt = data["encrypt"].as_bool().unwrap_or(false);
            let size = data["size"].as_usize().unwrap_or(0);
            let default = data["def"].as_str().unwrap_or("");
            let option: Vec<&str> = data["option"].members().map(|x| x.as_str().unwrap()).collect();
            let mut files_mode = files::Files::new(require.clone(), field.clone(), title.clone());
            if length > 1 {
                files_mode.multiple(length.clone());
            }
            if encrypt {
                files_mode.encrypt();
            }
            files_mode.def(default);
            files_mode.size(size);
            files_mode.option(option);
            files_mode.sql(model)
        }
        FieldMode::Json | FieldMode::Array | FieldMode::Object => {
            let default = data["def"].clone();
            text::Json::new(require.clone(), field.clone(), title.clone(), default.clone()).sql(model)
        }
        FieldMode::Float => {
            let length = data["length"].as_i32().unwrap();
            let dec = data["dec"].as_usize().unwrap();
            let default = data["def"].as_f32().unwrap();
            float::Float::new(require.clone(), field.clone(), title.clone(),
                              length.clone(), dec.clone(),
                              default.clone()).sql(model)
        }
        FieldMode::Int => {
            let length = data["length"].as_i32().unwrap();
            let default = data["def"].as_i64().unwrap();
            int::Int::new(require.clone(), field.clone(), title.clone(), length.clone(), default.clone()).sql(model)
        }
        FieldMode::Switch => {
            let default = data["def"].as_u8().unwrap_or(0);
            int::Switch::new(require.clone(), field.clone(), title.clone(),
                             default.clone()).sql(model)
        }
        FieldMode::Datetime => {
            let default = data["def"].as_str().unwrap();
            datetime::Datetime::new(require.clone(), field.clone(), title.clone(),
                                    default.clone()).sql(model)
        }
        FieldMode::Year => {
            let default = data["def"].as_u64().unwrap();
            datetime::Year::new(require.clone(), field.clone(), title.clone(),
                                default.clone()).sql(model)
        }
        FieldMode::Date => {
            let default = data["def"].as_str().unwrap();
            datetime::Date::new(require.clone(), field.clone(), title.clone(),
                                default.clone()).sql(model)
        }
        FieldMode::Time => {
            let default = data["def"].as_str().unwrap();
            datetime::Time::new(require.clone(), field.clone(), title.clone(),
                                default.clone()).sql(model)
        }
        FieldMode::Timestamp => {
            let dec = data["dec"].as_i32().unwrap();
            let default = data["def"].as_f64().unwrap_or(0.0);
            datetime::Timestamp::new(require.clone(), field.clone(), title.clone(),
                                     dec.clone(), default.clone()).sql(model)
        }
        FieldMode::Select => {
            let option: Vec<&str> = data["option"].members().map(|x| x.as_str().unwrap()).collect();
            let def: Vec<&str> = data["def"].members().map(|x| x.as_str().unwrap()).collect();
            select::Select::new(require.clone(), field.clone(), title.clone(), option.clone(), def.clone()).sql(model)
        }
        FieldMode::Radio => {
            let option: Vec<&str> = data["option"].members().map(|x| x.as_str().unwrap()).collect();
            select::Radio::new(require.clone(), field.clone(), title.clone(), option.clone(), data["def"].as_str().unwrap()).sql(model)
        }
        FieldMode::Code => {
            let default = data["def"].as_str().unwrap_or("");
            let dec = data["dec"].as_str().unwrap_or("");
            let length = data["length"].as_usize().unwrap_or(20);
            str::Code::new(require.clone(), field.clone(), title.clone(), length.clone(), dec.clone(), default.clone()).sql(model)
        }
        FieldMode::Location => {
            let default = data["def"].as_str().unwrap_or("");
            location::Location::new(require.clone(), field.clone(), title.clone()).def(default).sql(model)
        }
    };
    format!("{}", row.clone())
}
pub fn verify(field: &str, data: JsonValue) -> JsonValue {
    let mode = data["mode"].as_str().unwrap();
    let require = data["require"].as_bool().unwrap_or(false);
    let title = data["title"].as_str().unwrap_or("未知标题");
    let field_mode = FieldMode::from(mode);
    match field_mode {
        FieldMode::Key => {
            let length = data["length"].as_i32().unwrap();
            let auto = data["auto"].as_bool().unwrap();
            if auto {
                str::Key::new(true, field.clone(), title.clone(), length.clone()).auto().verify(data)
            } else {
                str::Key::new(true, field.clone(), title.clone(), length.clone()).verify(data)
            }
        }
        FieldMode::Pass => {
            let default = data["def"].as_str().unwrap();
            let length = data["length"].as_i32().unwrap();
            str::Pass::new(require.clone(), field.clone(), title.clone(), length.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::String => {
            let default = data["def"].as_str().unwrap_or("");
            let length = data["length"].as_i32().unwrap_or(20);
            str::Str::new(require.clone(), field.clone(), title.clone(), length.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Color => {
            let default = data["def"].as_str().unwrap_or("");
            str::Color::new(require.clone(), field.clone(), title.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Tel => {
            let default = data["def"].as_str().unwrap_or("");
            str::Tel::new(require.clone(), field.clone(), title.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Email => {
            let default = data["def"].as_str().unwrap_or("");
            str::Email::new(require.clone(), field.clone(), title.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Table => {
            let table = data["table"].as_str().unwrap();
            let fields: Vec<&str> = data["fields"].members().map(|x| x.as_str().unwrap()).collect();
            let api = data["api"].as_str().unwrap();
            text::Table::new(require.clone(), field.clone(), title.clone(),
                             table.clone(), fields.clone(), api.clone()).verify(data.clone())
        }
        FieldMode::Text => {
            let default = data["def"].as_str().unwrap_or("");
            text::Text::new(require.clone(), field.clone(), title.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Editor => {
            let default = data["def"].as_str().unwrap_or("");
            text::Editor::new(require.clone(), field.clone(), title.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Url => {
            let default = data["def"].as_str().unwrap_or("");
            text::Url::new(require.clone(), field.clone(), title.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Files => {
            let length = data["length"].as_i32().unwrap_or(1);
            let encrypt = data["encrypt"].as_bool().unwrap_or(false);
            let size = data["size"].as_usize().unwrap_or(0);
            let option: Vec<&str> = data["option"].members().map(|x| x.as_str().unwrap()).collect();
            let default = data["def"].as_str().unwrap_or("");
            let mut files_mode = files::Files::new(require.clone(), field.clone(), title.clone());
            if length > 1 { files_mode.multiple(length.clone()); }
            if encrypt {
                files_mode.encrypt();
            }
            files_mode.def(default);
            files_mode.size(size);
            files_mode.option(option);
            files_mode.verify(data.clone())
        }
        FieldMode::Json | FieldMode::Array | FieldMode::Object => {
            let default = data["def"].clone();
            text::Json::new(require.clone(), field.clone(), title.clone(),
                            default).verify(data.clone())
        }
        FieldMode::Float => {
            let length = data["length"].as_i32().unwrap();
            let dec = data["dec"].as_usize().unwrap();
            let default = data["def"].as_f32().unwrap();
            float::Float::new(require.clone(), field.clone(), title.clone(),
                              length.clone(), dec.clone(),
                              default.clone()).verify(data.clone())
        }
        FieldMode::Int => {
            let length = data["length"].as_i32().unwrap();
            let default = data["def"].as_i64().unwrap();
            int::Int::new(require.clone(), field.clone(), title.clone(), length.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Switch => {
            let default = data["def"].as_u8().unwrap_or(0);
            int::Switch::new(require.clone(), field.clone(), title.clone(),
                             default.clone()).verify(data.clone())
        }
        FieldMode::Datetime => {
            let default = data["def"].as_str().unwrap();
            datetime::Datetime::new(require.clone(), field.clone(), title.clone(),
                                    default.clone()).verify(data.clone())
        }
        FieldMode::Year => {
            let default = data["def"].as_u64().unwrap();
            datetime::Year::new(require.clone(), field.clone(), title.clone(),
                                default.clone()).verify(data.clone())
        }
        FieldMode::Date => {
            let default = data["def"].as_str().unwrap();
            datetime::Date::new(require.clone(), field.clone(), title.clone(),
                                default.clone()).verify(data.clone())
        }
        FieldMode::Time => {
            let default = data["def"].as_str().unwrap();
            datetime::Time::new(require.clone(), field.clone(), title.clone(),
                                default.clone()).verify(data.clone())
        }
        FieldMode::Timestamp => {
            let dec = data["dec"].as_i32().unwrap();
            let default = data["def"].as_f64().unwrap_or(0.0);
            datetime::Timestamp::new(require.clone(), field.clone(), title.clone(),
                                     dec.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Select => {
            let option: Vec<&str> = data["option"].members().map(|c| c.as_str().unwrap()).collect();
            let def: Vec<&str> = data["def"].members().map(|c| c.as_str().unwrap()).collect();
            select::Select::new(require.clone(), field.clone(), title.clone(),
                                option.clone(), def.clone()).verify(data.clone())
        }
        FieldMode::Radio => {
            let option: Vec<&str> = data["option"].members().map(|x| x.as_str().unwrap()).collect();
            select::Radio::new(require.clone(), field.clone(), title.clone(),
                               option.clone(), data["def"].as_str().unwrap()).verify(data.clone())
        }
        FieldMode::Code => {
            let default = data["def"].as_str().unwrap_or("");
            let dec = data["dec"].as_str().unwrap_or("");
            let length = data["length"].as_usize().unwrap_or(20);
            str::Code::new(require.clone(), field.clone(), title.clone(), length.clone(), dec.clone(), default.clone()).verify(data.clone())
        }
        FieldMode::Location => {
            let default = data["def"].as_str().unwrap_or("");
            location::Location::new(require.clone(), field.clone(), title.clone()).def(default).verify(data.clone())
        }
    }
}