// Copyright (c) 2012 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 <iomanip>
#include <iostream>  // NOLINT(readability/streams)
#include <memory>
#include <string>

#include <base/at_exit.h>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/message_loop/message_pump_type.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/task/single_thread_task_executor.h>
#include <base/time/time.h>
#include <brillo/flag_helper.h>

#include "power_manager/common/battery_percentage_converter.h"
#include "power_manager/common/power_constants.h"
#include "power_manager/common/prefs.h"
#include "power_manager/powerd/system/dbus_wrapper_stub.h"
#include "power_manager/powerd/system/power_supply.h"
#include "power_manager/powerd/system/udev_stub.h"

// Displays info about battery and line power.

using base::TimeDelta;
using power_manager::system::PowerStatus;

namespace {

// Number of columns that should be used to display field names.
const int kFieldNameColumns = 27;

std::string BoolToString(bool value) {
  return value ? "yes" : "no";
}

template <class T>
std::string ValueToString(T value) {
  std::stringstream stream;
  stream << value;
  return stream.str();
}

class InfoDisplay {
 public:
  InfoDisplay() : name_indent_(0), value_indent_(0) {}

  void SetIndent(int name_indent, int value_indent) {
    name_indent_ = name_indent;
    value_indent_ = value_indent;
  }

  void PrintStringValue(const std::string& name_field,
                        const std::string& value_field) {
    std::cout << std::setw(name_indent_) << ""
              << std::setw(value_indent_ - name_indent_)
              << std::setiosflags(std::ios::left)
              << std::resetiosflags(std::ios::right) << name_field + ":"
              << value_field << std::endl;
  }

  template <class T>
  void PrintValue(const std::string& name_field, T value) {
    PrintStringValue(name_field, ValueToString(value));
  }

  void PrintString(const std::string& string) {
    std::cout << std::setw(name_indent_) << "" << string << std::endl;
  }

 private:
  int name_indent_;
  int value_indent_;

  DISALLOW_COPY_AND_ASSIGN(InfoDisplay);
};

}  // namespace

int main(int argc, char** argv) {
  brillo::FlagHelper::Init(
      argc, argv,
      "Print information obtained from /sys about the power supply.");
  base::AtExitManager at_exit_manager;
  base::SingleThreadTaskExecutor task_executor(base::MessagePumpType::IO);
  logging::SetMinLogLevel(logging::LOG_WARNING);

  power_manager::Prefs prefs;
  CHECK(prefs.Init(power_manager::Prefs::GetDefaultStore(),
                   power_manager::Prefs::GetDefaultSources()));

  power_manager::system::UdevStub udev;
  power_manager::system::DBusWrapperStub dbus_wrapper;
  base::FilePath path(power_manager::kPowerStatusPath);

  auto battery_percentage_converter =
      power_manager::BatteryPercentageConverter::CreateFromPrefs(&prefs);

  power_manager::system::PowerSupply power_supply;
  power_supply.Init(path, &prefs, &udev, &dbus_wrapper,
                    battery_percentage_converter.get());

  CHECK(power_supply.RefreshImmediately());
  const PowerStatus status = power_supply.GetPowerStatus();

  // NOTE, autotests (see autotest/files/client/cros/power_status.py) rely on
  // parsing this information below.
  // DO NOT CHANGE formatting without also fixing there as well.
  InfoDisplay display;
  display.SetIndent(0, 0);
  display.PrintString("Device: Line Power");
  display.SetIndent(2, kFieldNameColumns);
  display.PrintValue("path", status.line_power_path);
  display.PrintStringValue("online", BoolToString(status.line_power_on));
  display.PrintStringValue("type", status.line_power_type);
  switch (status.external_power) {
    case power_manager::PowerSupplyProperties_ExternalPower_AC:
      display.PrintStringValue("enum type", "AC");
      break;
    case power_manager::PowerSupplyProperties_ExternalPower_USB:
      display.PrintStringValue("enum type", "USB");
      break;
    case power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED:
      display.PrintStringValue("enum type", "Disconnected");
      break;
    default:
      display.PrintStringValue("enum type", "Unknown");
  }

  if (status.has_line_power_voltage)
    display.PrintValue("voltage (V)", status.line_power_voltage);
  else
    display.PrintValue("voltage (V)", "Not available");

  if (status.has_line_power_current)
    display.PrintValue("current (A)", status.line_power_current);
  else
    display.PrintValue("current (A)", "Not available");

  if (status.has_line_power_max_voltage)
    display.PrintValue("max voltage (V)", status.line_power_max_voltage);
  else
    display.PrintValue("max voltage (V)", "Not available");

  if (status.has_line_power_max_current)
    display.PrintValue("max current (A)", status.line_power_max_current);
  else
    display.PrintValue("max current (A)", "Not available");

  display.PrintStringValue("active source", status.external_power_source_id);
  std::vector<std::string> sources;
  for (const auto& port : status.ports) {
    if (port.role == PowerStatus::Port::Role::DEDICATED_SOURCE ||
        port.role == PowerStatus::Port::Role::DUAL_ROLE) {
      sources.push_back(base::StringPrintf(
          "%s%s [%s/%s]", port.id.c_str(), port.active_by_default ? "*" : "",
          port.manufacturer_id.c_str(), port.model_id.c_str()));
    }
  }
  display.PrintStringValue("available sources",
                           base::JoinString(sources, ", "));

  display.PrintStringValue("supports dual-role",
                           BoolToString(status.supports_dual_role_devices));

  if (status.battery_is_present) {
    display.SetIndent(0, 0);
    display.PrintString("Device: Battery");
    display.SetIndent(2, kFieldNameColumns);
    display.PrintValue("path", status.battery_path);
    display.PrintStringValue("vendor", status.battery_vendor);
    display.PrintStringValue("model name", status.battery_model_name);

    switch (status.battery_state) {
      case power_manager::PowerSupplyProperties_BatteryState_FULL:
        display.PrintStringValue("state", "Fully charged");
        break;
      case power_manager::PowerSupplyProperties_BatteryState_CHARGING:
        display.PrintStringValue("state", "Charging");
        break;
      case power_manager::PowerSupplyProperties_BatteryState_DISCHARGING:
        display.PrintStringValue("state", "Discharging");
        break;
      case power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT:
        display.PrintStringValue("state", "Not present");
        break;
      default:
        display.PrintStringValue("state", "Unknown");
    }

    display.PrintValue("voltage (V)", status.battery_voltage);
    display.PrintValue("energy (Wh)", status.battery_energy);
    display.PrintValue("energy rate (W)", status.battery_energy_rate);
    display.PrintValue("current (A)", status.battery_current);
    display.PrintValue("charge (Ah)", status.battery_charge);
    display.PrintValue("full charge (Ah)", status.battery_charge_full);
    display.PrintValue("full charge design (Ah)",
                       status.battery_charge_full_design);
    display.PrintValue("percentage", status.battery_percentage);
    display.PrintValue("display percentage", status.display_battery_percentage);
    display.PrintStringValue("technology", status.battery_technology);

    // Don't print the battery time estimates -- they're wildly inaccurate since
    // this program only takes a single reading of the current.
  }
  return 0;
}
