// Copyright (c) 2012 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/power_save_blocker/power_save_blocker.h"

#include <windows.h>

#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"

namespace device {
namespace {

int g_blocker_count[2];

HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type,
                          const std::string& description) {
  if (type == PowerRequestExecutionRequired &&
      base::win::GetVersion() < base::win::VERSION_WIN8) {
    return INVALID_HANDLE_VALUE;
  }

  base::string16 wide_description = base::ASCIIToUTF16(description);
  REASON_CONTEXT context = {0};
  context.Version = POWER_REQUEST_CONTEXT_VERSION;
  context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
  context.Reason.SimpleReasonString =
      const_cast<wchar_t*>(wide_description.c_str());

  base::win::ScopedHandle handle(::PowerCreateRequest(&context));
  if (!handle.IsValid())
    return INVALID_HANDLE_VALUE;

  if (::PowerSetRequest(handle.Get(), type))
    return handle.Take();

  // Something went wrong.
  return INVALID_HANDLE_VALUE;
}

// Takes ownership of the |handle|.
void DeletePowerRequest(POWER_REQUEST_TYPE type, HANDLE handle) {
  base::win::ScopedHandle request_handle(handle);
  if (!request_handle.IsValid())
    return;

  if (type == PowerRequestExecutionRequired &&
      base::win::GetVersion() < base::win::VERSION_WIN8) {
    return;
  }

  BOOL success = ::PowerClearRequest(request_handle.Get(), type);
  DCHECK(success);
}

void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type, int delta) {
  g_blocker_count[type] += delta;
  DCHECK_GE(g_blocker_count[type], 0);

  if (g_blocker_count[type] > 1)
    return;

  DWORD this_flag = 0;
  if (type == PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension)
    this_flag |= ES_SYSTEM_REQUIRED;
  else
    this_flag |= ES_DISPLAY_REQUIRED;

  DCHECK(this_flag);

  static DWORD flags = ES_CONTINUOUS;
  if (!g_blocker_count[type])
    flags &= ~this_flag;
  else
    flags |= this_flag;

  SetThreadExecutionState(flags);
}

}  // namespace

class PowerSaveBlocker::Delegate
    : public base::RefCountedThreadSafe<PowerSaveBlocker::Delegate> {
 public:
  Delegate(PowerSaveBlockerType type,
           const std::string& description,
           scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
      : type_(type),
        description_(description),
        ui_task_runner_(ui_task_runner) {}

  // Does the actual work to apply or remove the desired power save block.
  void ApplyBlock();
  void RemoveBlock();

  // Returns the equivalent POWER_REQUEST_TYPE for this request.
  POWER_REQUEST_TYPE RequestType();

 private:
  friend class base::RefCountedThreadSafe<Delegate>;
  ~Delegate() {}

  PowerSaveBlockerType type_;
  const std::string description_;
  base::win::ScopedHandle handle_;
  scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;

  DISALLOW_COPY_AND_ASSIGN(Delegate);
};

void PowerSaveBlocker::Delegate::ApplyBlock() {
  DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  if (base::win::GetVersion() < base::win::VERSION_WIN7)
    return ApplySimpleBlock(type_, 1);

  handle_.Set(CreatePowerRequest(RequestType(), description_));
}

void PowerSaveBlocker::Delegate::RemoveBlock() {
  DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  if (base::win::GetVersion() < base::win::VERSION_WIN7)
    return ApplySimpleBlock(type_, -1);

  DeletePowerRequest(RequestType(), handle_.Take());
}

POWER_REQUEST_TYPE PowerSaveBlocker::Delegate::RequestType() {
  if (type_ == kPowerSaveBlockPreventDisplaySleep)
    return PowerRequestDisplayRequired;

  if (base::win::GetVersion() < base::win::VERSION_WIN8)
    return PowerRequestSystemRequired;

  return PowerRequestExecutionRequired;
}

PowerSaveBlocker::PowerSaveBlocker(
    PowerSaveBlockerType type,
    Reason reason,
    const std::string& description,
    scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner)
    : delegate_(new Delegate(type, description, ui_task_runner)),
      ui_task_runner_(ui_task_runner),
      blocking_task_runner_(blocking_task_runner) {
  ui_task_runner_->PostTask(FROM_HERE,
                            base::Bind(&Delegate::ApplyBlock, delegate_));
}

PowerSaveBlocker::~PowerSaveBlocker() {
  ui_task_runner_->PostTask(FROM_HERE,
                            base::Bind(&Delegate::RemoveBlock, delegate_));
}

}  // namespace device
