use anyhow::Result;
use dialoguer::{Input, Select, Confirm};
use serde_json::{Value, json, Map};
use ferrisup_common::*;
pub fn process_variables(
template_config: &Value,
project_name: &str,
interactive: bool,
initial_variables: Option<Value>,
) -> Result<Value> {
let mut variables = Map::new();
variables.insert("project_name".to_string(), json!(project_name));
variables.insert("project_name_snake_case".to_string(), json!(to_snake_case(project_name)));
variables.insert("project_name_pascal_case".to_string(), json!(to_pascal_case(project_name)));
if let Some(init_vars) = initial_variables {
if let Some(obj) = init_vars.as_object() {
for (key, value) in obj {
variables.insert(key.clone(), value.clone());
}
}
}
if let Some(vars_config) = template_config.get("variables").and_then(|v| v.as_array()) {
for var_config in vars_config {
if let Some(var_obj) = var_config.as_object() {
let name = var_obj.get("name").and_then(|n| n.as_str()).unwrap_or("");
let prompt = var_obj.get("prompt").and_then(|p| p.as_str()).unwrap_or(name);
let var_type = var_obj.get("type").and_then(|t| t.as_str()).unwrap_or("string");
if variables.contains_key(name) {
continue;
}
let value = match var_type {
"select" => {
if let Some(options) = var_obj.get("options").and_then(|o| o.as_array()) {
let options_str: Vec<String> = options
.iter()
.filter_map(|o| o.as_str().map(|s| s.to_string()))
.collect();
if name == "data_format" && options_str.contains(&"parquet".to_string()) {
let selected = if interactive {
let selection = Select::new()
.with_prompt(prompt)
.items(&options_str)
.default(0)
.interact()?;
options_str[selection].clone()
} else {
options_str[0].clone()
};
json!(selected)
} else {
let selected = if interactive {
let selection = Select::new()
.with_prompt(prompt)
.items(&options_str)
.default(0)
.interact()?;
options_str[selection].clone()
} else {
options_str[0].clone()
};
json!(selected)
}
} else {
json!("")
}
},
"boolean" => {
let default = var_obj.get("default").and_then(|d| d.as_bool()).unwrap_or(false);
if interactive {
let selected = Confirm::new()
.with_prompt(prompt)
.default(default)
.interact()?;
json!(selected)
} else {
json!(default)
}
},
_ => { let default = var_obj.get("default").and_then(|d| d.as_str()).unwrap_or("");
if interactive {
let input: String = Input::new()
.with_prompt(prompt)
.default(default.to_string())
.interact_text()?;
json!(input)
} else {
json!(default)
}
}
};
variables.insert(name.to_string(), value);
}
}
}
if let Some(data_source) = variables.get("data_source").and_then(|s| s.as_str()) {
if !variables.contains_key("data_format") {
let data_format = match data_source {
"csv" => "csv",
"json" => "json",
"parquet" => "parquet",
_ => "csv" };
variables.insert("data_format".to_string(), json!(data_format));
}
}
Ok(Value::Object(variables))
}