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

#if defined(ENABLE_DEBUG_CONSOLE)

#include "cobalt/debug/debug_hub.h"

#include <set>

#include "base/compiler_specific.h"
#include "cobalt/base/c_val.h"
#include "cobalt/base/console_commands.h"
#include "cobalt/base/source_location.h"

namespace cobalt {
namespace debug {

namespace {
class ScopedSetter {
 public:
  explicit ScopedSetter(bool* to_set) : to_set_(to_set) {
    DCHECK(to_set_);
    *to_set_ = true;
  }
  ~ScopedSetter() { *to_set_ = false; }

 private:
  bool* to_set_;
};
}  // namespace

DebugHub::DebugHub(
    const GetHudModeCallback& get_hud_mode_callback,
    const Debugger::GetDebugServerCallback& get_debug_server_callback)
    : message_loop_(MessageLoop::current()),
      get_hud_mode_callback_(get_hud_mode_callback),
      debugger_(new Debugger(get_debug_server_callback)),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
      weak_ptr_(weak_ptr_factory_.GetWeakPtr()),
      is_logging_(false) {
  // Get log output while still making it available elsewhere.
  const base::LogMessageHandler::OnLogMessageCallback on_log_message_callback =
      base::Bind(&DebugHub::OnLogMessage, base::Unretained(this));
  log_message_handler_callback_id_ =
      base::LogMessageHandler::GetInstance()->AddCallback(
          on_log_message_callback);
}

DebugHub::~DebugHub() {
  base::LogMessageHandler::GetInstance()->RemoveCallback(
      log_message_handler_callback_id_);
}

bool DebugHub::OnLogMessage(int severity, const char* file, int line,
                            size_t message_start, const std::string& str) {
  // Don't run recursively.
  if (MessageLoop::current() == message_loop_ && is_logging_) {
    return false;
  }

  message_loop_->PostTask(FROM_HERE,
                          base::Bind(&DebugHub::OnLogMessageInternal, weak_ptr_,
                                     severity, file, line, message_start, str));

  // Don't suppress the log message.
  return false;
}

void DebugHub::OnLogMessageInternal(int severity, const char* file, int line,
                                    size_t message_start,
                                    const std::string& str) {
  DCHECK(this);
  DCHECK_EQ(MessageLoop::current(), message_loop_);

  if (log_message_callback_) {
    ScopedSetter scoped_setter(&is_logging_);
    log_message_callback_->value().Run(severity, file, line, message_start,
                                       str);
  }
}

void DebugHub::SetLogMessageCallback(const LogMessageCallbackArg& callback) {
  DCHECK(MessageLoop::current() == message_loop_);
  log_message_callback_.reset(
      new LogMessageCallbackArg::Reference(this, callback));
}

// TODO: This function should be modified to return an array of strings instead
// of a single space-separated string, once the bindings support return of a
// string array.
std::string DebugHub::GetConsoleValueNames() const {
  std::string ret = "";
  base::CValManager* cvm = base::CValManager::GetInstance();
  DCHECK(cvm);

  if (cvm) {
    std::set<std::string> names = cvm->GetOrderedCValNames();
    for (std::set<std::string>::const_iterator it = names.begin();
         it != names.end(); ++it) {
      ret += (*it);
      std::set<std::string>::const_iterator next = it;
      ++next;
      if (next != names.end()) {
        ret += " ";
      }
    }
  }
  return ret;
}

std::string DebugHub::GetConsoleValue(const std::string& name) const {
  std::string ret = "<undefined>";
  base::CValManager* cvm = base::CValManager::GetInstance();
  DCHECK(cvm);

  if (cvm) {
    base::optional<std::string> result = cvm->GetValueAsPrettyString(name);
    if (result) {
      return *result;
    }
  }
  return ret;
}

int DebugHub::GetDebugConsoleMode() const {
  return get_hud_mode_callback_.Run();
}

// TODO: This function should be modified to return an array of strings instead
// of a single space-separated string, once the bindings support return of a
// string array.
std::string DebugHub::GetCommandChannels() const {
  std::string result = "";
  base::ConsoleCommandManager* command_mananger =
      base::ConsoleCommandManager::GetInstance();
  DCHECK(command_mananger);

  if (command_mananger) {
    std::set<std::string> channels = command_mananger->GetRegisteredChannels();
    for (std::set<std::string>::const_iterator it = channels.begin();
         it != channels.end(); ++it) {
      result += (*it);
      std::set<std::string>::const_iterator next = it;
      ++next;
      if (next != channels.end()) {
        result += " ";
      }
    }
  }
  return result;
}

std::string DebugHub::GetCommandChannelShortHelp(
    const std::string& channel) const {
  std::string result = "<undefined>";
  base::ConsoleCommandManager* command_mananger =
      base::ConsoleCommandManager::GetInstance();
  DCHECK(command_mananger);
  if (command_mananger) {
    result = command_mananger->GetShortHelp(channel);
  }
  return result;
}

std::string DebugHub::GetCommandChannelLongHelp(
    const std::string& channel) const {
  std::string result = "<undefined>";
  base::ConsoleCommandManager* command_mananger =
      base::ConsoleCommandManager::GetInstance();
  DCHECK(command_mananger);
  if (command_mananger) {
    result = command_mananger->GetLongHelp(channel);
  }
  return result;
}

void DebugHub::SendCommand(const std::string& channel,
                           const std::string& message) {
  base::ConsoleCommandManager* console_command_manager =
      base::ConsoleCommandManager::GetInstance();
  DCHECK(console_command_manager);
  console_command_manager->HandleCommand(channel, message);
}

}  // namespace debug
}  // namespace cobalt

#endif  // ENABLE_DEBUG_CONSOLE
