// Copyright 2015 Google Inc. 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/sandbox/media_sandbox.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/synchronization/lock.h"
#include "cobalt/base/event_dispatcher.h"
#include "cobalt/math/size.h"
#include "cobalt/math/size_f.h"
#include "cobalt/network/network_module.h"
#include "cobalt/render_tree/animations/animate_node.h"
#include "cobalt/render_tree/image_node.h"
#include "cobalt/render_tree/resource_provider.h"
#include "cobalt/renderer/pipeline.h"
#include "cobalt/renderer/renderer_module.h"
#include "cobalt/renderer/submission.h"
#include "cobalt/storage/storage_manager.h"
#include "cobalt/system_window/system_window.h"
#include "cobalt/trace_event/scoped_trace_to_file.h"

namespace cobalt {
namespace media {
namespace sandbox {

namespace {
const int kViewportWidth = 1920;
const int kViewportHeight = 1080;
}  // namespace

class MediaSandbox::Impl {
 public:
  Impl(int argc, char** argv, const FilePath& trace_log_path);

  void RegisterFrameCB(const MediaSandbox::FrameCB& frame_cb);
  MediaModule* GetMediaModule() { return media_module_.get(); }
  loader::FetcherFactory* GetFetcherFactory() { return fetcher_factory_.get(); }

 private:
  void SetupAndSubmitScene();
  void AnimateCB(render_tree::ImageNode::Builder* image_node,
                 base::TimeDelta time);

  base::Lock lock_;
  MessageLoop message_loop_;
  MediaSandbox::FrameCB frame_cb_;

  scoped_ptr<trace_event::ScopedTraceToFile> trace_to_file_;
  scoped_ptr<network::NetworkModule> network_module_;
  scoped_ptr<loader::FetcherFactory> fetcher_factory_;
  base::EventDispatcher event_dispatcher_;
  // System window used as a render target.
  scoped_ptr<system_window::SystemWindow> system_window_;
  scoped_ptr<renderer::RendererModule> renderer_module_;
  scoped_ptr<MediaModule> media_module_;
};

MediaSandbox::Impl::Impl(int argc, char** argv,
                         const FilePath& trace_log_path) {
  trace_to_file_.reset(new trace_event::ScopedTraceToFile(trace_log_path));
  network::NetworkModule::Options network_options;
  network_options.require_https = false;

  network_module_.reset(new network::NetworkModule(network_options));
  fetcher_factory_.reset(new loader::FetcherFactory(network_module_.get()));
  system_window_.reset(new system_window::SystemWindow(
      &event_dispatcher_, math::Size(kViewportWidth, kViewportHeight)));

  renderer::RendererModule::Options renderer_options;
  renderer_module_.reset(
      new renderer::RendererModule(system_window_.get(), renderer_options));
  MediaModule::Options media_module_options;
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  // Use string literals directly to avoid dependency on browser::switches.
  if (command_line->HasSwitch("audio_decoder_stub")) {
    media_module_options.use_audio_decoder_stub = true;
  }
  if (command_line->HasSwitch("null_audio_streamer")) {
    media_module_options.use_null_audio_streamer = true;
  }
  if (command_line->HasSwitch("video_decoder_stub")) {
    media_module_options.use_video_decoder_stub = true;
  }
#endif  // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)

  media_module_ = MediaModule::Create(
      system_window_.get(), renderer_module_->pipeline()->GetResourceProvider(),
      media_module_options);
  SetupAndSubmitScene();
}

void MediaSandbox::Impl::RegisterFrameCB(
    const MediaSandbox::FrameCB& frame_cb) {
  base::AutoLock auto_lock(lock_);
  frame_cb_ = frame_cb;
}

void MediaSandbox::Impl::AnimateCB(render_tree::ImageNode::Builder* image_node,
                                   base::TimeDelta time) {
  DCHECK(image_node);
  math::SizeF output_size(renderer_module_->render_target()->GetSize());
  image_node->destination_rect = math::RectF(output_size);
  base::AutoLock auto_lock(lock_);
  image_node->source = frame_cb_.is_null() ? NULL : frame_cb_.Run(time);
}

void MediaSandbox::Impl::SetupAndSubmitScene() {
  scoped_refptr<render_tree::ImageNode> image_node =
      new render_tree::ImageNode(NULL);
  render_tree::animations::AnimateNode::Builder animate_node_builder;

  animate_node_builder.Add(
      image_node, base::Bind(&Impl::AnimateCB, base::Unretained(this)));

  renderer_module_->pipeline()->Submit(
      renderer::Submission(new render_tree::animations::AnimateNode(
                               animate_node_builder, image_node),
                           base::TimeDelta()));
}

MediaSandbox::MediaSandbox(int argc, char** argv,
                           const FilePath& trace_log_path) {
  impl_ = new Impl(argc, argv, trace_log_path);
}

MediaSandbox::~MediaSandbox() {
  DCHECK(impl_);
  delete impl_;
}

void MediaSandbox::RegisterFrameCB(const FrameCB& frame_cb) {
  DCHECK(impl_);
  impl_->RegisterFrameCB(frame_cb);
}

MediaModule* MediaSandbox::GetMediaModule() {
  DCHECK(impl_);
  return impl_->GetMediaModule();
}

loader::FetcherFactory* MediaSandbox::GetFetcherFactory() {
  DCHECK(impl_);
  return impl_->GetFetcherFactory();
}

}  // namespace sandbox
}  // namespace media
}  // namespace cobalt
