// Copyright 2015 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.

#if defined(ENABLE_DEBUG_CONSOLE)

#include "cobalt/debug/debugger.h"

#include <set>

#include "base/json/json_writer.h"
#include "base/values.h"
#include "cobalt/base/console_commands.h"

namespace cobalt {
namespace debug {

Debugger::Debugger(const GetDebugServerCallback& get_debug_server_callback)
    : get_debug_server_callback_(get_debug_server_callback),
      on_event_(new DebuggerEventTarget()) {}

Debugger::~Debugger() {}

void Debugger::Attach(const AttachCallbackArg& callback) {
  last_error_ = base::nullopt;
  DebugServer* debug_server = get_debug_server_callback_.Run();

  // |debug_server| may be NULL if the WebModule is not available at this time.
  if (debug_server) {
    debug_client_.reset(new DebugClient(debug_server, this));
  } else {
    DLOG(WARNING) << "Debug server unavailable.";
    last_error_ = "Debug server unavailable.";
  }

  AttachCallbackArg::Reference callback_reference(this, callback);
  callback_reference.value().Run();
}

void Debugger::Detach(const AttachCallbackArg& callback) {
  last_error_ = base::nullopt;
  debug_client_.reset(NULL);
  AttachCallbackArg::Reference callback_reference(this, callback);
  callback_reference.value().Run();
}

void Debugger::SendCommand(const std::string& method,
                           const std::string& json_params,
                           const CommandCallbackArg& callback) {
  last_error_ = base::nullopt;
  if (!debug_client_ || !debug_client_->IsAttached()) {
    scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue);
    response->SetString("error.message",
                        "Debugger is not connected - call attach first.");
    std::string json_response;
    base::JSONWriter::Write(response.get(), &json_response);
    CommandCallbackArg::Reference callback_ref(this, callback);
    callback_ref.value().Run(json_response);
    return;
  }

  scoped_refptr<CommandCallbackInfo> callback_info(
      new CommandCallbackInfo(this, callback));
  debug_client_->SendCommand(
      method, json_params,
      base::Bind(&Debugger::OnCommandResponse, this, callback_info));
}

const script::Sequence<ConsoleCommand> Debugger::console_commands() const {
  script::Sequence<ConsoleCommand> result;
  base::ConsoleCommandManager* command_mananger =
      base::ConsoleCommandManager::GetInstance();
  DCHECK(command_mananger);
  if (command_mananger) {
    std::set<std::string> commands = command_mananger->GetRegisteredCommands();
    for (std::set<std::string>::const_iterator it = commands.begin();
         it != commands.end(); ++it) {
      ConsoleCommand console_command;
      console_command.set_command(*it);
      console_command.set_short_help(command_mananger->GetShortHelp(*it));
      console_command.set_long_help(command_mananger->GetLongHelp(*it));
      result.push_back(console_command);
    }
  }
  return result;
}

void Debugger::SendConsoleCommand(const std::string& command,
                                  const std::string& message) {
  base::ConsoleCommandManager* console_command_manager =
      base::ConsoleCommandManager::GetInstance();
  DCHECK(console_command_manager);
  console_command_manager->HandleCommand(command, message);
}

void Debugger::TraceMembers(script::Tracer* tracer) {
  tracer->Trace(on_event_);
}

void Debugger::OnCommandResponse(
    const scoped_refptr<CommandCallbackInfo>& callback_info,
    const base::optional<std::string>& response) const {
  // Run the script callback on the message loop the command was sent from.
  callback_info->message_loop_proxy->PostTask(
      FROM_HERE,
      base::Bind(&Debugger::RunCommandCallback, this, callback_info, response));
}

void Debugger::OnDebugClientEvent(const std::string& method,
                                  const base::optional<std::string>& params) {
  // Pass to the onEvent handler. The handler will notify the JavaScript
  // listener on the message loop the listener was registered on.
  on_event_->DispatchEvent(method, params);
}

void Debugger::OnDebugClientDetach(const std::string& reason) {
  DLOG(INFO) << "Debugger detached: " + reason;
  const std::string method = "Inspector.detached";
  JSONObject params(new base::DictionaryValue());
  params->SetString("reason", reason);
  on_event_->DispatchEvent(method, JSONStringify(params));
}

void Debugger::RunCommandCallback(
    const scoped_refptr<CommandCallbackInfo>& callback_info,
    base::optional<std::string> response) const {
  DCHECK_EQ(base::MessageLoopProxy::current(),
            callback_info->message_loop_proxy);
  callback_info->callback.value().Run(response);
}
}  // namespace debug
}  // namespace cobalt

#endif  // ENABLE_DEBUG_CONSOLE
