// Copyright (c) 2013 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 "power_manager/powerd/system/peripheral_battery_watcher.h"

#include <fcntl.h>

#include <cerrno>
#include <string>

#include <base/bind.h>
#include <base/file_util.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>

#include "power_manager/common/dbus_sender.h"
#include "power_manager/common/util.h"
#include "power_manager/proto_bindings/peripheral_battery_status.pb.h"

namespace power_manager {
namespace system {

namespace {

// Default path examined for peripheral battery directories.
const base::FilePath::CharType kDefaultPeripheralBatteryPath[] =
    FILE_PATH_LITERAL("/sys/class/power_supply/");

// Default interval for polling the device battery info.
const int kDefaultPollIntervalMs = 30000;

}  // namespace

PeripheralBatteryWatcher::PeripheralBatteryWatcher()
    : dbus_sender_(NULL),
      peripheral_battery_path_(kDefaultPeripheralBatteryPath),
      poll_interval_ms_(kDefaultPollIntervalMs) {
}

PeripheralBatteryWatcher::~PeripheralBatteryWatcher() {}

void PeripheralBatteryWatcher::Init(DBusSenderInterface* dbus_sender) {
  dbus_sender_ = dbus_sender;
  ReadBatteryStatuses();
}

void PeripheralBatteryWatcher::GetBatteryList(
    std::vector<base::FilePath>* battery_list) {
  battery_list->clear();
  base::FileEnumerator dir_enumerator(
      peripheral_battery_path_, false, base::FileEnumerator::DIRECTORIES);

  // Peripheral battery has a sysfs entry with name "scope" containing value
  // "Device".
  for (base::FilePath check_path = dir_enumerator.Next(); !check_path.empty();
       check_path = dir_enumerator.Next()) {
    base::FilePath scope_path = check_path.Append("scope");
    if (!base::PathExists(scope_path))
      continue;

    std::string buf;
    base::ReadFileToString(scope_path, &buf);
    base::TrimWhitespaceASCII(buf, base::TRIM_TRAILING, &buf);
    if (buf != "Device")
      continue;

    battery_list->push_back(check_path);
  }
}

void PeripheralBatteryWatcher::ReadBatteryStatuses() {
  battery_readers_.clear();

  std::vector<base::FilePath> new_battery_list;
  GetBatteryList(&new_battery_list);

  for (size_t i = 0; i < new_battery_list.size(); i++) {
    base::FilePath path = new_battery_list[i];

    // sysfs entry "capacity" has the current battery level.
    base::FilePath capacity_path = path.Append("capacity");
    if (!base::PathExists(capacity_path))
      continue;

    base::FilePath model_name_path = path.Append("model_name");
    if (!base::PathExists(model_name_path))
      continue;

    std::string model_name;
    base::ReadFileToString(model_name_path, &model_name);
    base::TrimWhitespaceASCII(model_name, base::TRIM_TRAILING, &model_name);

    AsyncFileReader* reader = new AsyncFileReader;
    battery_readers_.push_back(reader);

    if (reader->Init(capacity_path.value())) {
      reader->StartRead(
          base::Bind(&PeripheralBatteryWatcher::ReadCallback,
                     base::Unretained(this),
                     path.value(), model_name),
          base::Bind(&PeripheralBatteryWatcher::ErrorCallback,
                     base::Unretained(this),
                     path.value(), model_name));
    } else {
      LOG(ERROR) << "Can't read battery capacity " << capacity_path.value();
    }
  }
  poll_timer_.Start(FROM_HERE,
      base::TimeDelta::FromMilliseconds(poll_interval_ms_),
      this, &PeripheralBatteryWatcher::ReadBatteryStatuses);
}

void PeripheralBatteryWatcher::SendBatteryStatus(const std::string& path,
                                                 const std::string& model_name,
                                                 int level) {
  PeripheralBatteryStatus proto;
  proto.set_path(path);
  proto.set_name(model_name);
  if (level >= 0)
    proto.set_level(level);
  dbus_sender_->EmitSignalWithProtocolBuffer(kPeripheralBatteryStatusSignal,
                                             proto);
}

void PeripheralBatteryWatcher::ReadCallback(const std::string& path,
                                            const std::string& model_name,
                                            const std::string& data) {
  std::string trimmed_data;
  base::TrimWhitespaceASCII(data, base::TRIM_ALL, &trimmed_data);
  int level = -1;
  if (base::StringToInt(trimmed_data, &level)) {
    SendBatteryStatus(path, model_name, level);
  } else {
    LOG(ERROR) << "Invalid battery level reading : [" << data << "]"
               << " from " << path;
  }
}

void PeripheralBatteryWatcher::ErrorCallback(const std::string& path,
                                             const std::string& model_name) {
  SendBatteryStatus(path, model_name, -1);
}

}  // namespace system
}  // namespace power_manager
