#pragma once

#include <map>
#include <memory>
#include <string>
#include "api/devtools_data_channel.h"
#include "footstone/worker_manager.h"
#include "module/domain/base_domain.h"
#include "module/inspect_event.h"

namespace flexui::devtools {
class BaseDomain;

/**
 * @brief domain dispatch, including two parts protocol, 1. chrome debugging protocol, 2. self define protocol start
 * with TDF_
 */
class DomainDispatch : public std::enable_shared_from_this<DomainDispatch> {
 public:
  DomainDispatch(std::shared_ptr<DataChannel> data_channel, std::shared_ptr<footstone::WorkerManager> worker_manager)
      : data_channel_(data_channel), worker_manager_(worker_manager) {}

  inline std::shared_ptr<DataChannel> GetDataChannel() { return data_channel_; }

  inline std::shared_ptr<footstone::WorkerManager> GetWorkerManager() { return worker_manager_; }

  /**
   * @brief register domain handler which can handle Domain.Method
   */
  void RegisterDomainHandler(const std::shared_ptr<BaseDomain>& domain);

  /**
   * @brief clear domain register handler
   */
  void ClearDomainHandler();

  /**
   * @brief receive msg from frontend
   * @param data passing from frontend
   */
  bool ReceiveDataFromFrontend(const std::string& data);

  void DispatchToVm(const std::string& data);

  /**
   * @brief response to frontend after call ReceiveDataFromFrontend
   * @param result response
   */
  void SendDataToFrontend(int32_t id, bool is_success, const std::string& result);

  /**
   * @brief send event to frontend if you want
   * @param event params that should be implemented ToJsonString
   */
  void SendEventToFrontend(InspectEvent&& event);

  /**
   * @brief register domain handler relative with JS engine
   */
  void RegisterJSDebuggerDomainListener();

  void SetResponseHandler(std::function<void(const std::string)> rsp_handler) { rsp_handler_ = rsp_handler; }

  /**
   * @brief register domain handler default
   */
  void RegisterDefaultDomainListener();

 private:
  static std::string AdaptProtocolName(std::string domain_name);

  std::map<std::string, std::shared_ptr<BaseDomain>> domain_register_map_;
  std::function<void(const std::string)> rsp_handler_;
  std::shared_ptr<DataChannel> data_channel_;
  std::shared_ptr<footstone::WorkerManager> worker_manager_;
};

}  // namespace flexui::devtools