// 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 <algorithm>
#include <string>
#include <utility>
#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/format_support_query_metrics.h"
#include "nb/memory_scope.h"
#include "starboard/common/string.h"
#include "starboard/media.h"
#include "starboard/window.h"
#include "third_party/chromium/media/base/mime_util.h"

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

namespace cobalt {
namespace media {

namespace {

// TODO: Determine if ExtractCodecs() and ExtractEncryptionScheme() can be
// combined and simplified.
static std::vector<std::string> ExtractCodecs(const std::string& mime_type) {
  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") {
      ::media::SplitCodecs(name_and_value[1], &codecs);
      return codecs;
    }
  }
  return codecs;
}

static std::string ExtractEncryptionScheme(const std::string& key_system) {
  std::vector<std::string> components = base::SplitString(
      key_system, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);

  auto iter = components.begin();
  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() != 1 && name_and_value.size() != 2) {
      LOG(WARNING) << "parameter for key_system \"" << key_system
                   << "\" is not valid.";
      continue;
    }
    if (name_and_value[0] == "encryptionscheme") {
      if (name_and_value.size() < 2) {
        return "";
      }
      base::RemoveChars(name_and_value[1], "\"", &name_and_value[1]);
      return name_and_value[1];
    }
  }
  return "";
}

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.";
  }

  void SetDisabledMediaEncryptionSchemes(
      const std::string& disabled_encryption_schemes) override {
    disabled_encryption_schemes_ =
        base::SplitString(disabled_encryption_schemes, ";",
                          base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    LOG(INFO) << "Disabled encryption scheme(s) \""
              << disabled_encryption_schemes << "\" from command line.";
  }

  SbMediaSupportType CanPlayProgressive(
      const std::string& mime_type) const override {
    // |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.
    SbMediaSupportType support_type;
    media::FormatSupportQueryMetrics metrics;
    if (strstr(mime_type.c_str(), "video/mp4") == 0 &&
        strstr(mime_type.c_str(), "application/x-mpegURL") == 0) {
      support_type = kSbMediaSupportTypeNotSupported;
    } else {
      support_type = CanPlayType(mime_type, "");
    }
    metrics.RecordAndLogQuery("HTMLMediaElement::canPlayType", mime_type, "",
                              support_type);
    return support_type;
  }

  SbMediaSupportType CanPlayAdaptive(
      const std::string& mime_type,
      const std::string& key_system) const override {
    media::FormatSupportQueryMetrics metrics;
    SbMediaSupportType support_type = CanPlayType(mime_type, key_system);
    metrics.RecordAndLogQuery("MediaSource::IsTypeSupported", mime_type,
                              key_system, support_type);
    return support_type;
  }

 private:
  SbMediaSupportType CanPlayType(const std::string& mime_type,
                                 const std::string& key_system) const {
    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;
          }
        }
      }
    }

    if (!disabled_encryption_schemes_.empty()) {
      std::string encryption_scheme = ExtractEncryptionScheme(key_system);
      if (std::find(disabled_encryption_schemes_.begin(),
                    disabled_encryption_schemes_.end(),
                    encryption_scheme) != disabled_encryption_schemes_.end()) {
        LOG(INFO) << "Encryption scheme (" << encryption_scheme
                  << ") is disabled via console/command line.";
        return kSbMediaSupportTypeNotSupported;
      }
    }
    SbMediaSupportType type =
        SbMediaCanPlayMimeAndKeySystem(mime_type.c_str(), key_system.c_str());
    return type;
  }

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

}  // 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, options_.allow_resume_after_suspend, &media_log_));
}

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();
    }
  }

  decoder_buffer_allocator_.Suspend();

  resource_provider_ = NULL;
}

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

  resource_provider_ = resource_provider;

  SbWindow window = kSbWindowInvalid;
  if (system_window_) {
    window = system_window_->GetSbWindow();
  }

  decoder_buffer_allocator_.Resume();

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

  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
