rodo_lib 0.1.2

A Library for a Todo Manager
Documentation
use std::{env, fs, path::PathBuf};

pub mod structs;
pub mod utils;

use structs::rodo::{Rodo, FIELDS};

const STD_DIR_SEARCH_COUNT: u32 = 5;

#[derive(Clone, Debug)]
/// Struct representing the current Data
///
/// * `rodo`: Struct containing the Data
/// * `file`: File used to read and write to
pub struct RConfig {
    pub rodo: Rodo,
    file: String,
}

impl RConfig {
    /// Loads Data from the given Filename and if set it searches the Parent Directories
    ///
    /// * `file`: the filename to load from/search for
    pub fn load(file: String) -> Result<Self, String> {
        // FIX: refactor this again (just looks aweful)
        match env::var("RODO_SEARCH_DIRS") {
            Ok(_) => {
                if let Ok(cwd) = env::current_dir() {
                    let mut dir = cwd;
                    let mut count: u32;
                    match env::var("RODO_SEARCH_COUNT") {
                        Ok(v) => match v.parse() {
                            Ok(c) => count = c,
                            Err(_) => {
                                return Err("Cant parse the Value inside of `RODO_SEARCH_COUNT`"
                                    .to_string())
                            }
                        },
                        Err(_) => count = STD_DIR_SEARCH_COUNT,
                    }

                    while count > 0 {
                        if let Ok(entries) = fs::read_dir(dir.clone()) {
                            for entry in entries.flatten() {
                                let path = entry.path();
                                if path.is_file()
                                    && path.file_name().unwrap().to_str().unwrap() == file
                                {
                                    match Self::load_from_file(file) {
                                        Ok(r) => return Ok(r),
                                        Err(m) => return Err(m),
                                    }
                                }
                            }
                        }
                        dir = dir.parent().unwrap().to_path_buf();
                        count -= 1;
                    }

                    Err(format!(
                        "Cant find the given file ({}) in the upper dirs",
                        file
                    ))
                } else {
                    Err("Cant get the current directory".to_string())
                }
            }
            Err(_) => match Self::load_from_file(file) {
                Ok(r) => Ok(r),
                Err(m) => Err(m),
            },
        }
    }

    /// Initialize a fresh Dataset
    ///
    /// * `file`: the file to be used
    /// * `defaults`: if it should add some default Tags, States and Priorites
    pub fn init(file: String, defaults: bool) -> Self {
        let rodos = Rodo::new();

        // Insert the Defaults
        if defaults {
            // TODO: add defaults
            todo!();
        }

        Self { rodo: rodos, file }
    }

    /// Executes a Function in the given Table
    ///
    /// * `field`: the Table with the Function and the Value
    pub fn run(&mut self, field: FIELDS) {
        self.rodo.parse(field);
    }

    /// Saves the current Data
    pub fn save(&self) -> Result<String, String> {
        match serde_json::to_string_pretty(&self.rodo) {
            Ok(content) => match fs::write(self.file.clone(), content) {
                Err(msg) => Err(msg.to_string()),
                Ok(_) => Ok(format!("Successfully written to: {}", self.file)),
            },
            Err(msg) => Err(msg.to_string()),
        }
    }

    /// Loads the Data from the given File
    ///
    /// * `file`: path to the file
    fn load_from_file(file: String) -> Result<Self, String> {
        let path = PathBuf::from(file.clone());
        match fs::read_to_string(path) {
            Ok(content) => match serde_json::from_str(&content) {
                Ok(r) => Ok(Self { rodo: r, file }),
                Err(msg) => Err(msg.to_string()),
            },
            Err(msg) => Err(msg.to_string()),
        }
    }
}