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

#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/threading/thread_task_runner_handle.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[] = "debug_console";
}  // 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_manager = ConsoleCommandManager::GetInstance();
  DCHECK(command_manager);
  if (command_manager) {
    std::set<std::string> commands = command_manager->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_manager->GetShortHelp(*it));
      console_command.set_long_help(command_manager->GetLongHelp(*it));
      result.push_back(console_command);
    }
  }
  return result;
}

std::string DebugHub::SendConsoleCommand(const std::string& command,
                                         const std::string& message) {
  ConsoleCommandManager* console_command_manager =
      ConsoleCommandManager::GetInstance();
  DCHECK(console_command_manager);
  return 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 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::ThreadTaskRunnerHandle::Get(), callback_info->task_runner);
  callback_info->callback.value().Run(std::move(response));
}

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