// 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 "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));
}

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

void MediaController::HandleMediaPlayPause() {
  // 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() {
  ui::RecordMediaHardwareKeyAction(
      ui::MediaHardwareKeyAction::kNextTrack);

  // 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() {
  ui::RecordMediaHardwareKeyAction(
      ui::MediaHardwareKeyAction::kPreviousTrack);

  // 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() {
  client_.FlushForTesting();
  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();
}

}  // namespace ash
