// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <grp.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

#include <map>
#include <memory>
#include <optional>

#include <vector>

#include <base/check.h>
#include <base/files/file.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/process/launch.h>
#include <base/strings/stringprintf.h>
#include <libmems/common_types.h>
#include <libsar/sar_config_reader_delegate_impl.h>
#include <vpd/vpd.h>

#include "mems_setup/delegate_impl.h"

namespace mems_setup {

namespace {
const char kSysModulePath[] = "/sys/module";
}  // namespace

bool LoadVpdFromString(const std::string& vpd_data,
                       std::map<std::string, std::string>* cache) {
  CHECK(cache);

  size_t nl_pos = 0;
  const size_t vpd_len = vpd_data.size();
  while (nl_pos < vpd_len) {
    const auto i_eq = vpd_data.find('=', nl_pos);
    if (i_eq == std::string::npos)
      break;

    auto i_nl = vpd_data.find('\n', i_eq + 1);
    if (i_nl == std::string::npos)
      i_nl = vpd_len;

    // VPD entries come in "key"="value" form, including the quotes;
    // the purpose of the substring operations here is to remove those
    // quotes, as they are inconvenient to deal with from C++ code.
    const auto key = vpd_data.substr(nl_pos + 1, i_eq - nl_pos - 2);
    const auto value = vpd_data.substr(i_eq + 2, i_nl - i_eq - 3);
    cache->emplace(key, value);

    nl_pos = i_nl + 1;
  }

  return true;
}

DelegateImpl::DelegateImpl()
    : Delegate(std::make_unique<libsar::SarConfigReaderDelegateImpl>()) {}

std::optional<std::string> DelegateImpl::ReadVpdValue(const std::string& key) {
  // All VPD keys we're looking for should be in Read-Only region.
  return vpd::Vpd().GetValue(vpd::VpdRo, key);
}

bool DelegateImpl::ProbeKernelModule(const std::string& module) {
  base::FilePath init_path(kSysModulePath);
  init_path = init_path.Append(module).Append("initstate");

  std::string init_data;

  // If we can tell that a module has been loaded, then just return along
  // the happy path instead of forking a new process.
  if (base::ReadFileToString(init_path, &init_data)) {
    if (init_data == "live\n")
      return true;
  }

  std::vector<std::string> argv;
  argv.emplace_back("/usr/bin/modprobe");
  argv.emplace_back("-q");
  argv.emplace_back(module);

  base::Process process(base::LaunchProcess(argv, base::LaunchOptions()));
  if (!process.IsValid()) {
    LOG(ERROR) << "failed to launch modprobe";
    return false;
  }
  int exit_code = -1;
  if (!process.WaitForExit(&exit_code)) {
    LOG(ERROR) << "modprobe exit could not be detected";
    return false;
  }
  return exit_code == 0;
}

bool DelegateImpl::CreateDirectory(const base::FilePath& fp) {
  return base::CreateDirectory(fp);
}

bool DelegateImpl::Exists(const base::FilePath& fp) {
  return base::PathExists(fp);
}

std::vector<base::FilePath> DelegateImpl::EnumerateAllFiles(
    base::FilePath file_path) {
  std::vector<base::FilePath> files;

  base::FileEnumerator file_enumerator(file_path, false,
                                       base::FileEnumerator::FILES);

  for (base::FilePath file = file_enumerator.Next(); !file.empty();
       file = file_enumerator.Next())
    files.push_back(file);

  return files;
}

std::optional<gid_t> DelegateImpl::FindGroupId(const char* group) {
  size_t len = 1024;
  const auto max_len = sysconf(_SC_GETGR_R_SIZE_MAX);
  if (max_len != -1)
    len = max_len;

  std::vector<char> buf(len);
  struct group result;
  struct group* resultp = nullptr;

  getgrnam_r(group, &result, buf.data(), len, &resultp);
  if (!resultp)
    return std::nullopt;

  return resultp->gr_gid;
}

int DelegateImpl::GetPermissions(const base::FilePath& path) {
  int mode = 0;
  bool ok = base::GetPosixFilePermissions(path, &mode);
  if (ok)
    return mode;
  return 0;
}

bool DelegateImpl::SetPermissions(const base::FilePath& path, int mode) {
  return base::SetPosixFilePermissions(path, mode);
}

bool DelegateImpl::SetOwnership(const base::FilePath& path,
                                uid_t user,
                                gid_t group) {
  return lchown(path.value().c_str(), user, group) == 0;
}

std::optional<std::string> DelegateImpl::GetIioSarSensorDevlink(
    std::string sys_path) {
  return libmems::GetIioSarSensorDevlink(sys_path);
}

brillo::CrosConfigInterface* DelegateImpl::GetCrosConfig() {
  return &cros_config_;
}

}  // namespace mems_setup
