// Copyright (c) 2013 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 "chromeos/dbus/fake_power_manager_client.h"

#include <set>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/posix/unix_domain_socket.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"

namespace chromeos {

namespace {
// Minimum power for a USB power source to be classified as AC.
constexpr double kUsbMinAcWatts = 24;

// Callback fired when timer started through |StartArcTimer| expires. In
// non-test environments this does a potentially blocking call on the UI
// thread. However, the clients that exercise this code path don't run in
// non-test environments.
void ArcTimerExpirationCallback(int expiration_fd) {
  // The instance expects 8 bytes on the read end similar to what happens on
  // a timerfd expiration. The timerfd API expects this to be the number of
  // expirations, however, more than one expiration isn't tracked currently.
  const uint64_t timer_data = 1;
  if (!base::UnixDomainSocket::SendMsg(
          expiration_fd, &timer_data, sizeof(timer_data), std::vector<int>())) {
    PLOG(ERROR) << "Failed to indicate timer expiration to the instance";
  }
}

power_manager::BacklightBrightnessChange_Cause RequestCauseToChangeCause(
    power_manager::SetBacklightBrightnessRequest_Cause cause) {
  switch (cause) {
    case power_manager::SetBacklightBrightnessRequest_Cause_USER_REQUEST:
      return power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
    case power_manager::SetBacklightBrightnessRequest_Cause_MODEL:
      return power_manager::BacklightBrightnessChange_Cause_MODEL;
  }
  NOTREACHED() << "Unhandled brightness request cause " << cause;
  return power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
}

}  // namespace

FakePowerManagerClient::FakePowerManagerClient()
    : props_(power_manager::PowerSupplyProperties()), weak_ptr_factory_(this) {}

FakePowerManagerClient::~FakePowerManagerClient() = default;

void FakePowerManagerClient::Init(dbus::Bus* bus) {
  props_->set_battery_percent(50);
  props_->set_is_calculating_battery_time(false);
  props_->set_battery_state(
      power_manager::PowerSupplyProperties_BatteryState_DISCHARGING);
  props_->set_external_power(
      power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
  props_->set_battery_time_to_full_sec(0);
  props_->set_battery_time_to_empty_sec(18000);
}

void FakePowerManagerClient::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void FakePowerManagerClient::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

bool FakePowerManagerClient::HasObserver(const Observer* observer) const {
  return observers_.HasObserver(observer);
}

void FakePowerManagerClient::WaitForServiceToBeAvailable(
    WaitForServiceToBeAvailableCallback callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), true));
}

void FakePowerManagerClient::SetRenderProcessManagerDelegate(
    base::WeakPtr<RenderProcessManagerDelegate> delegate) {
  render_process_manager_delegate_ = delegate;
}

void FakePowerManagerClient::DecreaseScreenBrightness(bool allow_off) {}

void FakePowerManagerClient::IncreaseScreenBrightness() {}

void FakePowerManagerClient::SetScreenBrightness(
    const power_manager::SetBacklightBrightnessRequest& request) {
  screen_brightness_percent_ = request.percent();
  requested_screen_brightness_percent_ = request.percent();

  power_manager::BacklightBrightnessChange change;
  change.set_percent(request.percent());
  change.set_cause(RequestCauseToChangeCause(request.cause()));
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(&FakePowerManagerClient::SendScreenBrightnessChanged,
                     weak_ptr_factory_.GetWeakPtr(), change));
}

void FakePowerManagerClient::GetScreenBrightnessPercent(
    DBusMethodCallback<double> callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(std::move(callback), screen_brightness_percent_));
}

void FakePowerManagerClient::DecreaseKeyboardBrightness() {}

void FakePowerManagerClient::IncreaseKeyboardBrightness() {}

void FakePowerManagerClient::GetKeyboardBrightnessPercent(
    DBusMethodCallback<double> callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(std::move(callback), keyboard_brightness_percent_));
}

const base::Optional<power_manager::PowerSupplyProperties>&
FakePowerManagerClient::GetLastStatus() {
  return props_;
}

void FakePowerManagerClient::RequestStatusUpdate() {
  // RequestStatusUpdate() calls and notifies the observers
  // asynchronously on a real device. On the fake implementation, we call
  // observers in a posted task to emulate the same behavior.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(&FakePowerManagerClient::NotifyObservers,
                                weak_ptr_factory_.GetWeakPtr()));
}

void FakePowerManagerClient::RequestSuspend() {}

void FakePowerManagerClient::RequestRestart(
    power_manager::RequestRestartReason reason,
    const std::string& description) {
  ++num_request_restart_calls_;
}

void FakePowerManagerClient::RequestShutdown(
    power_manager::RequestShutdownReason reason,
    const std::string& description) {
  ++num_request_shutdown_calls_;
}

