use std::fs;
use std::fs::create_dir_all;
use std::path::PathBuf;
use crate::model::{Model, ModelTemp};

/// 插件创建
pub fn addon_create(path: &str, plugin: &str, plugin_title: &str, model: &str, model_title: &str, action: &str, action_title: &str) {
    let root_path = PathBuf::from(path);
    let plugin_path = root_path.join("plugin");
    let plugin_path = plugin_path.join(plugin);
    create_dir_all(plugin_path.as_os_str()).expect("创建目录失败");

    let plugin_mod_path = plugin_path.join("mod.rs");
    if !plugin_mod_path.is_file() {
        let temp_plugin_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        let temp_plugin_mod_path = temp_plugin_mod_path.join("temp").join("plugin");
        let temp_plugin_mod_data = fs::read_to_string(temp_plugin_mod_path).unwrap();
        let addon_1 = plugin.to_lowercase();
        let plugin_1 = plugin[0..=0].to_uppercase();
        let plugin_2 = plugin[1..].to_lowercase();
        let temp_plugin_mod_data = temp_plugin_mod_data.replace("{{addon}}", &*format!("{}", addon_1));
        let temp_plugin_mod_data = temp_plugin_mod_data.replace("{{plugin}}", &*format!("{}{}", plugin_1, plugin_2));
        let temp_plugin_mod_data = temp_plugin_mod_data.replace("{{title}}", plugin_title);
        fs::write(plugin_mod_path, temp_plugin_mod_data).expect("写入插件mod错误");
    }

    if model != "" {
        let model_path = plugin_path.join(model);
        create_dir_all(model_path.as_os_str()).expect("创建模型目录失败");


        let plugin_d = {
            let t: Vec<String> = plugin.split("_").map(|x| {
                let x1 = x[0..=0].to_uppercase();
                let x2 = x[1..].to_lowercase();
                format!("{}{}", x1.clone(), x2.clone())
            }).collect();
            t.join("")
        };
        let model_d = {
            let t: Vec<String> = model.split("_").map(|x| {
                let x1 = x[0..=0].to_uppercase();
                let x2 = x[1..].to_lowercase();
                format!("{}{}", x1.clone(), x2.clone())
            }).collect();
            t.join("")
        };

        let model_mod_path = model_path.join("mod.rs");
        if !model_mod_path.is_file() {
            let temp_plugin_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
            let temp_model_mod_path = temp_plugin_mod_path.join("temp").join("model");
            let mut temp_model_mod_data = fs::read_to_string(temp_model_mod_path).unwrap();
            temp_model_mod_data = temp_model_mod_data.replace("{{addon}}", &*format!("{}", plugin_d));
            temp_model_mod_data = temp_model_mod_data.replace("{{model}}", &*format!("{}{}", plugin_d, model_d));
            temp_model_mod_data = temp_model_mod_data.replace("{{plugin_model}}", &*format!("{}_{}", plugin, model));
            let temp_model_mod_data = temp_model_mod_data.replace("{{title}}", model_title);
            fs::write(model_mod_path, temp_model_mod_data).expect("写入模型mod错误");
        }

        if action != "" {
            let action_path = model_path.join(format!("{}.rs", action));
            if !action_path.is_file() {
                let temp_action_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
                let temp_action_mod_path = {
                    if action.contains("table") {
                        temp_action_mod_path.join("temp").join("action_table")
                    } else if action.contains("add") {
                        temp_action_mod_path.join("temp").join("action_add")
                    } else if action.contains("del") {
                        temp_action_mod_path.join("temp").join("action_del")
                    } else if action.contains("put") {
                        temp_action_mod_path.join("temp").join("action_put")
                    } else if action.contains("select") {
                        temp_action_mod_path.join("temp").join("action_select")
                    } else if action.contains("get") {
                        temp_action_mod_path.join("temp").join("action_get")
                    } else if action.contains("menu") {
                        temp_action_mod_path.join("temp").join("action_menu")
                    } else {
                        temp_action_mod_path.join("temp").join("action")
                    }
                };

                let temp_action_mod_data = fs::read_to_string(temp_action_mod_path).unwrap();


                let action_d = {
                    let t: Vec<String> = action.split("_").map(|x| {
                        let x1 = x[0..=0].to_uppercase();
                        let x2 = x[1..].to_lowercase();
                        format!("{}{}", x1.clone(), x2.clone())
                    }).collect();
                    t.join("")
                };

                let temp_action_mod_data = temp_action_mod_data.replace("{{action}}", &*format!("{}{}{}", plugin_d, model_d, action_d));
                let temp_action_mod_data = temp_action_mod_data.replace("{{api}}", &*format!("{}.{}.{}", plugin, model, action));
                let temp_action_mod_data = temp_action_mod_data.replace("{{model}}", &*format!("{}{}", plugin_d, model_d));
                let temp_action_mod_data = temp_action_mod_data.replace("{{model_a}}", &*format!("{}", model));
                let temp_action_mod_data = temp_action_mod_data.replace("{{plugin}}", &*format!("{}", plugin));
                let temp_action_mod_data = temp_action_mod_data.replace("{{title}}", action_title);
                fs::write(action_path, temp_action_mod_data).expect("写入动作文件错误");
            }
        }
    }
}

/// 插件入口
pub fn plugin(name: &str) -> Box<dyn Addon> {
    match name {
        _ => Box::new(AddonTemp {}),
    }
}

/// 插件
pub trait Addon {
    /// 模型入口
    fn model(&mut self, name: &str) -> Box<dyn Model>;
    /// 插件标题
    fn title(&mut self) -> &'static str;
    /// 插件名称
    fn name(&mut self) -> &'static str;
    /// 排序
    fn sort(&mut self) -> usize { return 0; }
    /// 插件描述
    fn describe(&mut self) -> &'static str { return ""; }
    /// 图标
    fn icon(&mut self) -> &'static str { return ""; }
    /// 插件适合模式 org|admin|user
    fn mode(&mut self) -> Vec<&'static str> { return vec![]; }
}

/// 插件模版
pub struct AddonTemp {}

impl Addon for AddonTemp {
    fn model(&mut self, name: &str) -> Box<dyn Model> {
        match name {
            _ => Box::new(ModelTemp { addon: AddonTemp {} }),
        }
    }
    fn title(&mut self) -> &'static str {
        "插件模版"
    }

    fn name(&mut self) -> &'static str { "addon_temp" }
}