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

#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/synchronization/waitable_event.h"
#include "cobalt/media/base/media_log.h"
#include "cobalt/media/base/mime_util.h"
#include "nb/memory_scope.h"
#include "starboard/common/string.h"
#include "starboard/media.h"
#include "starboard/window.h"

#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
#include "cobalt/browser/switches.h"
#endif  // ENABLE_DEBUG_COMMAND_LINE_SWITCHES

namespace cobalt {
namespace media {

namespace {

class CanPlayTypeHandlerStarboard : public CanPlayTypeHandler {
 public:
  void SetDisabledMediaCodecs(
      const std::string& disabled_media_codecs) override {
    disabled_media_codecs_ =
        base::SplitString(disabled_media_codecs, ";", base::TRIM_WHITESPACE,
                          base::SPLIT_WANT_NONEMPTY);
    LOG(INFO) << "Disabled media codecs \"" << disabled_media_codecs
              << "\" from console/command line.";
  }

  SbMediaSupportType CanPlayType(const std::string& mime_type,
                                 const std::string& key_system,
                                 bool is_progressive) const override {
    if (is_progressive) {
      // |mime_type| is something like:
      //   video/mp4
      //   video/webm
      //   video/mp4; codecs="avc1.4d401e"
      //   video/webm; codecs="vp9"
      // We do a rough pre-filter to ensure that only video/mp4 is supported as
      // progressive.
      if (SbStringFindString(mime_type.c_str(), "video/mp4") == 0 &&
          SbStringFindString(mime_type.c_str(), "application/x-mpegURL") == 0) {
        return kSbMediaSupportTypeNotSupported;
      }
    }
    if (!disabled_media_codecs_.empty()) {
      auto mime_codecs = ExtractCodecs(mime_type);
      for (auto& disabled_codec : disabled_media_codecs_) {
        for (auto& mime_codec : mime_codecs) {
          if (mime_codec.find(disabled_codec) != std::string::npos) {
            LOG(INFO) << "Codec (" << mime_codec
                      << ") is disabled via console/command line.";
            return kSbMediaSupportTypeNotSupported;
          }
        }
      }
    }
    SbMediaSupportType type =
        SbMediaCanPlayMimeAndKeySystem(mime_type.c_str(), key_system.c_str());
    return type;
  }

 private:
  std::vector<std::string> ExtractCodecs(const std::string& mime_type) const {
    std::vector<std::string> codecs;
    std::vector<std::string> components = base::SplitString(
        mime_type, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    LOG_IF(WARNING, components.empty())
        << "argument mime type \"" << mime_type << "\" is not valid.";
    // The first component is the type/subtype pair. We want to iterate over the
    // remaining components to search for the codecs.
    auto iter = components.begin() + 1;
    for (; iter != components.end(); ++iter) {
      std::vector<std::string> name_and_value = base::SplitString(
          *iter, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
      if (name_and_value.size() != 2) {
        LOG(WARNING) << "parameter for mime_type \"" << mime_type
                     << "\" is not valid.";
        continue;
      }
      if (name_and_value[0] == "codecs") {
        ParseCodecString(name_and_value[1], &codecs, /* strip= */ false);
        return codecs;
      }
    }
    return codecs;
  }

  // List of disabled media codecs that will be treated as unsupported.
  std::vector<std::string> disabled_media_codecs_;
};

}  // namespace

std::unique_ptr<WebMediaPlayer> MediaModule::CreateWebMediaPlayer(
    WebMediaPlayerClient* client) {
  TRACK_MEMORY_SCOPE("Media");
  SbWindow window = kSbWindowInvalid;
  if (system_window_) {
    window = system_window_->GetSbWindow();
  }
  return std::unique_ptr<WebMediaPlayer>(new media::WebMediaPlayerImpl(
      window,
      base::Bind(&MediaModule::GetSbDecodeTargetGraphicsContextProvider,
                 base::Unretained(this)),
      client, this, &decoder_buffer_allocator_,
      options_.allow_resume_after_suspend, new media::MediaLog));
}

void MediaModule::Suspend() {
  starboard::ScopedLock scoped_lock(players_lock_);

  suspended_ = true;

  for (Players::iterator iter = players_.begin(); iter != players_.end();
       ++iter) {
    DCHECK(!iter->second);
    if (!iter->second) {
      iter->first->Suspend();
    }
  }

  resource_provider_ = NULL;
}

void MediaModule::Resume(render_tree::ResourceProvider* resource_provider) {
  starboard::ScopedLock scoped_lock(players_lock_);

  resource_provider_ = resource_provider;

  for (Players::iterator iter = players_.begin(); iter != players_.end();
       ++iter) {
    DCHECK(!iter->second);
    if (!iter->second) {
      iter->first->Resume();
    }
  }

  suspended_ = false;
}

void MediaModule::RegisterPlayer(WebMediaPlayer* player) {
  starboard::ScopedLock scoped_lock(players_lock_);

  DCHECK(players_.find(player) == players_.end());
  players_.insert(std::make_pair(player, false));

  if (suspended_) {
    player->Suspend();
  }
}

void MediaModule::UnregisterPlayer(WebMediaPlayer* player) {
  starboard::ScopedLock scoped_lock(players_lock_);

  DCHECK(players_.find(player) != players_.end());
  players_.erase(players_.find(player));
}

void MediaModule::EnumerateWebMediaPlayers(
    const EnumeratePlayersCB& enumerate_callback) const {
  starboard::ScopedLock scoped_lock(players_lock_);

  for (Players::const_iterator iter = players_.begin(); iter != players_.end();
       ++iter) {
    enumerate_callback.Run(iter->first);
  }
}

std::unique_ptr<CanPlayTypeHandler> MediaModule::CreateCanPlayTypeHandler() {
  return std::unique_ptr<CanPlayTypeHandler>(new CanPlayTypeHandlerStarboard);
}

}  // namespace media
}  // namespace cobalt