void FakePowerManagerClient::NotifyUserActivity(
    power_manager::UserActivityType type) {
  if (user_activity_callback_)
    user_activity_callback_.Run();
}

void FakePowerManagerClient::NotifyVideoActivity(bool is_fullscreen) {
  video_activity_reports_.push_back(is_fullscreen);
}

void FakePowerManagerClient::SetPolicy(
    const power_manager::PowerManagementPolicy& policy) {
  policy_ = policy;
  ++num_set_policy_calls_;

  if (power_policy_quit_closure_)
    std::move(power_policy_quit_closure_).Run();
}

void FakePowerManagerClient::SetIsProjecting(bool is_projecting) {
  ++num_set_is_projecting_calls_;
  is_projecting_ = is_projecting;
}

void FakePowerManagerClient::SetPowerSource(const std::string& id) {
  props_->set_external_power_source_id(id);
  props_->set_external_power(
      power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED);
  for (const auto& source : props_->available_external_power_source()) {
    if (source.id() == id) {
      props_->set_external_power(
          !source.active_by_default() || source.max_power() < kUsbMinAcWatts
              ? power_manager::PowerSupplyProperties_ExternalPower_USB
              : power_manager::PowerSupplyProperties_ExternalPower_AC);
      break;
    }
  }

  NotifyObservers();
}

void FakePowerManagerClient::SetBacklightsForcedOff(bool forced_off) {
  backlights_forced_off_ = forced_off;
  ++num_set_backlights_forced_off_calls_;

  power_manager::BacklightBrightnessChange change;
  change.set_percent(forced_off ? 0 : requested_screen_brightness_percent_);
  change.set_cause(
      forced_off ? power_manager::BacklightBrightnessChange_Cause_FORCED_OFF
                 : power_manager::
                       BacklightBrightnessChange_Cause_NO_LONGER_FORCED_OFF);

  if (enqueue_brightness_changes_on_backlights_forced_off_) {
    pending_screen_brightness_changes_.push(change);
  } else {
    screen_brightness_percent_ = change.percent();
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(&FakePowerManagerClient::SendScreenBrightnessChanged,
                       weak_ptr_factory_.GetWeakPtr(), change));
  }
}

void FakePowerManagerClient::GetBacklightsForcedOff(
    DBusMethodCallback<bool> callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), backlights_forced_off_));
}

void FakePowerManagerClient::GetSwitchStates(
    DBusMethodCallback<SwitchStates> callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback),
                                SwitchStates{lid_state_, tablet_mode_}));
}

void FakePowerManagerClient::GetInactivityDelays(
    DBusMethodCallback<power_manager::PowerManagementPolicy::Delays> callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), inactivity_delays_));
}

base::Closure FakePowerManagerClient::GetSuspendReadinessCallback(
    const base::Location& from_where) {
  ++num_pending_suspend_readiness_callbacks_;
  return base::Bind(&FakePowerManagerClient::HandleSuspendReadiness,
                    base::Unretained(this));
}

int FakePowerManagerClient::GetNumPendingSuspendReadinessCallbacks() {
  return num_pending_suspend_readiness_callbacks_;
}

void FakePowerManagerClient::CreateArcTimers(
    const std::string& tag,
    std::vector<std::pair<clockid_t, base::ScopedFD>> arc_timer_requests,
    DBusMethodCallback<std::vector<TimerId>> callback) {
  // Check if client tag already exists. Return error iff it does.
  if (base::ContainsKey(client_timer_ids_, tag)) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), std::vector<TimerId>()));
    return;
  }

  // First, ensure that there are no duplicate clocks in the arguments. Return
  // error if there are.
  std::set<clockid_t> seen_clock_ids;
  for (const auto& request : arc_timer_requests) {
    if (!seen_clock_ids.emplace(request.first).second) {
      base::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE,
          base::BindOnce(std::move(callback), std::vector<TimerId>()));
      return;
    }
  }

  // For each request, create a timer id and map the timer id to the expiration
  // fd that will be written to on timer expiry.
  std::vector<TimerId> timer_ids;
  for (auto& request : arc_timer_requests) {
    // Insert is safe as |next_timer_id_| is always incremented.
    timer_expiration_fds_[next_timer_id_] = std::move(request.second);
    timer_ids.emplace_back(next_timer_id_);
    next_timer_id_++;
  }

  // Associate timer ids with the client's tag. The insert is safe because
  // duplicate client tags are checked for earlier.
  client_timer_ids_[tag] = timer_ids;
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), std::move(timer_ids)));
}

