Documentation
use indicatif::{ProgressBar, ProgressStyle};
// use rand::seq::SliceRandom;
use std::fs::File;
use std::io::{BufWriter, Write};

use cf::FileSystem as cfs;
// use cf::IO as cio;
use rand::{distributions::Alphanumeric, distributions::Uniform, Rng};
use std::{thread, time::Duration};

pub fn stress(size: i32) {
    println!("Allocating {} MB memory", size);
    let m = (size / 4) as i64;
    let _v: Vec<i64> = (1..(1024 * 1024 * m)).collect();
    thread::sleep(Duration::from_millis(3000));
}

pub struct StringHelper {}
impl StringHelper {
    pub fn generate_string(&self, length: usize) -> String {
        rand::thread_rng()
            .sample_iter(&Alphanumeric)
            .take(length)
            .map(char::from)
            .collect()
    }
}

pub fn create_file_with_size(cnt: usize) {
    // Create a random binary file with size <cnt> MB
    let log_ddfile = "/tmp/ddfile.txt";
    let previous_f = std::fs::read_to_string(log_ddfile).unwrap();
    let f = previous_f.as_ref();

    if cfs::exists(f) {
        println!("Removing previous file: {}", f);
        match cfs::rm(f) {
            _ => println!("Done"),
        }
    }
    let curpath = std::env::current_dir().unwrap();
    let curpath = format!("{}/{}", curpath.to_string_lossy(), "cc.txt");
    std::fs::write(log_ddfile, curpath).expect("write file failed");

    let f = File::create("cc.txt").expect("Failed to create file");
    let mut writer = BufWriter::new(f);

    let pb = ProgressBar::new(cnt as u64);
    pb.set_style(ProgressStyle::default_bar()
        .template("{spinner:.red} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {pos:>3}MB/{len:3}MB ({eta})")
        .progress_chars("->-"));

    let range = Uniform::from(0..255);
    let mut v: Vec<u8> = rand::thread_rng()
        .sample_iter(&range)
        .take(1 << 20)
        .collect();

    for i in 0..cnt {
        for _ in 0..1 << 11 {
            // Just to slow things down.
            &v.pop();
            &v.push(rand::thread_rng().gen());
        }
        writer.write(&v).expect("Unable to write data");
        pb.set_position(i as u64);
    }
    pb.finish_with_message("DONE");
}

pub fn syscall(commands_chain: Vec<&str>) {
    let logger = cf::logger::get_logger();
    logger.info("Starting syscall");
    let mut cmd = std::process::Command::new(commands_chain[0].clone());
    for i in 1..commands_chain.len() {
        cmd.arg(commands_chain[i].clone());
    }
    cmd.spawn().expect("Failed to execute command");
    std::thread::sleep(std::time::Duration::from_millis(1000));
    logger.info("Done");
}