new-home-application 0.1.3

New Home iot application framework. Meant to build application for the New Home Core
Documentation
use std::collections::HashMap;

use serde_json::{Value, Map};

use crate::method::method_callable::MethodCallable;
use crate::method::method_manager::MethodManager;
use crate::method::method_structure::{Method, MethodArgument, MethodArguments, MethodResult};
use crate::method::response_formatter::{JsonResponseFormatter, ResponseFormatter};

pub struct HelpCommand {
    methods: HashMap<String, Method>,
}

impl HelpCommand {
    pub fn new(methods: HashMap<String, Method>) -> Self {
        Self {
            methods
        }
    }

    pub fn self_register(method_manager: &mut Box<dyn MethodManager>) {
        let callable: Box<dyn MethodCallable> = Box::new(Self::new(method_manager.get_methods()));

        method_manager.add_method(Method {
            name: String::from("help"),
            description: String::from("Shows help for this application or a given method"),
            help: String::from("help [method]"),
            arguments: vec![
                MethodArgument {
                    name: String::from("method"),
                    description: String::from("Sets the name of the method for that the help should be displayed"),
                    help: String::from("The name of the method where you need help for leave blank to show list of available methods"),
                    value: None,
                    required: true,
                }
            ],
        }, callable);
    }

    fn get_method_list(&self) -> MethodResult {
        let mut list = vec![];

        for name in self.methods.keys() {
            list.push(Value::from(name.clone()));
        }

        let mut formatter = JsonResponseFormatter::new();
        formatter.add_markdown(&String::from("# Available commands"));
        formatter.add_list(list);

        formatter.as_result(0)
    }

    fn get_method_arguments(&self, method: &Method) -> Vec<Map<String, Value>> {
        let mut arguments = vec![];

        for argument in &method.arguments {
            arguments.push(self.get_method_argument(&argument))
        }

        arguments
    }
    fn get_method_argument(&self, argument: &MethodArgument) -> Map<String, Value> {
        let mut map = Map::new();

        map.insert(String::from("name"), Value::from(String::from(argument.name.clone())));
        map.insert(String::from("description"), Value::from(String::from(argument.description.clone())));
        map.insert(String::from("help"), Value::from(String::from(argument.help.clone())));
        map.insert(String::from("required"), Value::from(argument.required.clone()));

        if argument.value.is_some() {
            map.insert(String::from("value"), argument.value.clone().unwrap());
        }

        map
    }
}

impl MethodCallable for HelpCommand {
    fn call(&self, arguments: MethodArguments) -> MethodResult {
        let method_result = arguments.get_argument(&String::from("method"));

        if method_result.is_none() || method_result.as_ref().unwrap().is_null() {
            return self.get_method_list();
        }

        let method_name = method_result.unwrap();

        if !method_name.is_string() {
            let mut formatter = JsonResponseFormatter::new();
            formatter.add_error(&String::from("Argument 'method' has to be of type String"));

            return formatter.as_result(1);
        }

        let method_definition = self.methods.get(method_name.as_str().unwrap());

        if method_definition.is_none() {
            return JsonResponseFormatter::error(&String::from("Method not found"));
        }

        let mut data: Map<String, Value> = Map::new();

        data.insert(String::from("name"), Value::from(String::from(method_definition.unwrap().name.clone())));
        data.insert(String::from("description"), Value::from(String::from(method_definition.unwrap().description.clone())));
        data.insert(String::from("help"), Value::from(String::from(method_definition.unwrap().help.clone())));
        data.insert(String::from("arguments"), Value::from(self.get_method_arguments(method_definition.unwrap())));

        JsonResponseFormatter::table(data)
    }
}