// use std::collections::HashMap;
use std::{
    io::Write,
    // sync::Arc,
    fmt::Debug,
    fs,
    path::{Path, PathBuf},
    io::{Error, ErrorKind},
};
use serde::{Serialize, Deserialize};
//use serde_json::value::{to_value, Value};
// use log::error;

use crate::{
    defs::{
        FromFile,
        load_from_file,
    },
}; 

// use std::path::Path;

// use crate::tools::generate_uuid;
// fn default_server_uid() -> String {
//     generate_uuid(String::from("abcdef0123456789"))
// }

fn default_form_defs_empty() -> String {
  "".to_string()
}
fn default_form_selections() -> Vec<FormSelectItem> {
    Vec::new()
}
fn default_form_border() -> bool {
   false 
}
fn default_form_required() -> bool {
   false 
}
fn default_form_items_empty() -> Vec<FormField> {
   Vec::new()
}
fn default_form_overwrite_response() -> bool {
   false 
}
#[derive(Debug, Clone, Serialize, Deserialize,Default)]
pub struct  FormSelectItem {
        #[serde(default = "default_form_defs_empty")]
    pub title: String,
        #[serde(default = "default_form_defs_empty")]
    pub defs: String,
        #[serde(default = "default_form_defs_empty")]
    pub value: String,
}
#[derive(Debug, Clone, Serialize, Deserialize,Default)]
pub struct  FormField {
        #[serde(default = "default_form_defs_empty")]
    pub name: String,
        #[serde(default = "default_form_defs_empty")]
    pub id: String,
        #[serde(default = "default_form_defs_empty")]
    pub placeholder: String,
        #[serde(default = "default_form_defs_empty")]
    pub typ: String,
        #[serde(default = "default_form_defs_empty")]
    pub css: String,
        #[serde(default = "default_form_border")]
    pub border: bool,
        #[serde(default = "default_form_defs_empty")]
    pub label_top_text: String,
        #[serde(default = "default_form_defs_empty")]
    pub label_css: String,
        #[serde(default = "default_form_selections")]
    pub selections: Vec<FormSelectItem>,
        #[serde(default = "default_form_required")]
    pub required: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize,Default)]
