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

#include "cobalt/debug/component_connector.h"

#include "base/logging.h"
#include "base/values.h"

namespace cobalt {
namespace debug {

namespace {
// Error response message field.
const char kErrorMessage[] = "error.message";
}  // namespace

ComponentConnector::ComponentConnector(DebugServer* server,
                                       script::ScriptDebugger* script_debugger)
    : server_(server), script_debugger_(script_debugger) {}

ComponentConnector::~ComponentConnector() {
  // Remove all the commands added by this component.
  for (std::vector<std::string>::const_iterator it = command_methods_.begin();
       it != command_methods_.end(); ++it) {
    RemoveCommand(*it);
  }
}

void ComponentConnector::AddCommand(const std::string& method,
                                    const DebugServer::Command& callback) {
  if (server_) {
    server_->AddCommand(method, callback);

    // Store the command methods added by this component, so we can remove on
    // destruction.
    command_methods_.push_back(method);
  }
}

void ComponentConnector::RemoveCommand(const std::string& method) {
  if (server_) {
    server_->RemoveCommand(method);
  }
}

JSONObject ComponentConnector::RunScriptCommand(const std::string& command,
                                                const JSONObject& params) {
  if (server_) {
    script::ScriptDebugger::ScopedPauseOnExceptionsState no_pause(
        script_debugger_, script::ScriptDebugger::kNone);
    return server_->RunScriptCommand(command, params);
  } else {
    return ErrorResponse("Not attached to debug server");
  }
}

bool ComponentConnector::RunScriptFile(const std::string& filename) {
  if (server_) {
    script::ScriptDebugger::ScopedPauseOnExceptionsState no_pause(
        script_debugger_, script::ScriptDebugger::kNone);
    return server_->RunScriptFile(filename);
  } else {
    return ErrorResponse("Not attached to debug server");
  }
}

JSONObject ComponentConnector::CreateRemoteObject(
    const script::OpaqueHandleHolder* object) {
  // Parameter object for the JavaScript function call uses default values.
  JSONObject params(new base::DictionaryValue());

  // This will execute a JavaScript function to create a Runtime.Remote object
  // that describes the opaque JavaScript object.
  DCHECK(server_);
  base::optional<std::string> json_result =
      server()->CreateRemoteObject(object, JSONStringify(params));

  // Parse the serialized JSON result.
  if (json_result) {
    return JSONParse(json_result.value());
  } else {
    DLOG(WARNING) << "Could not create Runtime.RemoteObject";
    return JSONObject(new base::DictionaryValue());
  }
}

void ComponentConnector::SendEvent(const std::string& method,
                                   const JSONObject& params) {
  if (server_) {
    server_->OnEvent(method, params);
  }
}

// static
JSONObject ComponentConnector::ErrorResponse(const std::string& error_message) {
  JSONObject error_response(new base::DictionaryValue());
  error_response->SetString(kErrorMessage, error_message);
  return error_response.Pass();
}

}  // namespace debug
}  // namespace cobalt
