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

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

#include "content/public/browser/web_contents.h"

namespace {

// May be created on any thread but will be destroyed on the UI thread.
class CefDevToolsRegistrationImpl : public CefRegistration,
                                    public CefDevToolsController::Observer {
 public:
  explicit CefDevToolsRegistrationImpl(
      CefRefPtr<CefDevToolsMessageObserver> observer)
      : observer_(observer) {
    DCHECK(observer_);
  }

  ~CefDevToolsRegistrationImpl() override {
    CEF_REQUIRE_UIT();

    // May be null if OnDevToolsControllerDestroyed was called.
    if (!controller_)
      return;

    controller_->RemoveObserver(this);
  }

  void Initialize(CefBrowserHostImpl* browser,
                  base::WeakPtr<CefDevToolsController> controller) {
    CEF_REQUIRE_UIT();
    DCHECK(browser && controller);
    DCHECK(!browser_ && !controller_);
    browser_ = browser;
    controller_ = controller;

    controller_->AddObserver(this);
  }

 private:
  // CefDevToolsController::Observer methods:
  bool OnDevToolsMessage(const base::StringPiece& message) override {
    CEF_REQUIRE_UIT();
    return observer_->OnDevToolsMessage(browser_, message.data(),
                                        message.size());
  }

  void OnDevToolsMethodResult(int message_id,
                              bool success,
                              const base::StringPiece& result) override {
    CEF_REQUIRE_UIT();
    observer_->OnDevToolsMethodResult(browser_, message_id, success,
                                      result.data(), result.size());
  }

  void OnDevToolsEvent(const base::StringPiece& method,
                       const base::StringPiece& params) override {
    CEF_REQUIRE_UIT();
    observer_->OnDevToolsEvent(browser_, method.as_string(), params.data(),
                               params.size());
  }

  void OnDevToolsAgentAttached() override {
    CEF_REQUIRE_UIT();
    observer_->OnDevToolsAgentAttached(browser_);
  }

  void OnDevToolsAgentDetached() override {
    CEF_REQUIRE_UIT();
    observer_->OnDevToolsAgentDetached(browser_);
  }

  void OnDevToolsControllerDestroyed() override {
    CEF_REQUIRE_UIT();
    browser_ = nullptr;
    controller_.reset();
  }

  CefRefPtr<CefDevToolsMessageObserver> observer_;

  CefBrowserHostImpl* browser_ = nullptr;
  base::WeakPtr<CefDevToolsController> controller_;

  IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefDevToolsRegistrationImpl);
  DISALLOW_COPY_AND_ASSIGN(CefDevToolsRegistrationImpl);
};

}  // namespace

CefDevToolsManager::CefDevToolsManager(CefBrowserHostImpl* inspected_browser)
    : inspected_browser_(inspected_browser), weak_ptr_factory_(this) {
  CEF_REQUIRE_UIT();
}

CefDevToolsManager::~CefDevToolsManager() {
  CEF_REQUIRE_UIT();
}

void CefDevToolsManager::ShowDevTools(const CefWindowInfo& windowInfo,
                                      CefRefPtr<CefClient> client,
                                      const CefBrowserSettings& settings,
                                      const CefPoint& inspect_element_at) {
  CEF_REQUIRE_UIT();
  if (devtools_frontend_) {
    if (!inspect_element_at.IsEmpty()) {
      devtools_frontend_->InspectElementAt(inspect_element_at.x,
                                           inspect_element_at.y);
    }
    devtools_frontend_->Focus();
    return;
  }

  devtools_frontend_ = CefDevToolsFrontend::Show(
      inspected_browser_, windowInfo, client, settings, inspect_element_at,
      base::BindOnce(&CefDevToolsManager::OnFrontEndDestroyed,
                     weak_ptr_factory_.GetWeakPtr()));
}

void CefDevToolsManager::CloseDevTools() {
  CEF_REQUIRE_UIT();
  if (!devtools_frontend_)
    return;
  devtools_frontend_->Close();
}

bool CefDevToolsManager::HasDevTools() {
  CEF_REQUIRE_UIT();
  return !!devtools_frontend_;
}

bool CefDevToolsManager::SendDevToolsMessage(const void* message,
                                             size_t message_size) {
  CEF_REQUIRE_UIT();
  if (!message || message_size == 0)
    return false;

  if (!EnsureController())
    return false;

  return devtools_controller_->SendDevToolsMessage(
      base::StringPiece(static_cast<const char*>(message), message_size));
}

int CefDevToolsManager::ExecuteDevToolsMethod(
    int message_id,
    const CefString& method,
    CefRefPtr<CefDictionaryValue> params) {
  CEF_REQUIRE_UIT();
  if (method.empty())
    return 0;

  if (!EnsureController())
    return 0;

  if (params && params->IsValid()) {
    CefDictionaryValueImpl* impl =
        static_cast<CefDictionaryValueImpl*>(params.get());
    CefValueController::AutoLock lock_scope(impl->controller());
    return devtools_controller_->ExecuteDevToolsMethod(message_id, method,
                                                       impl->GetValueUnsafe());
  } else {
    return devtools_controller_->ExecuteDevToolsMethod(message_id, method,
                                                       nullptr);
  }
}

// static
CefRefPtr<CefRegistration> CefDevToolsManager::CreateRegistration(
    CefRefPtr<CefDevToolsMessageObserver> observer) {
  DCHECK(observer);
  return new CefDevToolsRegistrationImpl(observer);
}

void CefDevToolsManager::InitializeRegistrationOnUIThread(
    CefRefPtr<CefRegistration> registration) {
  CEF_REQUIRE_UIT();

  if (!EnsureController())
    return;

  static_cast<CefDevToolsRegistrationImpl*>(registration.get())
      ->Initialize(inspected_browser_, devtools_controller_->GetWeakPtr());
}

void CefDevToolsManager::OnFrontEndDestroyed() {
  devtools_frontend_ = nullptr;
}

bool CefDevToolsManager::EnsureController() {
  if (!devtools_controller_) {
    devtools_controller_.reset(
        new CefDevToolsController(inspected_browser_->web_contents()));
  }
  return true;
}
