// Copyright 2014 The Chromium 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 "device/battery/battery_status_manager.h"

#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/ps/IOPSKeys.h>
#include <IOKit/ps/IOPowerSources.h>

#include <memory>
#include <vector>

#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
#include "base/metrics/histogram.h"
#include "base/time/time.h"

namespace device {

namespace {

typedef BatteryStatusService::BatteryUpdateCallback BatteryCallback;

// Returns the value corresponding to |key| in the dictionary |description|.
// Returns |default_value| if the dictionary does not contain |key|, the
// corresponding value is NULL or it could not be converted to SInt64.
SInt64 GetValueAsSInt64(CFDictionaryRef description,
                        CFStringRef key,
                        SInt64 default_value) {
  CFNumberRef number =
      base::mac::GetValueFromDictionary<CFNumberRef>(description, key);
  SInt64 value;

  if (number && CFNumberGetValue(number, kCFNumberSInt64Type, &value))
    return value;

  return default_value;
}

bool GetValueAsBoolean(CFDictionaryRef description,
                       CFStringRef key,
                       bool default_value) {
  CFBooleanRef boolean =
      base::mac::GetValueFromDictionary<CFBooleanRef>(description, key);

  return boolean ? CFBooleanGetValue(boolean) : default_value;
}

bool CFStringsAreEqual(CFStringRef string1, CFStringRef string2) {
  if (!string1 || !string2)
    return false;
  return CFStringCompare(string1, string2, 0) == kCFCompareEqualTo;
}

void UpdateNumberBatteriesHistogram(int count) {
  UMA_HISTOGRAM_CUSTOM_COUNTS(
      "BatteryStatus.NumberBatteriesMac", count, 1, 5, 6);
}

void FetchBatteryStatus(CFDictionaryRef description, BatteryStatus* status) {
  CFStringRef current_state =
      base::mac::GetValueFromDictionary<CFStringRef>(description,
          CFSTR(kIOPSPowerSourceStateKey));

  bool on_battery_power =
      CFStringsAreEqual(current_state, CFSTR(kIOPSBatteryPowerValue));
  bool is_charging =
      GetValueAsBoolean(description, CFSTR(kIOPSIsChargingKey), true);
  bool is_charged =
      GetValueAsBoolean(description, CFSTR(kIOPSIsChargedKey), false);

  status->charging = !on_battery_power || is_charging;

  SInt64 current_capacity =
      GetValueAsSInt64(description, CFSTR(kIOPSCurrentCapacityKey), -1);
  SInt64 max_capacity =
      GetValueAsSInt64(description, CFSTR(kIOPSMaxCapacityKey), -1);

  // Set level if it is available and valid. Otherwise leave the default value,
  // which is 1.
  if (current_capacity != -1 && max_capacity != -1 &&
      current_capacity <= max_capacity && max_capacity != 0) {
    status->level = current_capacity / static_cast<double>(max_capacity);
  }

  if (is_charging) {
    SInt64 charging_time =
        GetValueAsSInt64(description, CFSTR(kIOPSTimeToFullChargeKey), -1);

    // Battery is charging: set the charging time if it's available, otherwise
    // set to +infinity.
    status->charging_time = charging_time != -1
        ? base::TimeDelta::FromMinutes(charging_time).InSeconds()
        : std::numeric_limits<double>::infinity();
  } else {
    // Battery is not charging.
    // Set chargingTime to +infinity if the battery is not charged. Otherwise
    // leave the default value, which is 0.
    if (!is_charged)
      status->charging_time = std::numeric_limits<double>::infinity();

    // Set dischargingTime if it's available and valid, i.e. when on battery
    // power. Otherwise leave the default value, which is +infinity.
    if (on_battery_power) {
      SInt64 discharging_time =
          GetValueAsSInt64(description, CFSTR(kIOPSTimeToEmptyKey), -1);
      if (discharging_time != -1) {
        status->discharging_time =
            base::TimeDelta::FromMinutes(discharging_time).InSeconds();
      }
    }
  }
}

std::vector<BatteryStatus> GetInternalBatteriesStates() {
  std::vector<BatteryStatus> internal_sources;

  base::ScopedCFTypeRef<CFTypeRef> info(IOPSCopyPowerSourcesInfo());
  base::ScopedCFTypeRef<CFArrayRef> power_sources_list(
      IOPSCopyPowerSourcesList(info));
  CFIndex count = CFArrayGetCount(power_sources_list);

  for (CFIndex i = 0; i < count; ++i) {
    CFDictionaryRef description = IOPSGetPowerSourceDescription(info,
        CFArrayGetValueAtIndex(power_sources_list, i));

    if (!description)
      continue;

    CFStringRef transport_type =
        base::mac::GetValueFromDictionary<CFStringRef>(description,
            CFSTR(kIOPSTransportTypeKey));

    bool internal_source =
        CFStringsAreEqual(transport_type, CFSTR(kIOPSInternalType));
    bool source_present =
        GetValueAsBoolean(description, CFSTR(kIOPSIsPresentKey), false);

    if (internal_source && source_present) {
      BatteryStatus status;
      FetchBatteryStatus(description, &status);
      internal_sources.push_back(status);
    }
  }

  return internal_sources;
}

void OnBatteryStatusChanged(const BatteryCallback& callback) {
  std::vector<BatteryStatus> batteries(GetInternalBatteriesStates());

  if (batteries.empty()) {
    callback.Run(BatteryStatus());
    return;
  }

  // TODO(timvolodine): implement the case when there are multiple internal
  // sources, e.g. when multiple batteries are present. Currently this will
  // fail a DCHECK.
  DCHECK(batteries.size() == 1);
  callback.Run(batteries.front());
}

class BatteryStatusObserver {
 public:
  explicit BatteryStatusObserver(const BatteryCallback& callback)
      : callback_(callback) {}

