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

#include "cobalt/debug/console/debug_hub.h"

#include <memory>
#include <set>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_writer.h"
#include "base/path_service.h"
#include "base/values.h"
#include "cobalt/base/c_val.h"
#include "cobalt/base/cobalt_paths.h"
#include "cobalt/debug/console/command_manager.h"
#include "cobalt/debug/json_object.h"

namespace cobalt {
namespace debug {
namespace console {

namespace {
constexpr char kContentDir[] = "cobalt/debug";
}  // namespace

DebugHub::DebugHub(
    const GetHudModeCallback& get_hud_mode_callback,
    const CreateDebugClientCallback& create_debug_client_callback)
    : c_val_(new dom::CValView()),
      get_hud_mode_callback_(get_hud_mode_callback),
      create_debug_client_callback_(create_debug_client_callback),
      on_event_(new DebuggerEventTarget()) {}

DebugHub::~DebugHub() {}

debug::console::DebugConsoleMode DebugHub::GetDebugConsoleMode() const {
  return get_hud_mode_callback_.Run();
}

void DebugHub::Attach(const AttachCallbackArg& callback) {
  last_error_ = base::nullopt;
  debug_client_ = create_debug_client_callback_.Run(this);

  // |debug_client_| may be NULL if the WebModule is not available at this time.
  if (!debug_client_) {
    DLOG(WARNING) << "Debug dispatcher unavailable.";
    last_error_ = "Debug dispatcher unavailable.";
  }

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

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

std::string DebugHub::ReadDebugContentText(const std::string& filename) {
  std::string result;

  base::FilePath file_path;
  base::PathService::Get(paths::DIR_COBALT_WEB_ROOT, &file_path);
  file_path = file_path.AppendASCII(kContentDir);
  file_path = file_path.AppendASCII(filename);

  std::string text;
  if (!base::ReadFileToString(file_path, &text)) {
    DLOG(WARNING) << "Cannot read file: " << file_path.value();
  }
  return text;
}

void DebugHub::SendCommand(const std::string& method,
                           const std::string& json_params,
                           const ResponseCallbackArg& callback) {
  last_error_ = base::nullopt;
  if (!debug_client_ || !debug_client_->IsAttached()) {
    std::unique_ptr<base::DictionaryValue> response(new base::DictionaryValue);
    response->SetString("error.message", "Debugger is not connected.");
    std::string json_response;
    auto* response_as_value = static_cast<const base::Value*>(response.get());
    base::JSONWriter::Write(*response_as_value, &json_response);
    ResponseCallbackArg::Reference callback_ref(this, callback);
    callback_ref.value().Run(json_response);
    return;
  }

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

const script::Sequence<ConsoleCommand> DebugHub::console_commands() const {
  script::Sequence<ConsoleCommand> result;
  ConsoleCommandManager* command_mananger =
      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 DebugHub::SendConsoleCommand(const std::string& command,
                                  const std::string& message) {
  ConsoleCommandManager* console_command_manager =
      ConsoleCommandManager::GetInstance();
  DCHECK(console_command_manager);
  console_command_manager->HandleCommand(command, message);
}

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

void DebugHub::OnCommandResponse(
    const scoped_refptr<ResponseCallbackInfo>& callback_info,
    const base::Optional<std::string>& response) const {
  // Run the script callback on the message loop the command was sent from.
  callback_info->task_runner->PostTask(
      FROM_HERE, base::Bind(&DebugHub::RunResponseCallback, this, callback_info,
                            response));
}

void DebugHub::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 DebugHub::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 DebugHub::RunResponseCallback(
    const scoped_refptr<ResponseCallbackInfo>& callback_info,
    base::Optional<std::string> response) const {
  DCHECK_EQ(base::MessageLoop::current()->task_runner(),
            callback_info->task_runner);
  callback_info->callback.value().Run(std::move(response));
}

}  // namespace console
}  // namespace debug
}  // namespace cobalt