void FakePowerManagerClient::StartArcTimer(
    TimerId timer_id,
    base::TimeTicks absolute_expiration_time,
    VoidDBusMethodCallback callback) {
  auto it = timer_expiration_fds_.find(timer_id);
  if (it == timer_expiration_fds_.end()) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), false));
    return;
  }

  // Post task to run |callback| and indicate success to the caller.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), true));

  // Post task to write to |clock_id|'s expiration fd. This will simulate the
  // timer expiring to the caller. Ignore delaying by
  // |absolute_expiration_time| for test purposes.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(&ArcTimerExpirationCallback, it->second.get()));
}

void FakePowerManagerClient::DeleteArcTimers(const std::string& tag,
                                             VoidDBusMethodCallback callback) {
  // Retrieve all timer ids associated with |tag|. Delete all timers associated
  // with these timer ids. Return true even if |tag| isn't found.
  auto it = client_timer_ids_.find(tag);
  if (it == client_timer_ids_.end()) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), true));
    return;
  }

  for (auto timer_id : it->second)
    timer_expiration_fds_.erase(timer_id);

  client_timer_ids_.erase(it);
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), true));
}

void FakePowerManagerClient::DeferScreenDim() {
  num_defer_screen_dim_calls_++;
}

bool FakePowerManagerClient::PopVideoActivityReport() {
  CHECK(!video_activity_reports_.empty());
  bool fullscreen = video_activity_reports_.front();
  video_activity_reports_.pop_front();
  return fullscreen;
}

void FakePowerManagerClient::SendSuspendImminent(
    power_manager::SuspendImminent::Reason reason) {
  for (auto& observer : observers_)
    observer.SuspendImminent(reason);
  if (render_process_manager_delegate_)
    render_process_manager_delegate_->SuspendImminent();
}

void FakePowerManagerClient::SendSuspendDone(base::TimeDelta sleep_duration) {
  if (render_process_manager_delegate_)
    render_process_manager_delegate_->SuspendDone();

  for (auto& observer : observers_)
    observer.SuspendDone(sleep_duration);
}

void FakePowerManagerClient::SendDarkSuspendImminent() {
  for (auto& observer : observers_)
    observer.DarkSuspendImminent();
}

void FakePowerManagerClient::SendScreenBrightnessChanged(
    const power_manager::BacklightBrightnessChange& change) {
  for (auto& observer : observers_)
    observer.ScreenBrightnessChanged(change);
}

void FakePowerManagerClient::SendKeyboardBrightnessChanged(
    const power_manager::BacklightBrightnessChange& change) {
  for (auto& observer : observers_)
    observer.KeyboardBrightnessChanged(change);
}

void FakePowerManagerClient::SendScreenIdleStateChanged(
    const power_manager::ScreenIdleState& proto) {
  for (auto& observer : observers_)
    observer.ScreenIdleStateChanged(proto);
}

void FakePowerManagerClient::SendPowerButtonEvent(
    bool down,
    const base::TimeTicks& timestamp) {
  for (auto& observer : observers_)
    observer.PowerButtonEventReceived(down, timestamp);
}

void FakePowerManagerClient::SendScreenDimImminent() {
  for (auto& observer : observers_)
    observer.ScreenDimImminent();
}

void FakePowerManagerClient::SetLidState(LidState state,
                                         const base::TimeTicks& timestamp) {
  lid_state_ = state;
  for (auto& observer : observers_)
    observer.LidEventReceived(state, timestamp);
}

void FakePowerManagerClient::SetTabletMode(TabletMode mode,
                                           const base::TimeTicks& timestamp) {
  tablet_mode_ = mode;
  for (auto& observer : observers_)
    observer.TabletModeEventReceived(mode, timestamp);
}

void FakePowerManagerClient::SetInactivityDelays(
    const power_manager::PowerManagementPolicy::Delays& delays) {
  inactivity_delays_ = delays;
  for (auto& observer : observers_)
    observer.InactivityDelaysChanged(delays);
}

void FakePowerManagerClient::UpdatePowerProperties(
    const power_manager::PowerSupplyProperties& power_props) {
  props_ = power_props;
  NotifyObservers();
}

void FakePowerManagerClient::NotifyObservers() {
  for (auto& observer : observers_)
    observer.PowerChanged(*props_);
}

void FakePowerManagerClient::HandleSuspendReadiness() {
  CHECK_GT(num_pending_suspend_readiness_callbacks_, 0);

  --num_pending_suspend_readiness_callbacks_;
}

void FakePowerManagerClient::SetPowerPolicyQuitClosure(
    base::OnceClosure quit_closure) {
  power_policy_quit_closure_ = std::move(quit_closure);
}

bool FakePowerManagerClient::ApplyPendingScreenBrightnessChange() {
  if (pending_screen_brightness_changes_.empty())
    return false;

  power_manager::BacklightBrightnessChange change =
      pending_screen_brightness_changes_.front();
  pending_screen_brightness_changes_.pop();

  screen_brightness_percent_ = change.percent();
  SendScreenBrightnessChanged(change);
  return true;
}

}  // namespace chromeos