  ~BatteryStatusObserver() { DCHECK(!notifier_run_loop_source_); }

  void Start() {
    if (notifier_run_loop_source_)
      return;

    notifier_run_loop_source_.reset(
        IOPSNotificationCreateRunLoopSource(CallOnBatteryStatusChanged,
                                            static_cast<void*>(&callback_)));
    if (!notifier_run_loop_source_) {
      LOG(ERROR) << "Failed to create battery status notification run loop";
      // Make sure to execute to callback with the default values.
      callback_.Run(BatteryStatus());
      return;
    }

    CallOnBatteryStatusChanged(static_cast<void*>(&callback_));
    CFRunLoopAddSource(CFRunLoopGetCurrent(), notifier_run_loop_source_,
                       kCFRunLoopDefaultMode);
    UpdateNumberBatteriesHistogram(GetInternalBatteriesStates().size());
  }

  void Stop() {
    if (!notifier_run_loop_source_)
      return;

    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifier_run_loop_source_,
                          kCFRunLoopDefaultMode);
    notifier_run_loop_source_.reset();
  }

 private:
  static void CallOnBatteryStatusChanged(void* callback) {
    OnBatteryStatusChanged(*static_cast<BatteryCallback*>(callback));
  }

  BatteryCallback callback_;
  base::ScopedCFTypeRef<CFRunLoopSourceRef> notifier_run_loop_source_;

  DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver);
};

class BatteryStatusManagerMac : public BatteryStatusManager {
 public:
  explicit BatteryStatusManagerMac(const BatteryCallback& callback)
      : notifier_(new BatteryStatusObserver(callback)) {}

  ~BatteryStatusManagerMac() override { notifier_->Stop(); }

  // BatteryStatusManager:
  bool StartListeningBatteryChange() override {
    notifier_->Start();
    return true;
  }

  void StopListeningBatteryChange() override {
    notifier_->Stop();
  }

 private:
  std::unique_ptr<BatteryStatusObserver> notifier_;

  DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerMac);
};

} // end namespace

// static
std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create(
    const BatteryStatusService::BatteryUpdateCallback& callback) {
  return std::unique_ptr<BatteryStatusManager>(
      new BatteryStatusManagerMac(callback));
}

}  // namespace device
