#include "task.h"

#include <errno.h>
#include <fcntl.h>
#include <log/log.h>
#include <stdio.h>

#include <cctype>
#include <cstdlib>
#include <memory>
#include <sstream>

#include <android-base/unique_fd.h>

#include "stdio_filebuf.h"
#include "string_trim.h"

namespace {

const char kProcBase[] = "/proc";

android::base::unique_fd OpenTaskDirectory(pid_t task_id) {
  std::ostringstream stream;
  stream << kProcBase << "/" << task_id;

  return android::base::unique_fd(
      open(stream.str().c_str(), O_RDONLY | O_DIRECTORY));
}

void ParseUidStatusField(const std::string& value, std::array<int, 4>& ids) {
  const char* start = value.c_str();

  ids[0] = std::strtol(start, const_cast<char**>(&start), 10);
  ids[1] = std::strtol(start, const_cast<char**>(&start), 10);
  ids[2] = std::strtol(start, const_cast<char**>(&start), 10);
  ids[3] = std::strtol(start, const_cast<char**>(&start), 10);
}

}  // anonymous namespace

namespace android {
namespace dvr {

Task::Task(pid_t task_id)
    : task_id_(task_id),
      thread_group_id_(-1),
      parent_process_id_(-1),
      thread_count_(0),
      cpus_allowed_mask_(0) {
  task_fd_ = OpenTaskDirectory(task_id_);
  ALOGE_IF(task_fd_.get() < 0,
           "Task::Task: Failed to open task directory for task_id=%d: %s",
           task_id, strerror(errno));

  ReadStatusFields();

  ALOGD_IF(TRACE, "Task::Task: task_id=%d name=%s tgid=%d ppid=%d cpu_mask=%x",
           task_id_, name_.c_str(), thread_group_id_, parent_process_id_,
           cpus_allowed_mask_);
}

base::unique_fd Task::OpenTaskFile(const std::string& name) const {
  const std::string relative_path = "./" + name;
  return base::unique_fd(
      openat(task_fd_.get(), relative_path.c_str(), O_RDONLY));
}

UniqueFile Task::OpenTaskFilePointer(const std::string& name) const {
  const std::string relative_path = "./" + name;
  base::unique_fd fd(openat(task_fd_.get(), relative_path.c_str(), O_RDONLY));
  if (fd.get() < 0) {
    ALOGE("Task::OpenTaskFilePointer: Failed to open /proc/%d/%s: %s", task_id_,
          name.c_str(), strerror(errno));
    return nullptr;
  }

  UniqueFile fp(fdopen(fd.release(), "r"));
  if (!fp)
    ALOGE("Task::OpenTaskFilePointer: Failed to fdopen /proc/%d/%s: %s",
          task_id_, name.c_str(), strerror(errno));

  return fp;
}

std::string Task::GetStatusField(const std::string& field) const {
  if (auto file = OpenTaskFilePointer("status")) {
    stdio_filebuf<char> filebuf(file.get());
    std::istream file_stream(&filebuf);

    for (std::string line; std::getline(file_stream, line);) {
      auto offset = line.find(field);

      ALOGD_IF(TRACE,
               "Task::GetStatusField: field=\"%s\" line=\"%s\" offset=%zd",
               field.c_str(), line.c_str(), offset);

      if (offset == std::string::npos)
        continue;

      // The status file has lines with the format <field>:<value>. Extract the
      // value after the colon.
      return Trim(line.substr(offset + field.size() + 1));
    }
  }

  return "[unknown]";
}

void Task::ReadStatusFields() {
  if (auto file = OpenTaskFilePointer("status")) {
    stdio_filebuf<char> filebuf(file.get());
    std::istream file_stream(&filebuf);

    for (std::string line; std::getline(file_stream, line);) {
      auto offset = line.find(":");
      if (offset == std::string::npos) {
        ALOGW("ReadStatusFields: Failed to find delimiter \":\" in line=\"%s\"",
              line.c_str());
        continue;
      }

      std::string key = line.substr(0, offset);
      std::string value = Trim(line.substr(offset + 1));

      ALOGD_IF(TRACE, "Task::ReadStatusFields: key=\"%s\" value=\"%s\"",
               key.c_str(), value.c_str());

      if (key == "Name")
        name_ = value;
      else if (key == "Tgid")
        thread_group_id_ = std::strtol(value.c_str(), nullptr, 10);
      else if (key == "PPid")
        parent_process_id_ = std::strtol(value.c_str(), nullptr, 10);
      else if (key == "Uid")
        ParseUidStatusField(value, user_id_);
      else if (key == "Gid")
        ParseUidStatusField(value, group_id_);
      else if (key == "Threads")
        thread_count_ = std::strtoul(value.c_str(), nullptr, 10);
      else if (key == "Cpus_allowed")
        cpus_allowed_mask_ = std::strtoul(value.c_str(), nullptr, 16);
      else if (key == "Cpus_allowed_list")
        cpus_allowed_list_ = value;
    }
  }
}

std::string Task::GetCpuSetPath() const {
  if (auto file = OpenTaskFilePointer("cpuset")) {
    stdio_filebuf<char> filebuf(file.get());
    std::istream file_stream(&filebuf);

    std::string line = "";
    std::getline(file_stream, line);

    return Trim(line);
  } else {
    return "";
  }
}

}  // namespace dvr
}  // namespace android