pub struct  FormDefs {
        #[serde(default = "default_form_defs_empty")]
    pub title: String,
        #[serde(default = "default_form_defs_empty")]
    pub name: String,
        #[serde(default = "default_form_defs_empty")]
    pub id: String,
        #[serde(default = "default_form_defs_empty")]
    pub css: String,
        #[serde(default = "default_form_defs_empty")]
    pub action: String,
        #[serde(default = "default_form_items_empty")]
    pub fields: Vec<FormField>,
        #[serde(default = "default_form_overwrite_response")]
    pub overwrite_response: bool,
}
impl FromFile for FormDefs {
    fn fix_root_path<Config>(&mut self, _root_path:  String ) { 
   //     if root_path != self.root_path {
   //         self.root_path = root_path.to_owned();
   //    }
   //   if self.root_path.is_empty() || ! Path::new(&self.root_path).exists() {
   //        return;
   //    }
    }
}
impl FormDefs {
    pub fn load_from(path: &str, name: &str) -> Self {
        load_from_file(path,name).unwrap_or_else(|e|{
            println!("FormDefs error: {}",e);
            FormDefs::default()
        })
    }
    pub fn write_data(&self, file_path: &str, data: &str, overwrite: bool) -> std::io::Result<()> {
        let check_path = |path: &Path| -> std::io::Result<()> {
            if ! Path::new(&path).exists() {
                if let Err(e) = std::fs::create_dir(&path) {
                    return Err(Error::new( ErrorKind::InvalidInput,
                        format!("Error create path {}: {}",&path.display(), e)
                    ));
                    // std::process::exit(2)
                }
            }
            Ok(())
        };
        if file_path.is_empty() || data.is_empty() {
            return Err(Error::new(
                ErrorKind::InvalidInput,
                format!("Error save {}",&file_path)
            ));
        }
        if ! Path::new(&file_path).exists() {
            let path = PathBuf::from(&file_path);
            if let Some(dir_path) =  path.parent() {
                if ! Path::new(&dir_path).exists() {
                    if let Some(parent_dir_path) = dir_path.parent() { 
                        if ! Path::new(&parent_dir_path).exists() {
                            let res = check_path(&parent_dir_path);
                            if res.is_err() { return res; }
                        }
                    }
                    let res = check_path(&dir_path);
                    if res.is_err() { return res; }
                }
            }
        }
        if overwrite || ! Path::new(&file_path).exists() {
            fs::write(&file_path, data)?;
            println!("Overwrite: {}",&file_path);
        } else {
            let sid_settings_file = fs::OpenOptions::new()
                .write(true)
                .append(true) // This is needed to append to file
                .open(&file_path);
            if let Ok(mut file) = sid_settings_file {
                file.write_all(data.as_bytes())?;
            }
            println!("write: {}",&file_path);
        }
        Ok(())
    }
    /*
     fn fix_item_path(&mut self, item: String ) -> String {
        if !item.is_empty() && ! Path::new(&item).exists() {
            format!("{}/{}",&self.root_path,&item)
        } else {
            item
        }
    }
    pub fn load_items(&mut self) { 
        self.fix_root_path::<Config>(self.root_path.to_owned());
        if !self.path_menu_items.is_empty() {
            self.path_menu_items = self.fix_item_path(self.path_menu_items.to_owned());
            let data_menu_items = load_from_file(&self.path_menu_items.to_owned(), "menu_items").unwrap_or_else(|e|{
                error!("Error loading menu_items from {}: {}",&self.path_menu_items,e);
                DataMenuItems::default()
            });
            self.ui.web_menu_items = data_menu_items.web_menu_items; 
        }
        if !self.path_serv_paths.is_empty() {
            self.path_serv_paths = self.fix_item_path(self.path_serv_paths.to_owned());
            let data_serv_paths = load_from_file(&self.path_serv_paths.to_owned(), "serv_paths").unwrap_or_else(|e|{
                error!("Error loading serv_paths from {}: {}",&self.path_serv_paths,e);
                DataServPath::default()
            });
            self.serv_paths = data_serv_paths.serv_paths;
        }
        if !self.path_locales_config.is_empty() {
            self.path_locales_config = self.fix_item_path(self.path_locales_config.to_owned());
            self.locales = load_dict_from_file(&self.path_locales_config.to_owned(), "locales").unwrap_or_else(|e|{
                error!("Error loading locales from {}: {}",&self.path_locales_config,e);
                HashMap::new()
            });
        }
        if self.users_store_uri.starts_with(FILE_SCHEME) {
            self.users_store_uri = format!("{}{}",
                FILE_SCHEME, self.fix_item_path(self.users_store_uri.replace(FILE_SCHEME,"")));
        } 
        if self.session_store_uri.starts_with(FILE_SCHEME) {
            self.session_store_uri = format!("{}{}",
                FILE_SCHEME, self.fix_item_path(self.session_store_uri.replace(FILE_SCHEME,"")));
        }
        if self.trace_store_uri.starts_with(FILE_SCHEME) {
            self.trace_store_uri = format!("{}{}",
                FILE_SCHEME, self.fix_item_path(self.trace_store_uri.replace(FILE_SCHEME,"")));
        } 
        self.cert_file = self.fix_item_path(self.cert_file.to_owned());
        self.key_file = self.fix_item_path(self.key_file.to_owned());
        self.templates_path = self.fix_item_path(self.templates_path.to_owned());
        self.defaults_path = self.fix_item_path(self.defaults_path.to_owned());

        #[cfg(feature = "authstore")]
        if self.authz_store_uri.starts_with(FILE_SCHEME) {
            self.authz_store_uri = format!("{}{}", 
                FILE_SCHEME, self.fix_item_path(self.authz_store_uri.replace(FILE_SCHEME,"")));
        }
        #[cfg(feature = "casbin")]
        {
            self.authz_model_path = self.fix_item_path(self.authz_model_path.to_owned());
            self.authz_policy_path = self.fix_item_path(self.authz_policy_path.to_owned());
        }
        self.paseto.public_path = self.fix_item_path(self.paseto.public_path.to_owned());
        self.paseto.secret_path = self.fix_item_path(self.paseto.secret_path.to_owned());
        (self.paseto.public_data, self.paseto.secret_data) = self.paseto.load_data();
        self.paseto.footer = ConfigPaSeToken::make_footer(
            self.paseto.map_footer.to_owned()
        ).unwrap_or(Footer::new());
    }
    #[allow(dead_code)] 
    pub fn to_json(&self) -> String {
        serde_json::to_string(self).unwrap_or_else(|e|{
            println!("Error to convert Config to json: {}",e);
            String::from("")
        })
    }
    // #[allow(dead_code)] 
    // pub fn st_html_path(&self) -> &'static str  {
    //     Box::leak(self.html_path.to_owned().into_boxed_str())
    // }
    #[allow(dead_code)] 
    pub fn full_html_url(&self, url: &str) -> String {
        format!("{}://{}:{}/{}",
            &self.protocol,&self.bind,&self.port,
            url
        )
    }
    */
}