// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/media_session/media_session_client.h"

#include <algorithm>
#include <cmath>
#include <memory>
#include <string>

#include "base/logging.h"
#include "cobalt/script/sequence.h"
#include "starboard/time.h"

using MediaImageSequence = ::cobalt::script::Sequence<MediaImage>;

namespace cobalt {
namespace media_session {

namespace {

// Delay to re-query position state after an action has been invoked.
const base::TimeDelta kUpdateDelay = base::TimeDelta::FromMilliseconds(250);

// Delay to check if the media session state is not active.
const base::TimeDelta kMaybeFreezeDelay = base::TimeDelta::FromMilliseconds(1500);

// Guess the media position state for the media session.
void GuessMediaPositionState(MediaSessionState* session_state,
                             const media::WebMediaPlayer** guess_player,
                             const media::WebMediaPlayer* current_player) {
  // Assume the player with the biggest video size is the one controlled by the
  // media session. This isn't perfect, so it's best that the web app set the
  // media position state explicitly.
  if (*guess_player == nullptr ||
      (*guess_player)->GetNaturalSize().GetArea() <
          current_player->GetNaturalSize().GetArea()) {
    *guess_player = current_player;

    MediaPositionState position_state;
    float duration = (*guess_player)->GetDuration();
    if (std::isfinite(duration)) {
      position_state.set_duration(duration);
    } else if (std::isinf(duration)) {
      position_state.set_duration(kSbTimeMax);
    } else {
      position_state.set_duration(0.0);
    }
    position_state.set_playback_rate((*guess_player)->GetPlaybackRate());
    position_state.set_position((*guess_player)->GetCurrentTime());

    *session_state = MediaSessionState(session_state->metadata(),
                                       SbTimeGetMonotonicNow(), position_state,
                                       session_state->actual_playback_state(),
                                       session_state->available_actions());
  }
}
}  // namespace

MediaSessionClient::MediaSessionClient(MediaSession* media_session)
    : media_session_(media_session),
      platform_playback_state_(kMediaSessionPlaybackStateNone),
      sequence_number_(0) {
  extension_ = static_cast<const CobaltExtensionMediaSessionApi*>(
      SbSystemGetExtension(kCobaltExtensionMediaSessionName));
  if (extension_) {
    if (strcmp(extension_->name,
                           kCobaltExtensionMediaSessionName) != 0 ||
        extension_->version < 1) {
      LOG(WARNING) << "Wrong MediaSession extension supplied";
      extension_ = nullptr;
    } else if (extension_->RegisterMediaSessionCallbacks != nullptr) {
      extension_->RegisterMediaSessionCallbacks(
          this, &InvokeActionCallback, &UpdatePlatformPlaybackStateCallback);
    }
  }
}

MediaSessionClient::~MediaSessionClient() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // Destroy the platform's MediaSessionClient, if it exists.
  if (extension_ != NULL &&
      extension_->DestroyMediaSessionClientCallback != NULL) {
    extension_->DestroyMediaSessionClientCallback();
  }
}

void MediaSessionClient::SetMediaPlayerFactory(
    const media::WebMediaPlayerFactory* factory) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  media_player_factory_ = factory;
}

MediaSessionPlaybackState MediaSessionClient::ComputeActualPlaybackState()
    const {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // Per https://wicg.github.io/mediasession/#guessed-playback-state
  // - If the "declared playback state" is "playing", then return "playing"
  // - Otherwise, return the guessed playback state
  MediaSessionPlaybackState declared_state;
  declared_state = media_session_->playback_state();
  if (declared_state == kMediaSessionPlaybackStatePlaying) {
    return kMediaSessionPlaybackStatePlaying;
  }

  if (platform_playback_state_ == kMediaSessionPlaybackStatePlaying) {
    // "...guessed playback state is playing if any of them is
    // potentially playing and not muted..."
    return kMediaSessionPlaybackStatePlaying;
  }

  // It's not super clear what to do when the declared state or the
  // active media session state is kPaused or kNone

  if (declared_state == kMediaSessionPlaybackStatePaused) {
    return kMediaSessionPlaybackStatePaused;
  }

  return kMediaSessionPlaybackStateNone;
}

