// 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_;
};

void RunClosureAndSignal(const base::Closure& closure,
                         base::WaitableEvent* event) {
  closure.Run();
  event->Signal();
}

void RunClosureOnMessageLoopAndWait(
    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
    const base::Closure& closure) {
  base::WaitableEvent waitable_event(
      base::WaitableEvent::ResetPolicy::MANUAL,
      base::WaitableEvent::InitialState::NOT_SIGNALED);
  task_runner->PostTask(
      FROM_HERE, base::Bind(&RunClosureAndSignal, closure, &waitable_event));
  waitable_event.Wait();
}

}  // 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() {
  RunClosureOnMessageLoopAndWait(
      task_runner_,
      base::Bind(&MediaModule::SuspendTask, base::Unretained(this)));
  resource_provider_ = NULL;
}

void MediaModule::Resume(render_tree::ResourceProvider* resource_provider) {
  resource_provider_ = resource_provider;
  RunClosureOnMessageLoopAndWait(
      task_runner_,
      base::Bind(&MediaModule::ResumeTask, base::Unretained(this)));
}

void MediaModule::RegisterPlayer(WebMediaPlayer* player) {
  RunClosureOnMessageLoopAndWait(task_runner_,
                                 base::Bind(&MediaModule::RegisterPlayerTask,
                                            base::Unretained(this), player));
}

void MediaModule::UnregisterPlayer(WebMediaPlayer* player) {
  RunClosureOnMessageLoopAndWait(task_runner_,
                                 base::Bind(&MediaModule::UnregisterPlayerTask,
                                            base::Unretained(this), player));
}

void MediaModule::SuspendTask() {
  DCHECK(task_runner_->BelongsToCurrentThread());

  suspended_ = true;

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

void MediaModule::ResumeTask() {
  DCHECK(task_runner_->BelongsToCurrentThread());

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

  suspended_ = false;
}

void MediaModule::RegisterPlayerTask(WebMediaPlayer* player) {
  DCHECK(task_runner_->BelongsToCurrentThread());

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

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

void MediaModule::UnregisterPlayerTask(WebMediaPlayer* player) {
  DCHECK(task_runner_->BelongsToCurrentThread());

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

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

}  // namespace media
}  // namespace cobalt
