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

#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") {
      // TODO(b/230888580): Revive ParseCodecString() to enable returning of
      // `codecs`.
      //   ParseCodecString(name_and_value[1], &codecs, /* strip= */ false);
      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.RecordQuery("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.RecordQuery("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