MediaSessionState::AvailableActionsSet
MediaSessionClient::ComputeAvailableActions() const {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // "Available actions" are determined based on active media session
  // and supported media session actions.
  // Note for cobalt, there's only one window/tab so there's only one
  // "active media session"
  // https://wicg.github.io/mediasession/#actions-model
  //
  // Note that this is essentially the "media session actions update algorithm"
  // inverted.
  MediaSessionState::AvailableActionsSet result =
      MediaSessionState::AvailableActionsSet();

  for (MediaSession::ActionMap::iterator it =
           media_session_->action_map_.begin();
       it != media_session_->action_map_.end(); ++it) {
    result[it->first] = true;
  }

  switch (ComputeActualPlaybackState()) {
    case kMediaSessionPlaybackStatePlaying:
      // "If the active media session’s actual playback state is playing, remove
      // play from available actions."
      result[kMediaSessionActionPlay] = false;
      break;
    case kMediaSessionPlaybackStateNone:
      // Not defined in the spec: disable Seekbackward, Seekforward, SeekTo, &
      // Stop when no media is playing.
      result[kMediaSessionActionSeekbackward] = false;
      result[kMediaSessionActionSeekforward] = false;
      result[kMediaSessionActionSeekto] = false;
      result[kMediaSessionActionStop] = false;
    // Fall-through intended (None case falls through to Paused case).
    case kMediaSessionPlaybackStatePaused:
      // "Otherwise, remove pause from available actions."
      result[kMediaSessionActionPause] = false;
      break;
  }

  return result;
}

void MediaSessionClient::PostDelayedTaskForMaybeFreezeCallback() {
  media_session_->task_runner_->PostDelayedTask(
      FROM_HERE, base::Bind(&MediaSessionClient::RunMaybeFreezeCallback,
                            base::Unretained(this), ++sequence_number_),
                            kMaybeFreezeDelay);
}

void MediaSessionClient::UpdatePlatformPlaybackState(
    CobaltExtensionMediaSessionPlaybackState state) {
  DCHECK(media_session_->task_runner_);
  if (!media_session_->task_runner_->BelongsToCurrentThread()) {
    media_session_->task_runner_->PostTask(
        FROM_HERE, base::Bind(&MediaSessionClient::UpdatePlatformPlaybackState,
                              base::Unretained(this), state));
    return;
  }

  platform_playback_state_ = ConvertPlaybackState(state);
  if (session_state_.actual_playback_state() != ComputeActualPlaybackState()) {
    UpdateMediaSessionState();
  }

  PostDelayedTaskForMaybeFreezeCallback();
}

void MediaSessionClient::RunMaybeFreezeCallback(int sequence_number) {
  if (sequence_number != sequence_number_) return;

  if (!is_active() && !maybe_freeze_callback_.is_null()) {
    maybe_freeze_callback_.Run();
  }
}

void MediaSessionClient::InvokeActionInternal(
    std::unique_ptr<CobaltExtensionMediaSessionActionDetails> details) {
  DCHECK(details->action >= 0 &&
         details->action < kCobaltExtensionMediaSessionActionNumActions);

  // Some fields should only be set for applicable actions.
  DCHECK(details->seek_offset < 0.0 ||
         details->action == kCobaltExtensionMediaSessionActionSeekforward ||
         details->action == kCobaltExtensionMediaSessionActionSeekbackward);
  DCHECK(details->seek_time < 0.0 ||
         details->action == kCobaltExtensionMediaSessionActionSeekto);
  DCHECK(!details->fast_seek ||
         details->action == kCobaltExtensionMediaSessionActionSeekto);

  DCHECK(media_session_->task_runner_);
  if (!media_session_->task_runner_->BelongsToCurrentThread()) {
    media_session_->task_runner_->PostTask(
        FROM_HERE, base::Bind(&MediaSessionClient::InvokeActionInternal,
                              base::Unretained(this), base::Passed(&details)));
    return;
  }

  MediaSession::ActionMap::iterator it = media_session_->action_map_.find(
      ConvertMediaSessionAction(details->action));

  if (it == media_session_->action_map_.end()) {
    return;
  }

  std::unique_ptr<MediaSessionActionDetails> script_details =
      ConvertActionDetails(*details);
  it->second->value().Run(*script_details);

  // Queue a session update to reflect the effects of the action.
  if (!media_session_->media_position_state_) {
    media_session_->MaybeQueueChangeTask(kUpdateDelay);
  }
}

