// 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 "ash/dbus/display_service_provider.h"

#include <utility>

#include "ash/shell.h"
#include "ash/wm/screen_dimmer.h"
#include "base/bind.h"
#include "base/callback.h"
#include "dbus/message.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/user_activity/user_activity_detector.h"
#include "ui/display/manager/display_configurator.h"

namespace ash {
namespace {

void OnDisplayOwnershipChanged(
    const dbus::ExportedObject::ResponseSender& response_sender,
    std::unique_ptr<dbus::Response> response,
    bool status) {
  dbus::MessageWriter writer(response.get());
  writer.AppendBool(status);
  response_sender.Run(std::move(response));
}

}  // namespace

class DisplayServiceProvider::Impl {
 public:
  Impl() = default;
  ~Impl() = default;

  void SetDimming(bool dimmed);
  void TakeDisplayOwnership(base::OnceCallback<void(bool)> callback);
  void ReleaseDisplayOwnership(base::OnceCallback<void(bool)> callback);

 private:
  std::unique_ptr<ScreenDimmer> screen_dimmer_;

  DISALLOW_COPY_AND_ASSIGN(Impl);
};

void DisplayServiceProvider::Impl::SetDimming(bool dimmed) {
  if (!screen_dimmer_) {
    screen_dimmer_ =
        std::make_unique<ScreenDimmer>(ScreenDimmer::Container::ROOT);
  }
  screen_dimmer_->SetDimming(dimmed);
}

void DisplayServiceProvider::Impl::TakeDisplayOwnership(
    base::OnceCallback<void(bool)> callback) {
  if (!Shell::Get()->display_configurator()) {
    LOG(ERROR) << "Display Controller not connected";
    std::move(callback).Run(false);
    return;
  }
  Shell::Get()->display_configurator()->TakeControl(std::move(callback));
}

void DisplayServiceProvider::Impl::ReleaseDisplayOwnership(
    base::OnceCallback<void(bool)> callback) {
  if (!Shell::Get()->display_configurator()) {
    LOG(ERROR) << "Display Controller not connected";
    std::move(callback).Run(false);
    return;
  }
  Shell::Get()->display_configurator()->RelinquishControl(std::move(callback));
}

DisplayServiceProvider::DisplayServiceProvider()
    : impl_(std::make_unique<Impl>()), weak_ptr_factory_(this) {}

DisplayServiceProvider::~DisplayServiceProvider() = default;

void DisplayServiceProvider::Start(
    scoped_refptr<dbus::ExportedObject> exported_object) {
  exported_object->ExportMethod(
      chromeos::kDisplayServiceInterface,
      chromeos::kDisplayServiceSetPowerMethod,
      base::BindRepeating(&DisplayServiceProvider::SetDisplayPower,
                          weak_ptr_factory_.GetWeakPtr()),
      base::BindRepeating(&DisplayServiceProvider::OnExported,
                          weak_ptr_factory_.GetWeakPtr()));

  exported_object->ExportMethod(
      chromeos::kDisplayServiceInterface,
      chromeos::kDisplayServiceSetSoftwareDimmingMethod,
      base::BindRepeating(&DisplayServiceProvider::SetDisplaySoftwareDimming,
                          weak_ptr_factory_.GetWeakPtr()),
      base::BindRepeating(&DisplayServiceProvider::OnExported,
                          weak_ptr_factory_.GetWeakPtr()));

  exported_object->ExportMethod(
      chromeos::kDisplayServiceInterface,
      chromeos::kDisplayServiceTakeOwnershipMethod,
      base::BindRepeating(&DisplayServiceProvider::TakeDisplayOwnership,
                          weak_ptr_factory_.GetWeakPtr()),
      base::BindRepeating(&DisplayServiceProvider::OnExported,
                          weak_ptr_factory_.GetWeakPtr()));

  exported_object->ExportMethod(
      chromeos::kDisplayServiceInterface,
      chromeos::kDisplayServiceReleaseOwnershipMethod,
      base::BindRepeating(&DisplayServiceProvider::ReleaseDisplayOwnership,
                          weak_ptr_factory_.GetWeakPtr()),
      base::BindRepeating(&DisplayServiceProvider::OnExported,
                          weak_ptr_factory_.GetWeakPtr()));
}

void DisplayServiceProvider::SetDisplayPower(
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  dbus::MessageReader reader(method_call);
  int int_state = 0;
  if (!reader.PopInt32(&int_state)) {
    LOG(ERROR) << "Unable to parse request: "
               << chromeos::kDisplayServiceSetPowerMethod;
    response_sender.Run(dbus::Response::FromMethodCall(method_call));
    return;
  }

  // Turning displays off when the device becomes idle or on just before
  // we suspend may trigger a mouse move, which would then be incorrectly
  // reported as user activity.  Let the UserActivityDetector
  // know so that it can ignore such events.
  ui::UserActivityDetector::Get()->OnDisplayPowerChanging();

  Shell::Get()->display_configurator()->SetDisplayPower(
      static_cast<chromeos::DisplayPowerState>(int_state),
      display::DisplayConfigurator::kSetDisplayPowerNoFlags,
      base::BindRepeating(
          [](dbus::MethodCall* method_call,
             dbus::ExportedObject::ResponseSender response_sender,
             bool /*status*/) {
            response_sender.Run(dbus::Response::FromMethodCall(method_call));
          },
          method_call, response_sender));
}

void DisplayServiceProvider::SetDisplaySoftwareDimming(
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  dbus::MessageReader reader(method_call);
  bool dimmed = false;
  if (reader.PopBool(&dimmed)) {
    impl_->SetDimming(dimmed);
  } else {
    LOG(ERROR) << "Unable to parse request: "
               << chromeos::kDisplayServiceSetSoftwareDimmingMethod;
  }
  response_sender.Run(dbus::Response::FromMethodCall(method_call));
}

void DisplayServiceProvider::TakeDisplayOwnership(
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  impl_->TakeDisplayOwnership(base::BindOnce(
      &OnDisplayOwnershipChanged, response_sender,
      base::Passed(dbus::Response::FromMethodCall(method_call))));
}

void DisplayServiceProvider::ReleaseDisplayOwnership(
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  impl_->ReleaseDisplayOwnership(base::BindOnce(
      &OnDisplayOwnershipChanged, response_sender,
      base::Passed(dbus::Response::FromMethodCall(method_call))));
}

void DisplayServiceProvider::OnExported(const std::string& interface_name,
                                        const std::string& method_name,
                                        bool success) {
  if (!success)
    LOG(ERROR) << "Failed to export " << interface_name << "." << method_name;
}

}  // namespace ash
