// Copyright 2018 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 "services/media_session/audio_focus_manager.h"

#include <iterator>
#include <utility>

#include "base/containers/adapters.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/media_session/audio_focus_manager_metrics_helper.h"
#include "services/media_session/public/cpp/switches.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"

namespace media_session {

class AudioFocusManager::StackRow : public mojom::AudioFocusRequestClient {
 public:
  StackRow(AudioFocusManager* owner,
           mojom::AudioFocusRequestClientRequest request,
           mojom::MediaSessionPtr session,
           mojom::MediaSessionInfoPtr session_info,
           mojom::AudioFocusType audio_focus_type,
           RequestId id,
           const std::string& source_name,
           const base::UnguessableToken& group_id)
      : id_(id),
        source_name_(source_name),
        group_id_(group_id),
        metrics_helper_(source_name),
        session_(std::move(session)),
        session_info_(std::move(session_info)),
        audio_focus_type_(audio_focus_type),
        binding_(this, std::move(request)),
        owner_(owner) {
    // Listen for mojo errors.
    binding_.set_connection_error_handler(
        base::BindOnce(&AudioFocusManager::StackRow::OnConnectionError,
                       base::Unretained(this)));
    session_.set_connection_error_handler(
        base::BindOnce(&AudioFocusManager::StackRow::OnConnectionError,
                       base::Unretained(this)));

    metrics_helper_.OnRequestAudioFocus(
        AudioFocusManagerMetricsHelper::AudioFocusRequestSource::kInitial,
        audio_focus_type);
  }

  ~StackRow() override = default;

  // mojom::AudioFocusRequestClient.
  void RequestAudioFocus(mojom::MediaSessionInfoPtr session_info,
                         mojom::AudioFocusType type,
                         RequestAudioFocusCallback callback) override {
    SetSessionInfo(std::move(session_info));

    if (IsActive() && owner_->IsSessionOnTopOfAudioFocusStack(id(), type)) {
      // Early returning if |media_session| is already on top (has focus) and is
      // active.
      std::move(callback).Run();
      return;
    }

    // Remove this StackRow for the audio focus stack.
    std::unique_ptr<StackRow> row = owner_->RemoveFocusEntryIfPresent(id());
    DCHECK(row);

    owner_->RequestAudioFocusInternal(std::move(row), type,
                                      std::move(callback));

    metrics_helper_.OnRequestAudioFocus(
        AudioFocusManagerMetricsHelper::AudioFocusRequestSource::kUpdate,
        audio_focus_type_);
  }

  void AbandonAudioFocus() override {
    metrics_helper_.OnAbandonAudioFocus(
        AudioFocusManagerMetricsHelper::AudioFocusAbandonSource::kAPI);

    owner_->AbandonAudioFocusInternal(id_);
  }

  void MediaSessionInfoChanged(mojom::MediaSessionInfoPtr info) override {
    SetSessionInfo(std::move(info));
  }

  void GetRequestId(GetRequestIdCallback callback) override {
    std::move(callback).Run(id());
  }

  mojom::MediaSession* session() { return session_.get(); }
  const mojom::MediaSessionInfoPtr& info() const { return session_info_; }
  mojom::AudioFocusType audio_focus_type() const { return audio_focus_type_; }

  void SetAudioFocusType(mojom::AudioFocusType type) {
    audio_focus_type_ = type;
  }

  bool IsActive() const {
    return session_info_->state ==
           mojom::MediaSessionInfo::SessionState::kActive;
  }

  RequestId id() const { return id_; }

  const std::string& source_name() const { return source_name_; }

  const base::UnguessableToken& group_id() const { return group_id_; }

  mojom::AudioFocusRequestStatePtr ToAudioFocusRequestState() const {
    auto request = mojom::AudioFocusRequestState::New();
    request->session_info = session_info_.Clone();
    request->audio_focus_type = audio_focus_type_;
    request->request_id = id_;
    request->source_name = source_name_;
    return request;
  }