void MediaSessionClient::UpdateMediaSessionState() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  scoped_refptr<MediaMetadata> session_metadata(media_session_->metadata());
  base::Optional<MediaMetadataInit> metadata;
  if (session_metadata) {
    metadata.emplace();
    metadata->set_title(session_metadata->title());
    metadata->set_artist(session_metadata->artist());
    metadata->set_album(session_metadata->album());
    metadata->set_artwork(session_metadata->artwork());
  }

  session_state_ = MediaSessionState(
      metadata, media_session_->last_position_updated_time_,
      media_session_->media_position_state_, ComputeActualPlaybackState(),
      ComputeAvailableActions());

  // Compute the media position state if it's not set in the media session.
  if (!media_session_->media_position_state_ && media_player_factory_) {
    const media::WebMediaPlayer* player = nullptr;
    media_player_factory_->EnumerateWebMediaPlayers(base::BindRepeating(
        &GuessMediaPositionState, &session_state_, &player));

    // The media duration may be reported as 0 when seeking. Re-query the
    // media session state after a delay.
    if (session_state_.actual_playback_state() ==
            kMediaSessionPlaybackStatePlaying &&
        session_state_.duration() == 0) {
      media_session_->MaybeQueueChangeTask(kUpdateDelay);
    }
  }

  OnMediaSessionStateChanged(session_state_);
}

void MediaSessionClient::OnMediaSessionStateChanged(
    const MediaSessionState& session_state) {
  if (extension_ && extension_->version >= 1) {
    CobaltExtensionMediaSessionState ext_state;
    size_t artwork_size = 0;
    if (session_state.has_metadata() &&
        session_state.metadata().value().has_artwork()) {
      artwork_size = session_state.metadata().value().artwork().size();
    }
    std::unique_ptr<CobaltExtensionMediaImage[]> ext_artwork =
        std::unique_ptr<CobaltExtensionMediaImage[]>(
            new CobaltExtensionMediaImage[artwork_size]);

    ext_state.duration = session_state.duration();
    ext_state.actual_playback_rate = session_state.actual_playback_rate();
    ext_state.current_playback_position =
        session_state.current_playback_position();
    ext_state.has_position_state = session_state.has_position_state();
    ext_state.actual_playback_state =
        ConvertPlaybackState(session_state.actual_playback_state());
    ConvertMediaSessionActions(session_state.available_actions(),
                               ext_state.available_actions);
    std::string album = "";
    std::string artist = "";
    std::string title = "";

    if (session_state.has_metadata()) {
      const MediaMetadataInit& metadata = session_state.metadata().value();
      album = metadata.album();
      artist = metadata.artist();
      title = metadata.title();
      if (artwork_size > 0) {
        const MediaImageSequence& artwork(metadata.artwork());
        for (MediaImageSequence::size_type i = 0; i < artwork_size; i++) {
          const MediaImage& media_image(artwork.at(i));
          CobaltExtensionMediaImage ext_image;
          ext_image.src = media_image.src().c_str();
          ext_image.size = media_image.sizes().c_str();
          ext_image.type = media_image.type().c_str();
          ext_artwork[i] = ext_image;
        }
      }
    }
    CobaltExtensionMediaMetadata ext_metadata = {
        album.c_str(), artist.c_str(), title.c_str(), ext_artwork.get(),
        artwork_size};
    ext_state.metadata = &ext_metadata;

    extension_->OnMediaSessionStateChanged(ext_state);
  }
}

// static
void MediaSessionClient::UpdatePlatformPlaybackStateCallback(
    CobaltExtensionMediaSessionPlaybackState state, void* callback_context) {
  MediaSessionClient* client =
      static_cast<MediaSessionClient*>(callback_context);
  client->UpdatePlatformPlaybackState(state);
}

// static
void MediaSessionClient::InvokeActionCallback(
    CobaltExtensionMediaSessionActionDetails details, void* callback_context) {
  MediaSessionClient* client =
      static_cast<MediaSessionClient*>(callback_context);
  client->InvokeAction(details);
}

