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

#ifndef COBALT_MEDIA_SESSION_MEDIA_SESSION_CLIENT_H_
#define COBALT_MEDIA_SESSION_MEDIA_SESSION_CLIENT_H_

#include <bitset>
#include <memory>

#include "base/threading/thread_checker.h"
#include "cobalt/extension/media_session.h"
#include "cobalt/media/web_media_player_factory.h"
#include "cobalt/media_session/media_session.h"
#include "cobalt/media_session/media_session_action_details.h"
#include "cobalt/media_session/media_session_state.h"
#include "starboard/time.h"

namespace cobalt {
namespace media_session {

// Base class for a platform-level implementation of MediaSession.
// Platforms should subclass this to connect MediaSession to their platform.
class MediaSessionClient {
  friend class MediaSession;

 public:
  MediaSessionClient(): MediaSessionClient(nullptr) {}
  // Injectable MediaSession for tests.
  explicit MediaSessionClient(MediaSession* media_session);

  virtual ~MediaSessionClient();

  // Creates platform-specific instance.
  static std::unique_ptr<MediaSessionClient> Create();

  // Retrieves the singleton MediaSession associated with this client.
  MediaSession* GetMediaSession() { return media_session_; }

  // The web app should set the MediaPositionState of the MediaSession object.
  // However, if that is not done, then query the web media player factory to
  // guess which player is associated with the media session to get the media
  // position state. The player factory must outlive the media session client.
  void SetMediaPlayerFactory(const media::WebMediaPlayerFactory* factory);

  // Sets the platform's current playback state. This is used to compute
  // the "guessed playback state"
  // https://wicg.github.io/mediasession/#guessed-playback-state
  // Can be invoked from any thread.
  void UpdatePlatformCobaltExtensionPlaybackState(
      CobaltExtensionMediaSessionPlaybackState state);

  // Deprecated - use the alternative
  // UpdatePlatformCobaltExtensionPlaybackState.
  // TODO: Delete once platform migrations to CobaltExtensionMediaSessionApi are
  // complete.
  void UpdatePlatformPlaybackState(MediaSessionPlaybackState state) {
    UpdatePlatformCobaltExtensionPlaybackState(ConvertPlaybackState(state));
  }

  // Invokes a given media session action
  // https://wicg.github.io/mediasession/#actions-model
  // Can be invoked from any thread.
  void InvokeAction(CobaltExtensionMediaSessionAction action) {
    std::unique_ptr<CobaltExtensionMediaSessionActionDetails> details(
        new CobaltExtensionMediaSessionActionDetails());
    CobaltExtensionMediaSessionActionDetailsInit(details.get(), action);
    InvokeActionInternal(std::move(details));
  }

  // Invokes a given media session action that takes additional details.
  void InvokeCobaltExtensionAction(
      CobaltExtensionMediaSessionActionDetails details) {
    std::unique_ptr<CobaltExtensionMediaSessionActionDetails> details_ptr(
        new CobaltExtensionMediaSessionActionDetails(details));
    InvokeActionInternal(std::move(details_ptr));
  }

  // Deprecated - use the alternative InvokeCobaltExtensionAction.
  // TODO: Delete once platform migrations to CobaltExtensionMediaSessionApi are
  // complete.
  void InvokeAction(std::unique_ptr<MediaSessionActionDetails> details) {
    std::unique_ptr<CobaltExtensionMediaSessionActionDetails> ext_details(
        new CobaltExtensionMediaSessionActionDetails());
    CobaltExtensionMediaSessionActionDetailsInit(
        ext_details.get(), ConvertMediaSessionAction(details->action()));
    if (details->has_seek_offset()) {
      ext_details->seek_offset = details->seek_offset().value();
    }
    if (details->has_seek_time()) {
      ext_details->seek_time = details->seek_time().value();
    }
    if (details->has_fast_seek()) {
      ext_details->fast_seek = details->fast_seek().value();
    }
    InvokeActionInternal(std::move(ext_details));
  }

  // Invoked on the browser thread when any metadata, position state, playback
  // state, or supported session actions change.
  virtual void OnMediaSessionStateChanged(
      const MediaSessionState& session_state);

  // Indicate the media session client is active or not depending on the
  // media session playback state.
  bool is_active() {
    return session_state_.actual_playback_state() !=
        kMediaSessionPlaybackStateNone;
  }

  // Set maybe freeze callback.
  void SetMaybeFreezeCallback(const base::Closure& maybe_freeze_callback) {
    maybe_freeze_callback_ = maybe_freeze_callback;
  }

  void set_media_session(MediaSession* media_session) {
    media_session_ = media_session;
  }

 private:
  THREAD_CHECKER(thread_checker_);
  MediaSession* media_session_;
  MediaSessionState session_state_;
  MediaSessionPlaybackState platform_playback_state_;
  const media::WebMediaPlayerFactory* media_player_factory_ = nullptr;
  const CobaltExtensionMediaSessionApi* extension_;

  void UpdateMediaSessionState();
  MediaSessionPlaybackState ComputeActualPlaybackState() const;
  MediaSessionState::AvailableActionsSet ComputeAvailableActions() const;
  void InvokeActionInternal(
      std::unique_ptr<CobaltExtensionMediaSessionActionDetails> details);

  void ConvertMediaSessionActions(
      const MediaSessionState::AvailableActionsSet& actions,
      bool result[kCobaltExtensionMediaSessionActionNumActions]);
  std::unique_ptr<MediaSessionActionDetails> ConvertActionDetails(
      const CobaltExtensionMediaSessionActionDetails& ext_details);

  // Static callback wrappers for MediaSessionAPI extension.
  static void UpdatePlatformPlaybackStateCallback(
      CobaltExtensionMediaSessionPlaybackState state, void* callback_context);
  static void InvokeActionCallback(
      CobaltExtensionMediaSessionActionDetails details, void* callback_context);

  // MediaSessionAPI extension type conversion helpers.
  CobaltExtensionMediaSessionPlaybackState ConvertPlaybackState(
      MediaSessionPlaybackState state);
  MediaSessionPlaybackState ConvertPlaybackState(
      CobaltExtensionMediaSessionPlaybackState state);
  CobaltExtensionMediaSessionAction ConvertMediaSessionAction(
      MediaSessionAction action);
  MediaSessionAction ConvertMediaSessionAction(
      CobaltExtensionMediaSessionAction action);

  base::Closure maybe_freeze_callback_;

  DISALLOW_COPY_AND_ASSIGN(MediaSessionClient);
};

}  // namespace media_session
}  // namespace cobalt

#endif  // COBALT_MEDIA_SESSION_MEDIA_SESSION_CLIENT_H_
