/*
 * 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/javascript_debugger_component.h"

#include "base/bind.h"
#include "base/optional.h"
#include "base/stringprintf.h"
#include "base/values.h"

namespace cobalt {
namespace debug {

namespace {
// Command, parameter and event names as specified by the protocol:
// https://developer.chrome.com/devtools/docs/protocol/1.1/debugger

// Commands.
const char kDisable[] = "Debugger.disable";
const char kEnable[] = "Debugger.enable";
const char kGetScriptSource[] = "Debugger.getScriptSource";
const char kPause[] = "Debugger.pause";
const char kResume[] = "Debugger.resume";
const char kSetBreakpointByUrl[] = "Debugger.setBreakpointByUrl";
const char kSetPauseOnExceptions[] = "Debugger.setPauseOnExceptions";
const char kStepInto[] = "Debugger.stepInto";
const char kStepOut[] = "Debugger.stepOut";
const char kStepOver[] = "Debugger.stepOver";

// Parameter names.
const char kCallFrameId[] = "callFrameId";
const char kCallFrames[] = "callFrames";
const char kColumnNumber[] = "columnNumber";
const char kErrorLine[] = "errorLine";
const char kErrorMessage[] = "errorMessage";
const char kFunctionName[] = "functionName";
const char kLineNumber[] = "lineNumber";
const char kLocationColumnNumber[] = "location.columnNumber";
const char kLocationLineNumber[] = "location.lineNumber";
const char kLocationScriptId[] = "location.scriptId";
const char kObject[] = "object";
const char kReason[] = "reason";
const char kScopeChain[] = "scopeChain";
const char kScriptId[] = "scriptId";
const char kState[] = "state";
const char kThis[] = "this";
const char kType[] = "type";
const char kUrl[] = "url";

// Parameter values.
const char kDebugCommand[] = "debugCommand";

// Result parameters.
const char kBreakpointId[] = "result.breakpointId";
const char kLocations[] = "result.locations";
const char kScriptSource[] = "result.scriptSource";

// Events.
const char kPaused[] = "Debugger.paused";
const char kResumed[] = "Debugger.resumed";
const char kScriptFailedToParse[] = "Debugger.scriptFailedToParse";
const char kScriptParsed[] = "Debugger.scriptParsed";

// Construct a unique breakpoint id from url and source location.
// Use the same format as Chrome.
std::string BreakpointId(const std::string url, int line_number,
                         int column_number) {
  return base::StringPrintf("%s:%d:%d", url.c_str(), line_number,
                            column_number);
}

}  // namespace

JavaScriptDebuggerComponent::JavaScriptDebuggerComponent(
    ComponentConnector* connector)
    : connector_(connector), source_providers_deleter_(&source_providers_) {
  DCHECK(connector_);
  connector_->AddCommand(kDisable,
                         base::Bind(&JavaScriptDebuggerComponent::Disable,
                                    base::Unretained(this)));
  connector_->AddCommand(
      kEnable,
      base::Bind(&JavaScriptDebuggerComponent::Enable, base::Unretained(this)));
  connector_->AddCommand(
      kGetScriptSource,
      base::Bind(&JavaScriptDebuggerComponent::GetScriptSource,
                 base::Unretained(this)));
  connector_->AddCommand(kPause, base::Bind(&JavaScriptDebuggerComponent::Pause,
                                            base::Unretained(this)));
  connector_->AddCommand(
      kResume,
      base::Bind(&JavaScriptDebuggerComponent::Resume, base::Unretained(this)));
  connector_->AddCommand(kStepInto,
                         base::Bind(&JavaScriptDebuggerComponent::StepInto,
                                    base::Unretained(this)));
  connector_->AddCommand(
      kSetBreakpointByUrl,
      base::Bind(&JavaScriptDebuggerComponent::SetBreakpointByUrl,
                 base::Unretained(this)));
  connector_->AddCommand(
      kSetPauseOnExceptions,
      base::Bind(&JavaScriptDebuggerComponent::SetPauseOnExceptions,
                 base::Unretained(this)));
  connector_->AddCommand(kStepOut,
                         base::Bind(&JavaScriptDebuggerComponent::StepOut,
                                    base::Unretained(this)));
  connector_->AddCommand(kStepOver,
                         base::Bind(&JavaScriptDebuggerComponent::StepOver,
                                    base::Unretained(this)));
}

JavaScriptDebuggerComponent::~JavaScriptDebuggerComponent() {}

JSONObject JavaScriptDebuggerComponent::Enable(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  DCHECK(connector_->script_debugger());
  connector_->script_debugger()->Attach();
  return JSONObject(new base::DictionaryValue());
}

JSONObject JavaScriptDebuggerComponent::Disable(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  DCHECK(connector_->script_debugger());
  connector_->script_debugger()->Detach();
  return JSONObject(new base::DictionaryValue());
}

JSONObject JavaScriptDebuggerComponent::GetScriptSource(
    const JSONObject& params) {
  // Get the scriptId from the parameters.
  std::string script_id;
  bool got_script_id = params->GetString(kScriptId, &script_id);
  if (!got_script_id) {
    return connector_->ErrorResponse("No scriptId specified in parameters.");
  }

  // Find the source provider with a matching scriptId.
  SourceProviderMap::iterator it = source_providers_.find(script_id);
  if (it == source_providers_.end()) {
    return connector_->ErrorResponse(
        "No script found with specified scriptId.");
  }
  script::SourceProvider* source_provider = it->second;
  DCHECK(source_provider);

  // Build and return the result.
  JSONObject result(new base::DictionaryValue());
  result->SetString(kScriptSource, source_provider->GetScriptSource());
  return result.Pass();
}

JSONObject JavaScriptDebuggerComponent::Pause(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  DCHECK(connector_->script_debugger());
  connector_->script_debugger()->Pause();
  return JSONObject(new base::DictionaryValue());
}

JSONObject JavaScriptDebuggerComponent::Resume(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  DCHECK(connector_->script_debugger());
  DCHECK(connector_->server());
  connector_->script_debugger()->Resume();
  connector_->server()->SetPaused(false);
  return JSONObject(new base::DictionaryValue());
}

JSONObject JavaScriptDebuggerComponent::SetBreakpointByUrl(
    const JSONObject& params) {
  DCHECK(connector_->script_debugger());
  DCHECK(connector_->server());

  std::string url;
  bool got_url = params->GetString(kUrl, &url);
  if (!got_url) {
    return connector_->ErrorResponse("Breakpoint URL must be specified.");
  }

  // TODO: Should also handle setting of breakpoint by urlRegex

  int line_number;
  bool got_line_number = params->GetInteger(kLineNumber, &line_number);
  if (!got_line_number) {
    return connector_->ErrorResponse("Line number must be specified.");
  }
  // If no column number is specified, just default to 0.
  int column_number = 0;
  params->GetInteger(kColumnNumber, &column_number);

  // TODO: Should also handle condition and isAntibreakpoint.

  // Create a new logical breakpoint and store it in our map.
  const std::string breakpoint_id =
      BreakpointId(url, line_number, column_number);
  Breakpoint breakpoint(url, line_number, column_number);
  breakpoints_[breakpoint_id] = breakpoint;

  // Check the logical breakpoint against all currently loaded source providers
  // and get an array of matching breakpoint locations.
  std::vector<ScriptLocation> locations;
  ResolveBreakpoint(breakpoint, &locations);

  // Construct a result object from the logical breakpoint id and resolved
  // source locations.
  JSONObject result(new base::DictionaryValue());
  result->SetString(kBreakpointId, breakpoint_id);
  JSONList location_objects(new base::ListValue());
  for (std::vector<ScriptLocation>::const_iterator it = locations.begin();
       it != locations.end(); ++it) {
    JSONObject location(new base::DictionaryValue());
    location->SetString(kScriptId, it->script_id);
    location->SetInteger(kLineNumber, it->line_number);
    location->SetInteger(kColumnNumber, it->column_number);
    location_objects->Append(location.release());
  }
  result->Set(kLocations, location_objects.release());
  return result.Pass();
}

JSONObject JavaScriptDebuggerComponent::SetPauseOnExceptions(
    const JSONObject& params) {
  DCHECK(connector_->script_debugger());
  DCHECK(connector_->server());

  std::string state;
  DCHECK(params->GetString(kState, &state));
  if (state == "all") {
    connector_->script_debugger()->SetPauseOnExceptions(
        script::ScriptDebugger::kAll);
  } else if (state == "none") {
    connector_->script_debugger()->SetPauseOnExceptions(
        script::ScriptDebugger::kNone);
  } else if (state == "uncaught") {
    connector_->script_debugger()->SetPauseOnExceptions(
        script::ScriptDebugger::kUncaught);
  } else {
    NOTREACHED();
  }
  return JSONObject(new base::DictionaryValue());
}

JSONObject JavaScriptDebuggerComponent::StepInto(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  DCHECK(connector_->script_debugger());
  DCHECK(connector_->server());
  connector_->script_debugger()->StepInto();
  connector_->server()->SetPaused(false);
  return JSONObject(new base::DictionaryValue());
}

JSONObject JavaScriptDebuggerComponent::StepOut(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  DCHECK(connector_->script_debugger());
  DCHECK(connector_->server());
  connector_->script_debugger()->StepOut();
  connector_->server()->SetPaused(false);
  return JSONObject(new base::DictionaryValue());
}

JSONObject JavaScriptDebuggerComponent::StepOver(const JSONObject& params) {
  UNREFERENCED_PARAMETER(params);
  DCHECK(connector_->script_debugger());
  DCHECK(connector_->server());
  connector_->script_debugger()->StepOver();
  connector_->server()->SetPaused(false);
  return JSONObject(new base::DictionaryValue());
}

void JavaScriptDebuggerComponent::OnScriptDebuggerDetach(
    const std::string& reason) {
  DLOG(INFO) << "JavaScript debugger detached: " << reason;
}

void JavaScriptDebuggerComponent::OnScriptDebuggerPause(
    scoped_ptr<script::CallFrame> call_frame) {
  // Notify the clients we're about to pause.
  SendPausedEvent(call_frame.Pass());

  // Tell the debug server to enter paused state - block this thread.
  DCHECK(connector_->server());
  connector_->server()->SetPaused(true);

  // Notify the clients we've resumed.
  SendResumedEvent();
}

void JavaScriptDebuggerComponent::OnScriptFailedToParse(
    scoped_ptr<script::SourceProvider> source_provider) {
  DCHECK(source_provider);
  HandleScriptEvent(kScriptFailedToParse, source_provider.Pass());
}

void JavaScriptDebuggerComponent::OnScriptParsed(
    scoped_ptr<script::SourceProvider> source_provider) {
  DCHECK(source_provider);
  HandleScriptEvent(kScriptParsed, source_provider.Pass());
}

JSONObject JavaScriptDebuggerComponent::CreateCallFrameData(
    const scoped_ptr<script::CallFrame>& call_frame) {
  DCHECK(call_frame);

  // Create the JSON object and add the data for this call frame.
  JSONObject call_frame_data(new base::DictionaryValue());
  call_frame_data->SetString(kCallFrameId, call_frame->GetCallFrameId());
  call_frame_data->SetString(kFunctionName, call_frame->GetFunctionName());

  // Offset the line number according to the start line of the source.
  const std::string script_id = call_frame->GetScriptId();
  int line_number = call_frame->GetLineNumber();
  DCHECK(source_providers_[script_id]);
  base::optional<int> start_line = source_providers_[script_id]->GetStartLine();
  line_number -= start_line.value_or(1);

  // Add the location data.
  call_frame_data->SetString(kLocationScriptId, script_id);
  call_frame_data->SetInteger(kLocationLineNumber, line_number);
  base::optional<int> column_number = call_frame->GetColumnNumber();
  if (column_number) {
    call_frame_data->SetInteger(kLocationColumnNumber, column_number.value());
  }

  // Add the scope chain data.
  JSONList scope_chain_data(CreateScopeChainData(call_frame->GetScopeChain()));
  call_frame_data->Set(kScopeChain, scope_chain_data.release());

  // Add the "this" object data.
  const script::OpaqueHandleHolder* this_object = call_frame->GetThis();
  if (this_object) {
    JSONObject this_object_data(connector_->CreateRemoteObject(this_object));
    call_frame_data->Set(kThis, this_object_data.release());
  }

  return call_frame_data.Pass();
}

JSONList JavaScriptDebuggerComponent::CreateCallStackData(
    scoped_ptr<script::CallFrame> call_frame) {
  JSONList call_frame_list(new base::ListValue());

  // Consume the scoped CallFrame objects as we iterate over them.
  while (call_frame) {
    JSONObject call_frame_data(CreateCallFrameData(call_frame));
    DCHECK(call_frame_data);
    call_frame_list->Append(call_frame_data.release());
    scoped_ptr<script::CallFrame> next_call_frame(call_frame->GetCaller());
    call_frame = next_call_frame.Pass();
  }

  return call_frame_list.Pass();
}

JSONObject JavaScriptDebuggerComponent::CreateScopeData(
    const scoped_ptr<script::Scope>& scope) {
  DCHECK(scope);
  const script::OpaqueHandleHolder* scope_object = scope->GetObject();
  JSONObject scope_data(new base::DictionaryValue());
  scope_data->Set(kObject,
                  connector_->CreateRemoteObject(scope_object).release());
  scope_data->SetString(kType, script::Scope::TypeToString(scope->GetType()));
  return scope_data.Pass();
}

JSONList JavaScriptDebuggerComponent::CreateScopeChainData(
    scoped_ptr<script::Scope> scope) {
  JSONList scope_chain_list(new base::ListValue());

  // Consume the scoped Scope objects as we iterate over them.
  while (scope) {
    JSONObject scope_data(CreateScopeData(scope));
    DCHECK(scope_data);
    scope_chain_list->Append(scope_data.release());
    scoped_ptr<script::Scope> next_scope(scope->GetNext());
    scope = next_scope.Pass();
  }

  return scope_chain_list.Pass();
}

void JavaScriptDebuggerComponent::HandleScriptEvent(
    const std::string& method,
    scoped_ptr<script::SourceProvider> source_provider) {
  DCHECK(source_provider);

  // Send the event notification to the debugger clients.
  JSONObject params(new base::DictionaryValue());
  params->SetString(kScriptId, source_provider->GetScriptId());
  params->SetString(kUrl, source_provider->GetUrl());
  base::optional<int> error_line = source_provider->GetErrorLine();
  if (error_line) {
    DCHECK_EQ(method, kScriptFailedToParse);
    params->SetInteger(kErrorLine, error_line.value());
  }
  base::optional<std::string> error_message =
      source_provider->GetErrorMessage();
  if (error_message) {
    DCHECK_EQ(method, kScriptFailedToParse);
    params->SetString(kErrorMessage, error_message.value());
  }
  connector_->SendEvent(method, params.Pass());

  // Store the raw pointer to the source provider in the map.
  // The values in the map will be deleted on destruction by
  // |source_providers_deleter_|.
  const std::string script_id = source_provider->GetScriptId();
  SourceProviderMap::iterator it = source_providers_.find(script_id);
  if (it != source_providers_.end()) {
    delete it->second;
  }
  source_providers_[script_id] = source_provider.release();
}

void JavaScriptDebuggerComponent::ResolveBreakpoint(
    const Breakpoint& breakpoint, std::vector<ScriptLocation>* locations) {
  for (SourceProviderMap::iterator it = source_providers_.begin();
       it != source_providers_.end(); ++it) {
    script::SourceProvider* script = it->second;
    if (script->GetUrl() == breakpoint.url) {
      connector_->script_debugger()->SetBreakpoint(
          script->GetScriptId(),
          breakpoint.line_number + script->GetStartLine().value_or(1),
          breakpoint.column_number);
      locations->push_back(ScriptLocation(script->GetScriptId(),
                                          breakpoint.line_number,
                                          breakpoint.column_number));
    }
  }
}

void JavaScriptDebuggerComponent::SendPausedEvent(
    scoped_ptr<script::CallFrame> call_frame) {
  std::string event_method = kPaused;
  JSONObject event_params(new base::DictionaryValue());
  JSONList call_stack_data(CreateCallStackData(call_frame.Pass()));
  DCHECK(call_stack_data);
  event_params->Set(kCallFrames, call_stack_data.release());
  event_params->SetString(kReason, kDebugCommand);
  connector_->SendEvent(event_method, event_params);
}

void JavaScriptDebuggerComponent::SendResumedEvent() {
  // Send the event to the clients. No parameters.
  std::string event_method = kResumed;
  scoped_ptr<base::DictionaryValue> event_params(new base::DictionaryValue());
  connector_->SendEvent(event_method, event_params);
}

}  // namespace debug
}  // namespace cobalt
