use std::collections::HashMap;
use yttrium_key_base::environment::Environment;
use yttrium_key_base::databases::{
DatabaseManager,
Database,
};
use crate::tree_creator;
pub async fn interpret_tree<'a, Manager: DatabaseManager<DB>, DB: Database>(tree: Vec<tree_creator::TreeNode>, key_list: &HashMap<String, Box<dyn yttrium_key_base::Key<Manager, DB> + Send + Sync>>, mut environment: Environment<'a, Manager, DB>) -> Result<InterpretationResult<'a, Manager, DB>, String> {
let mut current_index = 0; let mut interpretable_tree = Vec::with_capacity(tree.len());
let mut next_rule = None;
for node in tree {
let cond_if_false = node.key == "cond" && node.parameters.len() == 3;
let param_count = node.parameters.len();
interpretable_tree.push(InterpretableNode {
inner_node: node,
interpreted_param: 0, interpreted_subparam: 0, returned_values: Vec::with_capacity(param_count),
returned_subvalues: Vec::with_capacity(2),
cond_if_false: cond_if_false,
});
}
loop {
let mut current_node = &mut interpretable_tree[current_index];
if current_node.inner_node.key == "cond" && current_node.interpreted_param == 1 {
if current_node.returned_values[0].is_empty() || current_node.returned_values[0] == "0" {
if current_node.inner_node.parameters.len() == 3 {
current_node.interpreted_param = 2;
} else {
current_index = current_node.inner_node.parent.unwrap();
current_node = &mut interpretable_tree[current_index];
current_node.returned_subvalues.push(String::from(""));
}
} else {
let current_parameter = ¤t_node.inner_node.parameters[current_node.interpreted_param];
match current_parameter {
tree_creator::Parameter::Nodes(nodes) => {
if nodes.len() == current_node.returned_subvalues.len() {
current_node.finish_subvalue();
current_node.interpreted_param += 1;
} else {
current_index = nodes[current_node.interpreted_subparam];
current_node.interpreted_subparam += 1;
}
}
tree_creator::Parameter::String(text) => {
current_node.returned_values.push(text.clone());
current_node.interpreted_param += 1;
current_node.interpreted_subparam = 0;
}
}
}
} else if current_node.inner_node.key == "cond" && current_node.interpreted_param == 2 {
if current_node.returned_values[0].is_empty() || current_node.returned_values[0] == "0" {
let current_parameter = ¤t_node.inner_node.parameters[current_node.interpreted_param];
match current_parameter {
tree_creator::Parameter::Nodes(nodes) => {
if nodes.len() == current_node.returned_subvalues.len() {
current_node.finish_subvalue();
current_node.interpreted_param += 1;
} else {
current_index = nodes[current_node.interpreted_subparam];
current_node.interpreted_subparam += 1;
}
}
tree_creator::Parameter::String(text) => {
current_node.returned_values.push(text.clone());
current_node.interpreted_param += 1;
current_node.interpreted_subparam = 0;
}
}
} else {
let to_return = current_node.returned_values[1].clone();
current_index = current_node.inner_node.parent.unwrap();
current_node = &mut interpretable_tree[current_index];
current_node.returned_subvalues.push(to_return);
}
} else if current_node.inner_node.key == "cond" && current_node.interpreted_param == 3 {
let to_return = current_node.returned_values[1].clone();
current_index = current_node.inner_node.parent.unwrap();
current_node = &mut interpretable_tree[current_index];
current_node.returned_subvalues.push(to_return);
} else if current_node.inner_node.parameters.len() == current_node.interpreted_param {
match current_node.inner_node.parent {
Some(parent) => {
let returned;
if current_node.inner_node.key == "ars" {
next_rule = Some(current_node.returned_values.join(""));
returned = String::new();
} else if current_node.inner_node.key == "literal" {
returned = current_node.returned_values[0].clone();
} else if current_node.inner_node.key == "exit" {
let target;
match environment.target.parse::<u64>() {
Ok(channel) => {
target = Some(serenity::model::id::ChannelId::from(channel));
}
Err(_) => {
target = None;
}
}
return Ok(InterpretationResult {
message: current_node.returned_values.join(""),
environment: environment,
next_rule: next_rule,
target: target,
});
} else {
match key_list.get(¤t_node.inner_node.key) {
Some(key) => {
match key.run_key(¤t_node.returned_values, &mut environment).await {
Ok(result) => {
returned = result;
}
Err(error) => {
return Err(error);
}
}
}
None => {
return Err(String::from("One of the keys does not exist"));
}
}
}
current_index = parent;
current_node = &mut interpretable_tree[current_index];
current_node.returned_subvalues.push(returned);
}
None => {
let target;
match environment.target.parse::<u64>() {
Ok(channel) => {
target = Some(serenity::model::id::ChannelId::from(channel));
}
Err(_) => {
target = None;
}
}
return Ok(InterpretationResult {
message: current_node.returned_values.join(""),
environment: environment,
next_rule: next_rule,
target: target,
});
}
}
} else {
let current_parameter = ¤t_node.inner_node.parameters[current_node.interpreted_param];
match current_parameter {
tree_creator::Parameter::Nodes(nodes) => {
if nodes.len() == current_node.returned_subvalues.len() {
current_node.finish_subvalue();
current_node.interpreted_param += 1;
} else {
current_index = nodes[current_node.interpreted_subparam];
current_node.interpreted_subparam += 1;
}
}
tree_creator::Parameter::String(text) => {
current_node.returned_values.push(text.clone());
current_node.interpreted_param += 1;
current_node.interpreted_subparam = 0;
}
}
}
}
}
#[derive(Debug)]
pub struct InterpretationResult<'a, Manager: DatabaseManager<DB>, DB: Database> {
pub message: String,
pub environment: Environment<'a, Manager, DB>,
pub next_rule: Option<String>,
pub target: Option<serenity::model::id::ChannelId>,
}
struct InterpretableNode {
pub inner_node: tree_creator::TreeNode,
pub interpreted_param: usize,
pub interpreted_subparam: usize,
pub returned_values: Vec<String>,
pub returned_subvalues: Vec<String>,
pub cond_if_false: bool,
}
impl InterpretableNode {
fn finish_subvalue(&mut self) {
self.returned_values.push(self.returned_subvalues.join(""));
self.returned_subvalues.clear();
self.interpreted_subparam = 0;
}
}