// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/idle/idle_manager_impl.h"

#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_descriptor_util.h"
#include "content/public/browser/render_frame_host.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"

namespace content {

namespace {

using blink::mojom::IdleManagerError;
using blink::mojom::IdleState;
using blink::mojom::PermissionStatus;

constexpr base::TimeDelta kUserInputThreshold =
    base::Milliseconds(blink::mojom::IdleManager::kUserInputThresholdMs);

}  // namespace

IdleManagerImpl::IdleManagerImpl(RenderFrameHost* render_frame_host)
    : render_frame_host_(render_frame_host) {
  monitors_.set_disconnect_handler(base::BindRepeating(
      &IdleManagerImpl::OnMonitorDisconnected, base::Unretained(this)));
}

IdleManagerImpl::~IdleManagerImpl() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}

void IdleManagerImpl::CreateService(
    mojo::PendingReceiver<blink::mojom::IdleManager> receiver) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  receivers_.Add(this, std::move(receiver));
}

void IdleManagerImpl::SetIdleOverride(bool is_user_active,
                                      bool is_screen_unlocked) {
  state_override_ = true;
  observer_.Reset();

  last_state_ = IdleState::New();
  if (!is_user_active)
    last_state_->idle_time = base::Seconds(0);
  last_state_->screen_locked = !is_screen_unlocked;

  for (const auto& monitor : monitors_) {
    monitor->Update(last_state_->Clone(), /*is_overridden_by_devtools=*/true);
  }
}

void IdleManagerImpl::ClearIdleOverride() {
  state_override_ = false;

  if (monitors_.empty()) {
    return;
  }

  observer_.Observe(ui::IdlePollingService::GetInstance());
  last_state_ = CheckIdleState();
  for (const auto& monitor : monitors_) {
    monitor->Update(last_state_->Clone(), /*is_overridden_by_devtools=*/false);
  }
}

void IdleManagerImpl::AddMonitor(
    mojo::PendingRemote<blink::mojom::IdleMonitor> monitor_remote,
    AddMonitorCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!HasPermission()) {
    std::move(callback).Run(IdleManagerError::kPermissionDisabled, nullptr);
    return;
  }

  if (monitors_.empty() && !state_override_) {
    observer_.Observe(ui::IdlePollingService::GetInstance());
    last_state_ = CheckIdleState();
  }

  monitors_.Add(std::move(monitor_remote));

  std::move(callback).Run(IdleManagerError::kSuccess, last_state_->Clone());
}

bool IdleManagerImpl::HasPermission() {
  PermissionController* permission_controller =
      render_frame_host_->GetBrowserContext()->GetPermissionController();
  DCHECK(permission_controller);
  PermissionStatus status =
      permission_controller->GetPermissionStatusForCurrentDocument(
          content::PermissionDescriptorUtil::
              CreatePermissionDescriptorForPermissionType(
                  blink::PermissionType::IDLE_DETECTION),
          render_frame_host_);
  return status == PermissionStatus::GRANTED;
}

void IdleManagerImpl::OnMonitorDisconnected(mojo::RemoteSetElementId id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (monitors_.empty()) {
    observer_.Reset();
  }
}

void IdleManagerImpl::OnIdleStateChange(
    const ui::IdlePollingService::State& state) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  last_state_ = CreateIdleState(state);
  for (const auto& monitor : monitors_) {
    monitor->Update(last_state_->Clone(), /*is_overridden_by_devtools=*/false);
  }
}

blink::mojom::IdleStatePtr IdleManagerImpl::CreateIdleState(
    const ui::IdlePollingService::State& state) {
  auto result = IdleState::New();
  if (state.idle_time >= kUserInputThreshold) {
    result->idle_time = state.idle_time - kUserInputThreshold;
  }
  result->screen_locked = state.locked;
  return result;
}

blink::mojom::IdleStatePtr IdleManagerImpl::CheckIdleState() {
  return CreateIdleState(ui::IdlePollingService::GetInstance()->GetIdleState());
}

}  // namespace content
