use crate::converter::Converter;
use crate::errors::WysgyResult;
use crate::files::{CONFIG_JSON_CONTENTS, GV_TEMPLATE_CONTENTS};
use crate::node::Node;
use crate::rel::Rel;
use crate::wysgy::Wysgy;
use glob::glob;
use prettytable::Table;
use serde_json::{json, Value};
use std::cmp::max;
use std::error;
use std::fs::{self, DirEntry};
use std::io::{BufRead, ErrorKind};
use std::path::{PathBuf, Path};
use std::process::{Child, Command};
struct FileLoc {}
impl FileLoc {
fn nodes_dir(w: &Wysgy) -> PathBuf {
let nd = w.path.clone();
nd.push("nodes");
nd
}
fn rels_dir(w: &Wysgy) -> PathBuf {
let rd = w.path.clone();
rd.push("rels");
rd
}
fn max_file_id(path: PathBuf) -> WysgyResult<usize> {
info!("Finding largest id...");
let max_id: usize = 0;
for fl in fs::read_dir(path)? {
max_id = max(
fl.expect("No dir entry")
.path()
.file_stem()
.expect("No file stem")
.to_str()
.expect("No str")
.parse::<usize>()?,
max_id,
);
}
Ok(max_id)
}
fn apply_to_files_until_true(path: &Path, f: fn(&DirEntry)-> bool) -> WysgyResult<()>{
if path.is_dir() {
for e in fs::read_dir(path)? {
if e?.path().is_dir() {
FileLoc::apply_to_files_until_true(path, f)
} else {
if f(&e?) {
}
}
}
}
Ok(())
}
}
pub trait FileOps {
fn get_node(&self, id: String) -> WysgyResult<Node>;
fn get_rel(&self, id: String) -> WysgyResult<Rel>;
fn get_all_nodes(&self) -> WysgyResult<Vec<Node>>;
fn get_all_rels(&self) -> WysgyResult<Vec<Rel>>;
fn save_node(&self, id: String, n: Node) -> WysgyResult<()>;
fn save_rel(&self, id: String, r: Rel) -> WysgyResult<()>;
fn add_node(&self, kv: Value) -> WysgyResult<Node>;
fn add_rel(&self, kv: Value, src_id: String, dst_id: String) -> WysgyResult<Rel>;
fn del_node(&self, id: String) -> WysgyResult<()>;
fn del_rel(&self, id: String) -> WysgyResult<()>;
fn ext(s: String) -> String;
fn nodes_dir(&self) -> PathBuf;
fn create_dir(&self, name: &String) -> Result<(), Box<error::Error>>;
fn create_file(&self, name: String, contents: &str) -> Result<(), Box<dyn error::Error>>;
fn rel_dir(&self) -> PathBuf;
fn new_node_id(&self) -> String;
fn new_rel_id(&self, src_id: String, dst_id: String) -> String;
fn node(&self, s: &String) -> String;
fn file(&self, s: &String) -> String;
fn rel(&self, s: &String, d: &String) -> Option<String>;
fn delete(&self) -> std::io::Result<()>;
fn create(name: String) -> Result<Self, Box<error::Error>>;
fn open(name: String) -> Result<Self, Box<error::Error>>;
}
impl FileOps for Wysgy {
fn get_node(&self, id: String) -> WysgyResult<Node> {
let node_path = FileLoc::nodes_dir(self);
node_path.push(format!("{}.wnode", id));
let node_contents = fs::read_to_string(node_path)?;
Ok({
kv: Converter::kv_to_json(&node_contents, "\n")?,
id: id
})
}
fn get_rel(&self, id: String) -> WysgyResult<Rel> {
let rel_name = format!("{}.wrel", id);
FileLoc::apply_to_files(, |e|{e == })
}
fn add_node(&self, kv: Value) -> WysgyResult<Node> {
let n = Node {
id: FileOps::new_node_id(self),
kv: kv,
};
Ok(n)
}
fn add_rel(&self, kv: Value, src_id: String, dst_id: String) -> WysgyResult<Rel> {
let r = Rel {
src_id: src_id,
dst_id: dst_id,
kv: kv,
id: FileOps::new_rel_id(self, src_id, dst_id),
};
Ok(r)
}
fn new_node_id(&self) -> String {
FileLoc::max_file_id(FileLoc::nodes_dir(self))
.expect("No nodes id")
.to_string()
}
fn new_rel_id(&self, src_id: String, dst_id: String) -> String {
let path = FileLoc::rels_dir(self);
path.push(src_id);
path.push(dst_id);
FileLoc::max_file_id(path)
.expect("No rels id")
.to_string()
}
fn ext(s: String) -> String {
let new_s = s + &String::from("");
new_s
}
fn nodes_dir(&self) -> PathBuf {
let mut f = self.path.clone();
f.push("nodes");
f
}
fn rel_dir(&self) -> PathBuf {
let mut f = self.path.clone();
f.push("rels");
f
}
fn node(&self, s: &String) -> String {
let mut f = self.nodes_dir();
info!("Finding largest id...");
let max_id = Project::max_file_id(&(f.to_str().unwrap().to_string() + "/*.wnode"));
let new_id = max_id + 1;
info!("New node is {}", new_id);
f.push(format!("{}.wnode", new_id));
f.to_str().unwrap().to_string()
}
fn file(&self, s: &String) -> String {
let mut f = PathBuf::from(&self.path);
let fname = PathBuf::from(s.clone());
f.push("files");
f.push(fname.file_name().unwrap().to_str().unwrap());
f.to_str().unwrap().to_string()
}
fn rel(&self, s: &String, d: &String) -> Option<String> {
let mut r = self.rel_dir();
r.push(s);
r.push(d);
if let Some(dir_to_make) = &r.to_str() {
fs::create_dir(dir_to_make).unwrap();
let max_id = Project::max_file_id(&(r.to_str().unwrap().to_string() + "*.wrel"));
let new_id = max_id + 1;
info!("New rel is {}", new_id);
r.push(format!("{}.wrel", new_id));
Some(r.to_str().unwrap().to_string())
} else {
info!("Failed to create rel: {} -> {}", s, d);
None
}
}
}