 private:
  void SetSessionInfo(mojom::MediaSessionInfoPtr session_info) {
    bool is_controllable_changed =
        session_info_->is_controllable != session_info->is_controllable;

    session_info_ = std::move(session_info);

    if (is_controllable_changed)
      owner_->MaybeUpdateActiveSession();
  }

  void OnConnectionError() {
    // Since we have multiple pathways that can call |OnConnectionError| we
    // should use the |encountered_error_| bit to make sure we abandon focus
    // just the first time.
    if (encountered_error_)
      return;
    encountered_error_ = true;

    metrics_helper_.OnAbandonAudioFocus(
        AudioFocusManagerMetricsHelper::AudioFocusAbandonSource::
            kConnectionError);

    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(&AudioFocusManager::AbandonAudioFocusInternal,
                                  base::Unretained(owner_), id_));
  }

  const RequestId id_;
  const std::string source_name_;
  const base::UnguessableToken group_id_;

  AudioFocusManagerMetricsHelper metrics_helper_;
  bool encountered_error_ = false;

  mojom::MediaSessionPtr session_;
  mojom::MediaSessionInfoPtr session_info_;
  mojom::AudioFocusType audio_focus_type_;
  mojo::Binding<mojom::AudioFocusRequestClient> binding_;

  // Weak pointer to the owning |AudioFocusManager| instance.
  AudioFocusManager* owner_;

  DISALLOW_COPY_AND_ASSIGN(StackRow);
};

void AudioFocusManager::RequestAudioFocus(
    mojom::AudioFocusRequestClientRequest request,
    mojom::MediaSessionPtr media_session,
    mojom::MediaSessionInfoPtr session_info,
    mojom::AudioFocusType type,
    RequestAudioFocusCallback callback) {
  RequestGroupedAudioFocus(
      std::move(request), std::move(media_session), std::move(session_info),
      type, base::UnguessableToken::Create(), std::move(callback));
}

void AudioFocusManager::RequestGroupedAudioFocus(
    mojom::AudioFocusRequestClientRequest request,
    mojom::MediaSessionPtr media_session,
    mojom::MediaSessionInfoPtr session_info,
    mojom::AudioFocusType type,
    const base::UnguessableToken& group_id,
    RequestGroupedAudioFocusCallback callback) {
  RequestAudioFocusInternal(
      std::make_unique<StackRow>(
          this, std::move(request), std::move(media_session),
          std::move(session_info), type, base::UnguessableToken::Create(),
          GetBindingSourceName(), group_id),
      type, std::move(callback));
}

void AudioFocusManager::GetFocusRequests(GetFocusRequestsCallback callback) {
  std::vector<mojom::AudioFocusRequestStatePtr> requests;

  for (const auto& row : audio_focus_stack_)
    requests.push_back(row->ToAudioFocusRequestState());

  std::move(callback).Run(std::move(requests));
}

void AudioFocusManager::GetDebugInfoForRequest(
    const RequestId& request_id,
    GetDebugInfoForRequestCallback callback) {
  for (auto& row : audio_focus_stack_) {
    if (row->id() != request_id)
      continue;

    row->session()->GetDebugInfo(base::BindOnce(
        [](const base::UnguessableToken& group_id,
           GetDebugInfoForRequestCallback callback,
           mojom::MediaSessionDebugInfoPtr info) {
          // Inject the |group_id| into the state string. This is because in
          // some cases the group id is automatically generated by the media
          // session service so the session is unaware of it.
          if (!info->state.empty())
            info->state += " ";
          info->state += "GroupId=" + group_id.ToString();

          std::move(callback).Run(std::move(info));
        },
        row->group_id(), std::move(callback)));
    return;
  }

  std::move(callback).Run(mojom::MediaSessionDebugInfo::New());
}