CobaltExtensionMediaSessionPlaybackState
MediaSessionClient::ConvertPlaybackState(MediaSessionPlaybackState state) {
  switch (state) {
    case kMediaSessionPlaybackStatePlaying:
      return kCobaltExtensionMediaSessionPlaying;
    case kMediaSessionPlaybackStatePaused:
      return kCobaltExtensionMediaSessionPaused;
    case kMediaSessionPlaybackStateNone:
    default:
      return kCobaltExtensionMediaSessionNone;
  }
}

MediaSessionPlaybackState MediaSessionClient::ConvertPlaybackState(
    CobaltExtensionMediaSessionPlaybackState state) {
  switch (state) {
    case kCobaltExtensionMediaSessionPlaying:
      return kMediaSessionPlaybackStatePlaying;
    case kCobaltExtensionMediaSessionPaused:
      return kMediaSessionPlaybackStatePaused;
    case kCobaltExtensionMediaSessionNone:
    default:
      return kMediaSessionPlaybackStateNone;
  }
}

void MediaSessionClient::ConvertMediaSessionActions(
    const MediaSessionState::AvailableActionsSet& actions,
    bool result[kCobaltExtensionMediaSessionActionNumActions]) {
  for (int i = 0; i < kCobaltExtensionMediaSessionActionNumActions; i++) {
    result[i] = false;
    MediaSessionAction action = static_cast<MediaSessionAction>(i);
    if (actions[action]) {
      result[ConvertMediaSessionAction(action)] = true;
    }
  }
}

std::unique_ptr<MediaSessionActionDetails>
MediaSessionClient::ConvertActionDetails(
    const CobaltExtensionMediaSessionActionDetails& ext_details) {
  std::unique_ptr<MediaSessionActionDetails> details(
      new MediaSessionActionDetails());
  details->set_action(ConvertMediaSessionAction(ext_details.action));
  if (ext_details.seek_offset >= 0.0) {
    details->set_seek_offset(ext_details.seek_offset);
  }
  if (ext_details.seek_time >= 0.0) {
    details->set_seek_time(ext_details.seek_time);
  }
  details->set_fast_seek(ext_details.fast_seek);
  return details;
}

CobaltExtensionMediaSessionAction MediaSessionClient::ConvertMediaSessionAction(
    MediaSessionAction action) {
  switch (action) {
    case kMediaSessionActionPause:
      return kCobaltExtensionMediaSessionActionPause;
    case kMediaSessionActionSeekbackward:
      return kCobaltExtensionMediaSessionActionSeekbackward;
    case kMediaSessionActionPrevioustrack:
      return kCobaltExtensionMediaSessionActionPrevioustrack;
    case kMediaSessionActionNexttrack:
      return kCobaltExtensionMediaSessionActionNexttrack;
    case kMediaSessionActionSeekforward:
      return kCobaltExtensionMediaSessionActionSeekforward;
    case kMediaSessionActionSeekto:
      return kCobaltExtensionMediaSessionActionSeekto;
    case kMediaSessionActionStop:
      return kCobaltExtensionMediaSessionActionStop;
    case kMediaSessionActionPlay:
    default:
      return kCobaltExtensionMediaSessionActionPlay;
  }
}

MediaSessionAction MediaSessionClient::ConvertMediaSessionAction(
    CobaltExtensionMediaSessionAction action) {
  switch (action) {
    case kCobaltExtensionMediaSessionActionPause:
      return kMediaSessionActionPause;
    case kCobaltExtensionMediaSessionActionSeekbackward:
      return kMediaSessionActionSeekbackward;
    case kCobaltExtensionMediaSessionActionPrevioustrack:
      return kMediaSessionActionPrevioustrack;
    case kCobaltExtensionMediaSessionActionNexttrack:
      return kMediaSessionActionNexttrack;
    case kCobaltExtensionMediaSessionActionSeekforward:
      return kMediaSessionActionSeekforward;
    case kCobaltExtensionMediaSessionActionSeekto:
      return kMediaSessionActionSeekto;
    case kCobaltExtensionMediaSessionActionStop:
      return kMediaSessionActionStop;
    case kCobaltExtensionMediaSessionActionPlay:
    default:
      return kMediaSessionActionPlay;
  }
}
}  // namespace media_session
}  // namespace cobalt
