// 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.h"

#include "base/threading/thread_task_runner_handle.h"
#include "cobalt/media_session/media_session_client.h"

namespace cobalt {
namespace media_session {

MediaSession::MediaSession()
    : playback_state_(kMediaSessionPlaybackStateNone),
      task_runner_(base::ThreadTaskRunnerHandle::Get()),
      is_change_task_queued_(false),
      last_position_updated_time_(0) {}

MediaSession::~MediaSession() {
  // Stop the media session client first. This avoids possible access to media
  // session during destruction.
  media_session_client_.reset();

  ActionMap::iterator it;
  for (it = action_map_.begin(); it != action_map_.end(); ++it) {
    delete it->second;
  }
  action_map_.clear();
}

MediaSession::MediaSession(MediaSessionClient* client)
    : media_session_client_(client),
      playback_state_(kMediaSessionPlaybackStateNone),
      task_runner_(base::ThreadTaskRunnerHandle::Get()),
      is_change_task_queued_(false),
      last_position_updated_time_(0) {}

void MediaSession::set_metadata(scoped_refptr<MediaMetadata> value) {
  metadata_ = value;
  MaybeQueueChangeTask(base::TimeDelta());
}

void MediaSession::set_playback_state(
    MediaSessionPlaybackState playback_state) {
  playback_state_ = playback_state;
  MaybeQueueChangeTask(base::TimeDelta());
}

void MediaSession::SetActionHandler(
    MediaSessionAction action, const MediaSessionActionHandlerHolder& handler) {
  // See algorithm https://wicg.github.io/mediasession/#actions-model
  DCHECK(task_runner_->BelongsToCurrentThread());
  ActionMap::iterator it = action_map_.find(action);

  if (it != action_map_.end()) {
    delete it->second;
    action_map_.erase(it);
  }
  if (!handler.IsNull()) {
    action_map_[action] = new MediaSessionActionHandlerReference(this, handler);
  }

  MaybeQueueChangeTask(base::TimeDelta());
}

void MediaSession::SetPositionState(base::Optional<MediaPositionState> state) {
  last_position_updated_time_ = GetMonotonicNow();
  media_position_state_ = state;
  MaybeQueueChangeTask(base::TimeDelta());
}

void MediaSession::TraceMembers(script::Tracer* tracer) {
  tracer->Trace(metadata_.get());
}

bool MediaSession::IsChangeTaskQueuedForTesting() const {
  DCHECK(task_runner_->BelongsToCurrentThread());
  return is_change_task_queued_;
}

void MediaSession::EnsureMediaSessionClient() {
  if (media_session_client_ == nullptr) {
    media_session_client_ = std::make_unique<MediaSessionClient>();
    DCHECK(media_session_client_);
    media_session_client_->set_media_session(this);
  }
}

void MediaSession::MaybeQueueChangeTask(base::TimeDelta delay) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (is_change_task_queued_) {
    return;
  }
  is_change_task_queued_ = true;
  task_runner_->PostDelayedTask(
      FROM_HERE, base::Bind(&MediaSession::OnChanged, this), delay);
}

void MediaSession::OnChanged() {
  is_change_task_queued_ = false;
  if (media_session_client_) {
    media_session_client_->UpdateMediaSessionState();
  }
}

}  // namespace media_session
}  // namespace cobalt
