// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "libcef/browser/devtools/devtools_controller.h"

#include "libcef/browser/devtools/devtools_util.h"
#include "libcef/browser/thread_util.h"

#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "content/public/browser/devtools_agent_host.h"

CefDevToolsController::CefDevToolsController(
    content::WebContents* inspected_contents)
    : inspected_contents_(inspected_contents), weak_ptr_factory_(this) {
  DCHECK(inspected_contents_);
}

CefDevToolsController::~CefDevToolsController() {
  if (agent_host_) {
    agent_host_->DetachClient(this);
    AgentHostClosed(agent_host_.get());
  }

  for (auto& observer : observers_) {
    observer.OnDevToolsControllerDestroyed();
  }
}

bool CefDevToolsController::SendDevToolsMessage(
    const base::StringPiece& message) {
  CEF_REQUIRE_UIT();
  if (!EnsureAgentHost())
    return false;

  agent_host_->DispatchProtocolMessage(
      this, base::as_bytes(base::make_span(message)));
  return true;
}

int CefDevToolsController::ExecuteDevToolsMethod(
    int suggested_message_id,
    const std::string& method,
    const base::DictionaryValue* params) {
  CEF_REQUIRE_UIT();
  if (!EnsureAgentHost())
    return 0;

  // Message IDs must always be increasing and unique.
  int message_id = suggested_message_id;
  if (message_id < next_message_id_)
    message_id = next_message_id_++;
  else
    next_message_id_ = message_id + 1;

  base::DictionaryValue message;
  message.SetIntKey("id", message_id);
  message.SetStringKey("method", method);
  if (params)
    message.SetKey("params", params->Clone());

  std::string protocol_message;
  if (!base::JSONWriter::Write(message, &protocol_message))
    return 0;

  agent_host_->DispatchProtocolMessage(
      this, base::as_bytes(base::make_span(protocol_message)));
  return message_id;
}

void CefDevToolsController::AgentHostClosed(
    content::DevToolsAgentHost* agent_host) {
  DCHECK(agent_host == agent_host_.get());
  agent_host_ = nullptr;
  for (auto& observer : observers_) {
    observer.OnDevToolsAgentDetached();
  }
}

void CefDevToolsController::AddObserver(Observer* observer) {
  CEF_REQUIRE_UIT();
  observers_.AddObserver(observer);
}

void CefDevToolsController::RemoveObserver(Observer* observer) {
  CEF_REQUIRE_UIT();
  observers_.RemoveObserver(observer);
}

void CefDevToolsController::DispatchProtocolMessage(
    content::DevToolsAgentHost* agent_host,
    base::span<const uint8_t> message) {
  if (!observers_.might_have_observers())
    return;

  base::StringPiece str_message(reinterpret_cast<const char*>(message.data()),
                                message.size());
  if (!devtools_util::ProtocolParser::IsValidMessage(str_message)) {
    LOG(WARNING) << "Invalid message: " << str_message.substr(0, 100);
    return;
  }

  devtools_util::ProtocolParser parser;

  for (auto& observer : observers_) {
    if (observer.OnDevToolsMessage(str_message)) {
      continue;
    }

    // Only perform parsing a single time.
    if (parser.Initialize(str_message) && parser.IsFailure()) {
      LOG(WARNING) << "Failed to parse message: " << str_message.substr(0, 100);
    }

    if (parser.IsEvent()) {
      observer.OnDevToolsEvent(parser.method_, parser.params_);
    } else if (parser.IsResult()) {
      observer.OnDevToolsMethodResult(parser.message_id_, parser.success_,
                                      parser.params_);
    }
  }
}

bool CefDevToolsController::EnsureAgentHost() {
  if (!agent_host_) {
    agent_host_ =
        content::DevToolsAgentHost::GetOrCreateFor(inspected_contents_);
    if (agent_host_) {
      agent_host_->AttachClient(this);
      for (auto& observer : observers_) {
        observer.OnDevToolsAgentAttached();
      }
    }
  }
  return !!agent_host_;
}