void AudioFocusManager::AbandonAudioFocusInternal(RequestId id) {
  if (audio_focus_stack_.empty())
    return;

  if (audio_focus_stack_.back()->id() != id) {
    RemoveFocusEntryIfPresent(id);
    MaybeUpdateActiveSession();
    return;
  }

  auto row = std::move(audio_focus_stack_.back());
  audio_focus_stack_.pop_back();

  if (audio_focus_stack_.empty()) {
    // Notify observers that we lost audio focus.
    observers_.ForAllPtrs([&row](mojom::AudioFocusObserver* observer) {
      observer->OnFocusLost(row->ToAudioFocusRequestState());
    });

    MaybeUpdateActiveSession();
    return;
  }

  if (IsAudioFocusEnforcementEnabled())
    EnforceAudioFocusAbandon(row->audio_focus_type());

  MaybeUpdateActiveSession();

  // Notify observers that we lost audio focus.
  observers_.ForAllPtrs([&row](mojom::AudioFocusObserver* observer) {
    observer->OnFocusLost(row->ToAudioFocusRequestState());
  });

  // Notify observers that the session on top gained focus.
  StackRow* new_session = audio_focus_stack_.back().get();
  observers_.ForAllPtrs([&new_session](mojom::AudioFocusObserver* observer) {
    observer->OnFocusGained(new_session->ToAudioFocusRequestState());
  });
}

void AudioFocusManager::AddObserver(mojom::AudioFocusObserverPtr observer) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  observers_.AddPtr(std::move(observer));
}

void AudioFocusManager::SetSourceName(const std::string& name) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  bindings_.dispatch_context()->source_name = name;
}

void AudioFocusManager::BindToInterface(
    mojom::AudioFocusManagerRequest request) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  bindings_.AddBinding(this, std::move(request),
                       std::make_unique<BindingContext>());
}

void AudioFocusManager::BindToDebugInterface(
    mojom::AudioFocusManagerDebugRequest request) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  debug_bindings_.AddBinding(this, std::move(request));
}

void AudioFocusManager::BindToActiveControllerInterface(
    mojom::MediaControllerRequest request) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  active_media_controller_.BindToInterface(std::move(request));
}

void AudioFocusManager::RequestAudioFocusInternal(
    std::unique_ptr<StackRow> row,
    mojom::AudioFocusType type,
    base::OnceCallback<void()> callback) {
  // If audio focus is enabled then we should enforce this request and make sure
  // the new active session is not ducking.
  if (IsAudioFocusEnforcementEnabled()) {
    EnforceAudioFocusRequest(type, row->group_id());
    row->session()->StopDucking();
  }

  row->SetAudioFocusType(type);
  audio_focus_stack_.push_back(std::move(row));

  MaybeUpdateActiveSession();

  // Notify observers that we were gained audio focus.
  mojom::AudioFocusRequestStatePtr session_state =
      audio_focus_stack_.back()->ToAudioFocusRequestState();
  observers_.ForAllPtrs([&session_state](mojom::AudioFocusObserver* observer) {
    observer->OnFocusGained(session_state.Clone());
  });

  // We always grant the audio focus request but this may not always be the case
  // in the future.
  std::move(callback).Run();
}

void AudioFocusManager::EnforceAudioFocusRequest(
    mojom::AudioFocusType type,
    const base::UnguessableToken& group_id) {
  DCHECK(IsAudioFocusEnforcementEnabled());

  for (auto& old_session : audio_focus_stack_) {
    // If the session has the force duck flag set then we should always duck it.
    if (old_session->info()->force_duck) {
      old_session->session()->StartDucking();
      continue;
    }

    switch (type) {
      case mojom::AudioFocusType::kGain:
      case mojom::AudioFocusType::kGainTransient:
        // If the session has the same group id as the new session then we
        // should not suspend that session.
        if (old_session->group_id() == group_id)
          break;

        old_session->session()->Suspend(
            mojom::MediaSession::SuspendType::kSystem);
        break;
      case mojom::AudioFocusType::kGainTransientMayDuck:
        old_session->session()->StartDucking();
        break;
    }
  }
}

