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