/*
 * Copyright 2016 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/debug/debug_server_module.h"

#include "cobalt/debug/render_layer.h"

namespace cobalt {
namespace debug {

DebugServerModule::DebugServerModule(
    dom::Console* console, script::GlobalObjectProxy* global_object_proxy,
    RenderOverlay* render_overlay,
    render_tree::ResourceProvider* resource_provider, dom::Window* window) {
  ConstructionData data(console, global_object_proxy, MessageLoop::current(),
                        render_overlay, resource_provider, window);
  Build(data);
}

DebugServerModule::DebugServerModule(
    dom::Console* console, script::GlobalObjectProxy* global_object_proxy,
    RenderOverlay* render_overlay,
    render_tree::ResourceProvider* resource_provider, dom::Window* window,
    MessageLoop* message_loop) {
  ConstructionData data(console, global_object_proxy, message_loop,
                        render_overlay, resource_provider, window);
  Build(data);
}

DebugServerModule::~DebugServerModule() { script_debugger_->Detach(); }

void DebugServerModule::Build(const ConstructionData& data) {
  DCHECK(data.message_loop);

  if (MessageLoop::current() == data.message_loop) {
    BuildInternal(data, NULL);
  } else {
    base::WaitableEvent created(true, false);
    data.message_loop->PostTask(
        FROM_HERE,
        base::Bind(&DebugServerModule::BuildInternal, base::Unretained(this),
                   data, base::Unretained(&created)));
    created.Wait();
  }

  DCHECK(debug_server_);
}

void DebugServerModule::BuildInternal(const ConstructionData& data,
                                      base::WaitableEvent* created) {
  DCHECK(MessageLoop::current() == data.message_loop);
  DCHECK(data.console);
  DCHECK(data.global_object_proxy);
  DCHECK(data.render_overlay);
  DCHECK(data.resource_provider);
  DCHECK(data.window);

  // Create the debug server itself.
  debug_server_.reset(new debug::DebugServer(
      data.global_object_proxy, data.window->document()->csp_delegate()));

  // Create render layers for the components that need them and chain them
  // together. Ownership will be passed to the component that uses each layer.
  // The layers will be painted in the reverse order they are listed here.
  scoped_ptr<RenderLayer> page_render_layer(new RenderLayer(base::Bind(
      &RenderOverlay::SetOverlay, base::Unretained(data.render_overlay))));

  scoped_ptr<RenderLayer> dom_render_layer(new RenderLayer(
      base::Bind(&RenderLayer::SetBackLayer, page_render_layer->AsWeakPtr())));

  // Create the script debugger. This is owned by this object, and is
  // accessible to all the debugger components.
  script_debugger_ =
      script::ScriptDebugger::CreateDebugger(data.global_object_proxy, this);

  // Create the connector object that provides functionality for each
  // component to interact with the debug server, script debugger, etc.
  component_connector_.reset(
      new ComponentConnector(debug_server_.get(), script_debugger_.get()));

  // Create the various components that implement the functionality of the
  // debugger by handling commands and sending event notifications.
  console_component_.reset(
      new ConsoleComponent(component_connector_.get(), data.console));

  dom_component_.reset(
      new DOMComponent(component_connector_.get(), dom_render_layer.Pass()));

  page_component_.reset(new PageComponent(component_connector_.get(),
                                          data.window, page_render_layer.Pass(),
                                          data.resource_provider));

  runtime_component_.reset(new RuntimeComponent(component_connector_.get()));

  script_debugger_component_.reset(
      new JavaScriptDebuggerComponent(component_connector_.get()));

  if (created) {
    created->Signal();
  }
}

void DebugServerModule::OnScriptDebuggerDetach(const std::string& reason) {
  DCHECK(script_debugger_component_);
  script_debugger_component_->OnScriptDebuggerDetach(reason);
}

void DebugServerModule::OnScriptDebuggerPause(
    scoped_ptr<script::CallFrame> call_frame) {
  DCHECK(script_debugger_component_);
  script_debugger_component_->OnScriptDebuggerPause(call_frame.Pass());
}

void DebugServerModule::OnScriptFailedToParse(
    scoped_ptr<script::SourceProvider> source_provider) {
  DCHECK(script_debugger_component_);
  script_debugger_component_->OnScriptFailedToParse(source_provider.Pass());
}

void DebugServerModule::OnScriptParsed(
    scoped_ptr<script::SourceProvider> source_provider) {
  DCHECK(script_debugger_component_);
  script_debugger_component_->OnScriptParsed(source_provider.Pass());
}

}  // namespace debug
}  // namespace cobalt