void AudioFocusManager::EnforceAudioFocusAbandon(mojom::AudioFocusType type) {
  DCHECK(IsAudioFocusEnforcementEnabled());

  // Allow the top-most MediaSession having force duck to unduck even if
  // it is not active.
  for (auto iter = audio_focus_stack_.rbegin();
       iter != audio_focus_stack_.rend(); ++iter) {
    if (!(*iter)->info()->force_duck)
      continue;

    // TODO(beccahughes): Replace with std::rotate.
    auto duck_row = std::move(*iter);
    duck_row->session()->StopDucking();
    audio_focus_stack_.erase(std::next(iter).base());
    audio_focus_stack_.push_back(std::move(duck_row));
    return;
  }

  DCHECK(!audio_focus_stack_.empty());
  StackRow* top = audio_focus_stack_.back().get();

  switch (type) {
    case mojom::AudioFocusType::kGain:
      // Do nothing. The abandoned session suspended all the media sessions and
      // they should stay suspended to avoid surprising the user.
      break;
    case mojom::AudioFocusType::kGainTransient:
      // The abandoned session suspended all the media sessions but we should
      // start playing the top one again as the abandoned media was transient.
      // This will also apply to any sessions that have the same group_id as the
      // new top most session.
      for (auto& session : audio_focus_stack_) {
        if (session->group_id() != top->group_id())
          continue;

        session->session()->Resume(mojom::MediaSession::SuspendType::kSystem);
      }
      break;
    case mojom::AudioFocusType::kGainTransientMayDuck:
      // The abandoned session ducked all the media sessions so we should unduck
      // them. If they are not playing then they will not resume.
      for (auto& session : base::Reversed(audio_focus_stack_)) {
        session->session()->StopDucking();

        // If the new session is ducking then we should continue ducking all but
        // the new session.
        if (top->audio_focus_type() ==
            mojom::AudioFocusType::kGainTransientMayDuck)
          break;
      }
      break;
  }
}

void AudioFocusManager::MaybeUpdateActiveSession() {
  StackRow* active = nullptr;

  for (auto& row : base::Reversed(audio_focus_stack_)) {
    if (!row->info()->is_controllable)
      continue;

    active = row.get();
    break;
  }

  if (!active_media_controller_.SetMediaSession(active ? active->session()
                                                       : nullptr)) {
    return;
  }

  mojom::AudioFocusRequestStatePtr state =
      active ? active->ToAudioFocusRequestState() : nullptr;

  // Notify observers that the active media session changed.
  observers_.ForAllPtrs([&state](mojom::AudioFocusObserver* observer) {
    observer->OnActiveSessionChanged(state.Clone());
  });
}

AudioFocusManager::AudioFocusManager() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}

AudioFocusManager::~AudioFocusManager() = default;

std::unique_ptr<AudioFocusManager::StackRow>
AudioFocusManager::RemoveFocusEntryIfPresent(RequestId id) {
  std::unique_ptr<StackRow> row;

  for (auto iter = audio_focus_stack_.begin(); iter != audio_focus_stack_.end();
       ++iter) {
    if ((*iter)->id() == id) {
      row.swap((*iter));
      audio_focus_stack_.erase(iter);
      break;
    }
  }

  return row;
}

const std::string& AudioFocusManager::GetBindingSourceName() const {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return bindings_.dispatch_context()->source_name;
}

bool AudioFocusManager::IsSessionOnTopOfAudioFocusStack(
    RequestId id,
    mojom::AudioFocusType type) const {
  return !audio_focus_stack_.empty() && audio_focus_stack_.back()->id() == id &&
         audio_focus_stack_.back()->audio_focus_type() == type;
}

}  // namespace media_session
