text: #include <dirent.h>
  #include <unistd.h>
  #include <string>
  #include <vector>
  #include <iostream>
  
  #include "linux_parser.h"
  
  using std::stof;
  using std::string;
  using std::to_string;
  using std::vector;
  
  // DONE: An example of how to read data from the filesystem
  string LinuxParser::OperatingSystem() {
    string line;
    string key;
    string value;
    std::ifstream filestream(kOSPath);
    if (filestream.is_open()) {
      while (std::getline(filestream, line)) {
        std::replace(line.begin(), line.end(), ' ', '_');
        std::replace(line.begin(), line.end(), '=', ' ');
        std::replace(line.begin(), line.end(), '"', ' ');
        std::istringstream linestream(line);
        while (linestream >> key >> value) {
          if (key == "PRETTY_NAME") {
            std::replace(value.begin(), value.end(), '_', ' ');
            return value;
          }
        }
      }
    }
    return value;
  }
  
  // DONE: An example of how to read data from the filesystem
  string LinuxParser::Kernel() {
    string os;
    string version;
    string kernel;
    string line;
    std::ifstream stream(kProcDirectory + kVersionFilename);
    if (stream.is_open()) {
      std::getline(stream, line);
      std::istringstream linestream(line);
      linestream >> os >> version >> kernel;
    }
    return kernel;
  }
  
  // BONUS: Update this to use std::filesystem
  vector<int> LinuxParser::Pids() {
    vector<int> pids;
    DIR* directory = opendir(kProcDirectory.c_str());
    struct dirent* file;
    while ((file = readdir(directory)) != nullptr) {
      // Is this a directory?
      if (file->d_type == DT_DIR) {
        // Is every character of the name a digit?
        string filename(file->d_name);
        if (std::all_of(filename.begin(), filename.end(), isdigit)) {
          int pid = stoi(filename);
          pids.push_back(pid);
        }
      }
    }
    closedir(directory);
    return pids;
  }
  
  // TODO: Read and return the system memory utilization
  float LinuxParser::MemoryUtilization() { 
    string line;
    string key;
    string value;
    float memoryTotal;
    float memoryFree;
  
    std::ifstream stream(kProcDirectory + kMeminfoFilename);
    if (stream.is_open()) {
      while (std::getline(stream, line)) {
        std::istringstream linestream(line);
        while (linestream >> key >> value) {
          if (key == "MemTotal:") {
            memoryTotal = stof(value);
          }
          else if (key == "MemFree:"){
            memoryFree = stof(value);
          }
        }
      }
    }
    
    return (memoryTotal - memoryFree) / memoryTotal; 
  }
  
  // TODO: Read and return the system uptime
  long LinuxParser::UpTime() { 
    string line;
    string value;
    
    long uptime{0};
    
    std::ifstream stream(kProcDirectory + kUptimeFilename);
    if (stream.is_open()) {
      std::getline(stream, line);
      std::istringstream linestream(line);
      linestream >> value;
  
      uptime =  std::stol(value);
    }
     
     return uptime;
  }
  
  // TODO: Read and return the number of jiffies for the system
  long LinuxParser::Jiffies() { return 0; }
  
  // TODO: Read and return the number of active jiffies for a PID
  // REMOVE: [[maybe_unused]] once you define the function
  long LinuxParser::ActiveJiffies(int pid) { 
    string line;
    string value;
  
    long result = 0;
  
    std::ifstream stream(kProcDirectory + std::to_string(pid) + kStatFilename);
    if (stream.is_open()) {
      std::getline(stream, line);
      std::istringstream linestream(line);
  
      for(int i = 1; i < 18; i++){
        linestream  >> value;
        if(i>= 14 && i<=17){
          result += stol(value);
        }
      }
    }
    
    return result; 
  }
  
  // TODO: Read and return the number of active jiffies for the system
  long LinuxParser::ActiveJiffies() { 
    
    auto values = LinuxParser::CpuUtilization();
    
    return stol(values[kUser_]) + stol(values[kNice_]) + stol(values[kSystem_]) + stol(values[kIRQ_]) + stol(values[kSoftIRQ_]) + stol(values[kSteal_]); 
  }
  
  // TODO: Read and return the number of idle jiffies for the system
  long LinuxParser::IdleJiffies() { return 0; }
  
  // TODO: Read and return CPU utilization
  vector<string> LinuxParser::CpuUtilization() { 
    vector<string> return_vec;
    string line;
    string cpu;
    string value;
  
    std::ifstream stream(kProcDirectory + kStatFilename);
    if (stream.is_open()) {
      std::getline(stream, line);
      std::istringstream linestream(line);
      linestream >> cpu; //ignore keyword
        while (linestream >> value){                  
            return_vec.push_back(value);
        }
    }
       
    return return_vec;
  }
  
  // TODO: Read and return the total number of processes
  int LinuxParser::TotalProcesses() { 
    string line;
    string key;
    string value;
  
    std::ifstream stream(kProcDirectory + kStatFilename);
    if (stream.is_open()) {
      while (std::getline(stream, line)) {
        std::istringstream linestream(line);
        while (linestream >> key >> value) {
          if (key == "processes") {          
            return stoi(value);
          }
        }
      } 
    }
    
    return 0;
  }
  
  // TODO: Read and return the number of running processes
  int LinuxParser::RunningProcesses() { 
    string line;
    string key;
    string value;
  
    std::ifstream stream(kProcDirectory + kStatFilename);
    if (stream.is_open()) {
      while (std::getline(stream, line)) {
        std::istringstream linestream(line);
        while (linestream >> key >> value) {
          if (key == "procs_running") {          
            std::replace(value.begin(), value.end(), '_', ' ');
            return stoi(value);
          }
        }
      } 
    }
    
    return 0;
  }
  
  // TODO: Read and return the command associated with a process
  // REMOVE: [[maybe_unused]] once you define the function
  string LinuxParser::Command(int pid) {
    string line;
  
    std::ifstream stream(kProcDirectory + std::to_string(pid) + kCmdlineFilename);
    if (stream.is_open()) {
      std::getline(stream, line);
      std::replace(line.begin(), line.end(), '\0', ' ');
    }
    
    return line; 
  }
  
  // TODO: Read and return the memory used by a process
  // REMOVE: [[maybe_unused]] once you define the function
  int LinuxParser::Ram(int pid) { 
    string line;
    string key;
    string value;
  
    std::ifstream stream(kProcDirectory + std::to_string(pid) + kStatusFilename);
    if (stream.is_open()) {
      while (std::getline(stream, line)) {
        std::istringstream linestream(line);
        while (linestream >> key >> value) {
          if (key == "VmSize:") {          
            return stoi(value) / 1024;
          }
        }
      } 
    }
  
    return 0;
  }
  
  // TODO: Read and return the user ID associated with a process
  // REMOVE: [[maybe_unused]] once you define the function
  string LinuxParser::Uid(int pid) { 
    string line;
    string key;
    string value;
  
    std::ifstream stream(kProcDirectory + std::to_string(pid) + kStatusFilename);
    if (stream.is_open()) {
      while (std::getline(stream, line)) {
        std::istringstream linestream(line);
        while (linestream >> key >> value) {
          if (key == "Uid:") {          
            return value;
          }
        }
      } 
    }
  
    return string(); 
  }
  
  // TODO: Read and return the user associated with a process
  // REMOVE: [[maybe_unused]] once you define the function
  string LinuxParser::User(int pid) { 
    string line;
    string key;
    string pass;
    string value;
    std::ifstream filestream(kPasswordPath);
    if (filestream.is_open()) {
      while (std::getline(filestream, line)) {
        std::replace(line.begin(), line.end(), ':', ' ');
        std::istringstream linestream(line);
        while (linestream >> value >> pass >> key) {
          if (key == LinuxParser::Uid(pid)) {
            return value;
          }
        }
      }
    }
    return string();
  }
  
  // TODO: Read and return the uptime of a process
  // REMOVE: [[maybe_unused]] once you define the function
  long LinuxParser::UpTime(int pid) {   
    string line;
    string key;
    string value;
    long uptime{0};
  
    std::ifstream filestream(kProcDirectory + std::to_string(pid) + kStatFilename);
    if (filestream.is_open()) {
      std::getline(filestream, line);
      std::istringstream linestream(line);
  
      for(int i = 1; i <= 22; i++){
        linestream >> value;
      }
      
      uptime = std::stol(value) / sysconf(_SC_CLK_TCK);
    }
  
    return uptime;
  }
  