// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <map>
#include <sstream>

#include <base/bind.h>
#include <base/callback.h>
#include <base/logging.h>
#include <base/memory/weak_ptr.h>
#include <base/run_loop.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_tokenizer.h>
#include <base/strings/string_util.h>
#include <base/threading/thread_task_runner_handle.h>
#include <base/time/time.h>
#include <re2/re2.h>

#include "diagnostics/telem/telem_connection.h"
#include "diagnostics/telem/telemetry_group_enum.h"
#include "diagnosticsd.pb.h"  // NOLINT(build/include)

namespace diagnostics {

namespace {
// Generic callback which moves the response to its destination. All
// specific parsing logic is left to other methods, allowing this
// single callback to be used for each gRPC request.
template <typename ResponseType>
void OnRpcResponseReceived(std::unique_ptr<ResponseType>* response_destination,
                           base::Closure run_loop_quit_closure,
                           std::unique_ptr<ResponseType> response) {
  *response_destination = std::move(response);
  run_loop_quit_closure.Run();
}

// Mapping between groups and items. Each item belongs to exactly one
// group.
const std::map<TelemetryGroupEnum, std::vector<TelemetryItemEnum>> group_map = {
    {TelemetryGroupEnum::kDisk,
     {TelemetryItemEnum::kMemTotalMebibytes,
      TelemetryItemEnum::kMemFreeMebibytes}}};

}  // namespace

TelemConnection::TelemConnection() {
  owned_client_impl_ = std::make_unique<AsyncGrpcClientAdapterImpl>();
  client_impl_ = owned_client_impl_.get();
}

TelemConnection::TelemConnection(AsyncGrpcClientAdapter* client)
    : client_impl_(client) {}

TelemConnection::~TelemConnection() {
  ShutdownClient();
}

void TelemConnection::Connect(const std::string& target_uri) {
  DCHECK(!client_impl_->IsConnected());

  client_impl_->Connect(target_uri);
}

const base::Optional<base::Value> TelemConnection::GetItem(
    TelemetryItemEnum item, base::TimeDelta acceptable_age) {
  // First, check to see if the desired telemetry information is
  // present and valid in the cache. If so, just return it.
  if (!cache_.IsValid(item, acceptable_age)) {
    // When no valid cached data is present, make a gRPC request to
    // obtain the appropriate telemetry data. This may result in
    // more data being fetched and cached than just the desired item.
    switch (item) {
      case TelemetryItemEnum::kUptime:
        UpdateProcData(grpc_api::GetProcDataRequest::FILE_UPTIME);
        break;
      case TelemetryItemEnum::kMemTotalMebibytes:  // FALLTHROUGH
      case TelemetryItemEnum::kMemFreeMebibytes:
        UpdateProcData(grpc_api::GetProcDataRequest::FILE_MEMINFO);
        break;
      case TelemetryItemEnum::kNumRunnableEntities:  // FALLTHROUGH
      case TelemetryItemEnum::kNumExistingEntities:
        UpdateProcData(grpc_api::GetProcDataRequest::FILE_LOADAVG);
        break;
      case TelemetryItemEnum::kTotalIdleTimeUserHz:  // FALLTHROUGH
      case TelemetryItemEnum::kIdleTimePerCPUUserHz:
        UpdateProcData(grpc_api::GetProcDataRequest::FILE_STAT);
        break;
      case TelemetryItemEnum::kAcpiButton:
        UpdateProcData(grpc_api::GetProcDataRequest::DIRECTORY_ACPI_BUTTON);
        break;
      case TelemetryItemEnum::kNetStat:
        UpdateProcData(grpc_api::GetProcDataRequest::FILE_NET_NETSTAT);
        break;
      case TelemetryItemEnum::kNetDev:
        UpdateProcData(grpc_api::GetProcDataRequest::FILE_NET_DEV);
        break;
      case TelemetryItemEnum::kHwmon:
        UpdateSysfsData(grpc_api::GetSysfsDataRequest::CLASS_HWMON);
        break;
      case TelemetryItemEnum::kThermal:
        UpdateSysfsData(grpc_api::GetSysfsDataRequest::CLASS_THERMAL);
        break;
      case TelemetryItemEnum::kDmiTables:
        UpdateSysfsData(grpc_api::GetSysfsDataRequest::FIRMWARE_DMI_TABLES);
        break;
    }
  }

  return cache_.GetParsedData(item);
}

const std::vector<
    std::pair<TelemetryItemEnum, const base::Optional<base::Value>>>
TelemConnection::GetGroup(TelemetryGroupEnum group,
                          base::TimeDelta acceptable_age) {
  std::vector<std::pair<TelemetryItemEnum, const base::Optional<base::Value>>>
      telem_items;

  for (TelemetryItemEnum item : group_map.at(group))
    telem_items.emplace_back(item, GetItem(item, acceptable_age));

  return telem_items;
}

// Sends a GetProcDataRequest, then parses and caches the response.
// If the response format for a specific telemetry item is incorrectly
// formatted, that item will be ignored and not cached, but other,
// correctly formatted telemetry items from the same response will
// still be parsed and cached.
void TelemConnection::UpdateProcData(grpc_api::GetProcDataRequest::Type type) {
  grpc_api::GetProcDataRequest request;
  request.set_type(type);
  std::unique_ptr<grpc_api::GetProcDataResponse> response;
  base::RunLoop run_loop;

  client_impl_->GetProcData(
      request, base::Bind(&OnRpcResponseReceived<grpc_api::GetProcDataResponse>,
                          base::Unretained(&response), run_loop.QuitClosure()));
  VLOG(0) << "Sent GetProcDataRequest";
  run_loop.Run();

  if (!response) {
    LOG(ERROR) << "No ProcDataResponse received.";
    return;
  }

  // Parse the response and cache the parsed data.
  switch (type) {
    case grpc_api::GetProcDataRequest::FILE_UPTIME:
      ExtractDataFromProcUptime(*response);
      break;
    case grpc_api::GetProcDataRequest::FILE_MEMINFO:
      ExtractDataFromProcMeminfo(*response);
      break;
    case grpc_api::GetProcDataRequest::FILE_LOADAVG:
      ExtractDataFromProcLoadavg(*response);
      break;
    case grpc_api::GetProcDataRequest::FILE_STAT:
      ExtractDataFromProcStat(*response);
      break;
    case grpc_api::GetProcDataRequest::DIRECTORY_ACPI_BUTTON:
      ExtractDataFromProcAcpiButton(*response);
      break;
    case grpc_api::GetProcDataRequest::FILE_NET_NETSTAT:
      ExtractDataFromProcNetStat(*response);
      break;
    case grpc_api::GetProcDataRequest::FILE_NET_DEV:
      ExtractDataFromProcNetDev(*response);
      break;
    default:
      LOG(ERROR) << "Bad ProcDataRequest type: " << type;
      return;
  }
}

// Sends a GetSysfsDataRequest, then parses and caches the response.
// If the response format for a specific telemetry item is incorrectly
// formatted, that item will be ignored and not cached, but other,
// correctly formatted telemetry items from the same response will
// still be parsed and cached.
void TelemConnection::UpdateSysfsData(
    grpc_api::GetSysfsDataRequest::Type type) {
  grpc_api::GetSysfsDataRequest request;
  request.set_type(type);
  std::unique_ptr<grpc_api::GetSysfsDataResponse> response;
  base::RunLoop run_loop;

  client_impl_->GetSysfsData(
      request,
      base::Bind(&OnRpcResponseReceived<grpc_api::GetSysfsDataResponse>,
                 base::Unretained(&response), run_loop.QuitClosure()));
  VLOG(0) << "Sent GetSysfsDataRequest";
  run_loop.Run();

  if (!response) {
    LOG(ERROR) << "No SysfsDataResponse received.";
    return;
  }

  // Parse the response and cache the parsed data.
  switch (type) {
    case grpc_api::GetSysfsDataRequest::CLASS_HWMON:
      ExtractDataFromSysfsHwmon(*response);
      break;
    case grpc_api::GetSysfsDataRequest::CLASS_THERMAL:
      ExtractDataFromSysfsThermal(*response);
      break;
    case grpc_api::GetSysfsDataRequest::FIRMWARE_DMI_TABLES:
      ExtractDataFromSysfsDmiTables(*response);
      break;
    default:
      LOG(ERROR) << "Bad SysfsDataRequest type: " << type;
      return;
  }
}

void TelemConnection::ShutdownClient() {
  base::RunLoop loop;
  client_impl_->Shutdown(loop.QuitClosure());
  loop.Run();
}

// Parse the raw /proc/meminfo file.
void TelemConnection::ExtractDataFromProcMeminfo(
    const grpc_api::GetProcDataResponse& response) {
  // Make sure we received exactly one file in the response.
  if (response.file_dump_size() != 1) {
    LOG(ERROR) << "Bad GetProcDataResponse from request of type FILE_MEMINFO.";
    return;
  }

  // Parse the meminfo response for kMemTotal and kMemFree.
  base::StringPairs keyVals;
  base::SplitStringIntoKeyValuePairs(response.file_dump(0).contents(), ':',
                                     '\n', &keyVals);

  for (int i = 0; i < keyVals.size(); i++) {
    if (keyVals[i].first == "MemTotal") {
      // Convert from kB to MB and cache the result.
      int memtotal_mb;
      base::StringTokenizer t(keyVals[i].second, " ");
      if (t.GetNext() && base::StringToInt(t.token(), &memtotal_mb) &&
          t.GetNext() && t.token() == "kB") {
        memtotal_mb /= 1024;
        cache_.SetParsedData(
            TelemetryItemEnum::kMemTotalMebibytes,
            base::Optional<base::Value>(base::Value(memtotal_mb)));
      } else {
        LOG(ERROR) << "Incorrectly formatted MemTotal.";
      }
    } else if (keyVals[i].first == "MemFree") {
      // Convert from kB to MB and cache the result.
      int memfree_mb;
      base::StringTokenizer t(keyVals[i].second, " ");
      if (t.GetNext() && base::StringToInt(t.token(), &memfree_mb) &&
          t.GetNext() && t.token() == "kB") {
        memfree_mb /= 1024;
        cache_.SetParsedData(
            TelemetryItemEnum::kMemFreeMebibytes,
            base::Optional<base::Value>(base::Value(memfree_mb)));
      } else {
        LOG(ERROR) << "Incorrectly formatted MemFree.";
      }
    }
  }
}

void TelemConnection::ExtractDataFromProcUptime(
    const grpc_api::GetProcDataResponse& response) {
  NOTIMPLEMENTED();
}

void TelemConnection::ExtractDataFromProcLoadavg(
    const grpc_api::GetProcDataResponse& response) {
  // Make sure we received exactly one file in the response.
  if (response.file_dump_size() != 1) {
    LOG(ERROR) << "Bad GetProcDataResponse from request of type FILE_LOADAVG.";
    return;
  }

  // We expect the loadavg response to have the following format:
  // %f %f %f %d/%d %d. At the moment, we're only interested in
  // the %d/%d: it will parse into kNumRunnableEntities/kNumExistingEntities.
  // We'll first make sure the entire response matches the expected format,
  // then we'll extract the %d/%d.
  int running_entities;
  int existing_entities;
  if (!RE2::FullMatch(response.file_dump(0).contents(),
                      "\\d+\\.\\d+\\s\\d+\\.\\d+\\s\\d+"
                      "\\.\\d+\\s(\\d+)/(\\d+)\\s\\d+\\n",
                      &running_entities, &existing_entities)) {
    LOG(ERROR) << "Incorrectly formatted loadavg.";
    return;
  }
  cache_.SetParsedData(
      TelemetryItemEnum::kNumRunnableEntities,
      base::Optional<base::Value>(base::Value(running_entities)));
  cache_.SetParsedData(
      TelemetryItemEnum::kNumExistingEntities,
      base::Optional<base::Value>(base::Value(existing_entities)));
}

void TelemConnection::ExtractDataFromProcStat(
    const grpc_api::GetProcDataResponse& response) {
  // Make sure we received exactly one file in the response.
  if (response.file_dump_size() != 1) {
    LOG(ERROR) << "Bad GetProcDataResponse from request of type FILE_LOADAVG.";
    return;
  }

  // Grab the idle time for all CPUs combined, as well as the idle time
  // for each logical CPU. We'll store each of the times as a string in
  // case the system has been on for long enough to overflow an int with
  // its idle time.
  std::string idle_time_combined;
  std::stringstream response_sstream(response.file_dump(0).contents());
  std::string current_line;
  // The first line should be: cpu %d %d %d %d ..., where the last number
  // is the idle time.
  if (!std::getline(response_sstream, current_line) ||
      !RE2::PartialMatch(current_line, "cpu\\s+\\d+ \\d+ \\d+ (\\d+)",
                         &idle_time_combined)) {
    LOG(ERROR) << "Incorrectly formatted stat.";
    return;
  }

  // The next N lines should be: cpu%d %d %d %d %d ..., where N is the number
  // of logical CPUs.
  std::string idle_time_current_cpu;
  base::ListValue logical_cpu_idle_time;
  while (std::getline(response_sstream, current_line) &&
         RE2::PartialMatch(current_line, "cpu\\d+ \\d+ \\d+ \\d+ (\\d+)",
                           &idle_time_current_cpu))
    logical_cpu_idle_time.AppendString(idle_time_current_cpu);

  cache_.SetParsedData(
      TelemetryItemEnum::kTotalIdleTimeUserHz,
      base::Optional<base::Value>(base::Value(idle_time_combined)));
  cache_.SetParsedData(TelemetryItemEnum::kIdleTimePerCPUUserHz,
                       base::Optional<base::Value>(logical_cpu_idle_time));
}

void TelemConnection::ExtractDataFromProcAcpiButton(
    const grpc_api::GetProcDataResponse& response) {
  NOTIMPLEMENTED();
}

void TelemConnection::ExtractDataFromProcNetStat(
    const grpc_api::GetProcDataResponse& response) {
  NOTIMPLEMENTED();
}

void TelemConnection::ExtractDataFromProcNetDev(
    const grpc_api::GetProcDataResponse& response) {
  NOTIMPLEMENTED();
}

void TelemConnection::ExtractDataFromSysfsHwmon(
    const grpc_api::GetSysfsDataResponse& response) {
  NOTIMPLEMENTED();
}

void TelemConnection::ExtractDataFromSysfsThermal(
    const grpc_api::GetSysfsDataResponse& response) {
  NOTIMPLEMENTED();
}

void TelemConnection::ExtractDataFromSysfsDmiTables(
    const grpc_api::GetSysfsDataResponse& response) {
  NOTIMPLEMENTED();
}

}  // namespace diagnostics
