//! AbleOS capability tree implementation

use {
    crate::{tab, utils::TAB},
    alloc::{
        string::{String, ToString},
        vec,
    },
    core::fmt,
};

// Seperate
use alloc::vec::Vec;

struct Argument {
    name:  String,
    type_: String,
}

struct Function {
    name: String,
    args: Vec<Argument>,
    ret:  String,
}

struct Capability {
    name: String,
    functions: Vec<Function>,
    sub_capabilities: Vec<Capability>,
}

impl Capability {
    fn new(name: String) -> Capability {
        Capability {
            name,
            functions: Vec::new(),
            sub_capabilities: Vec::new(),
        }
    }
}

impl fmt::Display for Capability {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Capability: {}\r\n", self.name)?;
        for function in &self.functions {
            write!(f, "{}Function: {}\r\n", tab!(1), function.name)?;
            for arg in &function.args {
                write!(
                    f,
                    "{}Argument: {} (Type: {})\r\n",
                    tab!(2),
                    arg.name,
                    arg.type_
                )?;
            }
            write!(f, "{}Return Type: {}\r\n", tab!(2), &function.ret)?;
        }
        for sub_capability in &self.sub_capabilities {
            write!(f, "{}{}\r\n", tab!(1), sub_capability)?;
        }
        Ok(())
    }
}

// impl Capability {
//     fn to_string_with_indentation(&self, level: usize) -> String {
//         let indent = tab!(level);
//         let mut result = format!("{}Capability: {}\n", indent, self.name);
//         for function in &self.functions {
//             result.push_str(&format!(
//                 "{}Function: {}\n",
//                 tab!(indent + 1),
//                 function.name
//             ));
//             for arg in &function.args {
//                 result.push_str(&format!(
//                     "{}Argument: {} (Type: {})\n",
//                     tab!(indent + 2),
//                     arg.name,
//                     arg.type_
//                 ));
//             }
//             result.push_str(&format!(
//                 "{}Return Type: {}\n",
//                 tab!(indent + 2),
//                 &function.ret
//             ));
//         }
//         for sub_capability in &self.sub_capabilities {
//             result.push_str(&sub_capability.to_string_with_indentation(level + 1));
//         }
//         result
//     }
// }

struct CapabilityTree {
    capabilities: Vec<Capability>,
}

impl CapabilityTree {
    fn new() -> CapabilityTree {
        CapabilityTree {
            capabilities: Vec::new(),
        }
    }
}

/// A super simple capabilities example
pub fn example() {
    let mut capability_tree = Capability::new("VFS".to_string());

    let mut file_management_capability = Capability::new("File Management".to_string());
    file_management_capability.functions.push(Function {
        name: "OpenFile".to_string(),
        args: vec![
            Argument {
                name:  "path".to_string(),
                type_: "String".to_string(),
            },
            Argument {
                name:  "mode".to_string(),
                type_: "String".to_string(),
            },
        ],
        ret:  "FileHandle".to_string(),
    });
    file_management_capability.functions.push(Function {
        name: "ReadFile".to_string(),
        args: vec![
            Argument {
                name:  "file".to_string(),
                type_: "FileHandle".to_string(),
            },
            Argument {
                name:  "buffer".to_string(),
                type_: "&mut [u8]".to_string(),
            },
            Argument {
                name:  "length".to_string(),
                type_: "usize".to_string(),
            },
        ],
        ret:  "usize".to_string(),
    });
    file_management_capability.functions.push(Function {
        name: "WriteFile".to_string(),
        args: vec![
            Argument {
                name:  "file".to_string(),
                type_: "FileHandle".to_string(),
            },
            Argument {
                name:  "buffer".to_string(),
                type_: "&[u8]".to_string(),
            },
        ],
        ret:  "None".to_string(),
    });

    let mut directory_management_capability = Capability::new("Directory Management".to_string());
    directory_management_capability.functions.push(Function {
        name: "CreateDirectory".to_string(),
        args: vec![Argument {
            name:  "path".to_string(),
            type_: "String".to_string(),
        }],
        ret:  "bool".to_string(),
    });
    directory_management_capability.functions.push(Function {
        name: "ListDirectory".to_string(),
        args: vec![Argument {
            name:  "path".to_string(),
            type_: "String".to_string(),
        }],
        ret:  "Vec<String>".to_string(),
    });

    capability_tree
        .sub_capabilities
        .push(file_management_capability);
    capability_tree
        .sub_capabilities
        .push(directory_management_capability);

    log::debug!("CapTree\r\n{}", capability_tree);
}