// Copyright 2016 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/media/media_controller.h"

#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "media/base/media_switches.h"
#include "services/media_session/public/mojom/constants.mojom.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "ui/base/accelerators/media_keys_util.h"

namespace ash {

namespace {

bool IsMediaSessionActionEligibleForKeyControl(
    media_session::mojom::MediaSessionAction action) {
  return action == media_session::mojom::MediaSessionAction::kPlay ||
         action == media_session::mojom::MediaSessionAction::kPause ||
         action == media_session::mojom::MediaSessionAction::kPreviousTrack ||
         action == media_session::mojom::MediaSessionAction::kNextTrack;
}

}  // namespace

MediaController::MediaController(service_manager::Connector* connector)
    : connector_(connector) {
  // If media session media key handling is enabled this will setup a connection
  // and bind an observer to the media session service.
  if (base::FeatureList::IsEnabled(media::kHardwareMediaKeyHandling))
    GetMediaSessionController();
}

MediaController::~MediaController() = default;

void MediaController::BindRequest(mojom::MediaControllerRequest request) {
  bindings_.AddBinding(this, std::move(request));
}

void MediaController::AddObserver(MediaCaptureObserver* observer) {
  observers_.AddObserver(observer);
}

void MediaController::RemoveObserver(MediaCaptureObserver* observer) {
  observers_.RemoveObserver(observer);
}

void MediaController::SetClient(mojom::MediaClientAssociatedPtrInfo client) {
  client_.Bind(std::move(client));

  // When |client_| is changed or encounters an error we should reset the
  // |force_media_client_key_handling_| bit.
  ResetForceMediaClientKeyHandling();
  client_.set_connection_error_handler(
      base::BindOnce(&MediaController::ResetForceMediaClientKeyHandling,
                     base::Unretained(this)));
}

void MediaController::SetForceMediaClientKeyHandling(bool enabled) {
  force_media_client_key_handling_ = enabled;
}

void MediaController::NotifyCaptureState(
    const base::flat_map<AccountId, mojom::MediaCaptureState>& capture_states) {
  for (auto& observer : observers_)
    observer.OnMediaCaptureChanged(capture_states);
}

void MediaController::HandleMediaPlayPause() {
  if (Shell::Get()->session_controller()->IsScreenLocked())
    return;

  // If the |client_| is force handling the keys then we should forward them.
  if (client_ && force_media_client_key_handling_) {
    ui::RecordMediaHardwareKeyAction(ui::MediaHardwareKeyAction::kPlayPause);
    client_->HandleMediaPlayPause();
    return;
  }

  // If media session media key handling is enabled. Toggle play pause using the
  // media session service.
  if (ShouldUseMediaSession()) {
    switch (media_session_info_->playback_state) {
      case media_session::mojom::MediaPlaybackState::kPaused:
        GetMediaSessionController()->Resume();
        ui::RecordMediaHardwareKeyAction(
            ui::MediaHardwareKeyAction::kPlay);
        break;
      case media_session::mojom::MediaPlaybackState::kPlaying:
        GetMediaSessionController()->Suspend();
        ui::RecordMediaHardwareKeyAction(
            ui::MediaHardwareKeyAction::kPause);
        break;
    }

    return;
  }

  // If media session does not handle the key then we don't know whether the
  // action will play or pause so we should record a generic "play/pause".
  ui::RecordMediaHardwareKeyAction(
      ui::MediaHardwareKeyAction::kPlayPause);

  if (client_)
    client_->HandleMediaPlayPause();
}

void MediaController::HandleMediaNextTrack() {
  if (Shell::Get()->session_controller()->IsScreenLocked())
    return;

  ui::RecordMediaHardwareKeyAction(
      ui::MediaHardwareKeyAction::kNextTrack);

  // If the |client_| is force handling the keys then we should forward them.
  if (client_ && force_media_client_key_handling_) {
    client_->HandleMediaNextTrack();
    return;
  }

  // If media session media key handling is enabled. Fire next track using the
  // media session service.
  if (ShouldUseMediaSession()) {
    GetMediaSessionController()->NextTrack();
    return;
  }

  if (client_)
    client_->HandleMediaNextTrack();
}

void MediaController::HandleMediaPrevTrack() {
  if (Shell::Get()->session_controller()->IsScreenLocked())
    return;

  ui::RecordMediaHardwareKeyAction(
      ui::MediaHardwareKeyAction::kPreviousTrack);

  // If the |client_| is force handling the keys then we should forward them.
  if (client_ && force_media_client_key_handling_) {
    client_->HandleMediaPrevTrack();
    return;
  }

  // If media session media key handling is enabled. Fire previous track using
  // the media session service.
  if (ShouldUseMediaSession()) {
    GetMediaSessionController()->PreviousTrack();
    return;
  }

  if (client_)
    client_->HandleMediaPrevTrack();
}

void MediaController::RequestCaptureState() {
  if (client_)
    client_->RequestCaptureState();
}

void MediaController::SuspendMediaSessions() {
  if (client_)
    client_->SuspendMediaSessions();
}

void MediaController::MediaSessionInfoChanged(
    media_session::mojom::MediaSessionInfoPtr session_info) {
  media_session_info_ = std::move(session_info);
}

void MediaController::MediaSessionActionsChanged(
    const std::vector<media_session::mojom::MediaSessionAction>& actions) {
  supported_media_session_action_ = false;

  for (auto action : actions) {
    if (IsMediaSessionActionEligibleForKeyControl(action)) {
      supported_media_session_action_ = true;
      return;
    }
  }
}

void MediaController::SetMediaSessionControllerForTest(
    media_session::mojom::MediaControllerPtr controller) {
  media_session_controller_ptr_ = std::move(controller);
  BindMediaControllerObserver();
}

void MediaController::FlushForTesting() {
  if (client_)
    client_.FlushForTesting();

  if (media_session_controller_ptr_)
    media_session_controller_ptr_.FlushForTesting();
}

media_session::mojom::MediaController*
MediaController::GetMediaSessionController() {
  // |connector_| can be null in tests.
  if (connector_ && !media_session_controller_ptr_.is_bound()) {
    media_session::mojom::MediaControllerManagerPtr controller_manager_ptr;
    connector_->BindInterface(media_session::mojom::kServiceName,
                              &controller_manager_ptr);
    controller_manager_ptr->CreateActiveMediaController(
        mojo::MakeRequest(&media_session_controller_ptr_));

    media_session_controller_ptr_.set_connection_error_handler(
        base::BindRepeating(&MediaController::OnMediaSessionControllerError,
                            base::Unretained(this)));

    BindMediaControllerObserver();
  }

  return media_session_controller_ptr_.get();
}

void MediaController::OnMediaSessionControllerError() {
  media_session_controller_ptr_.reset();
  supported_media_session_action_ = false;
}

void MediaController::BindMediaControllerObserver() {
  if (!media_session_controller_ptr_.is_bound())
    return;

  media_session::mojom::MediaControllerObserverPtr observer;
  media_controller_observer_binding_.Bind(mojo::MakeRequest(&observer));
  media_session_controller_ptr_->AddObserver(std::move(observer));
}

bool MediaController::ShouldUseMediaSession() {
  return base::FeatureList::IsEnabled(media::kHardwareMediaKeyHandling) &&
         GetMediaSessionController() && supported_media_session_action_ &&
         !media_session_info_.is_null();
}

void MediaController::ResetForceMediaClientKeyHandling() {
  force_media_client_key_handling_ = false;
}

}  // namespace ash
