#pragma once

#include "event.hpp"
#include "vertex_engine/utils/using.hpp"

namespace VE
{
  struct event_manager : public hack::patterns::singleton<event_manager>
  {
    template<typename T>
    std::string connect(T* obj, void (T::*method)(event&)) 
    {
      std::string key = hack::security::generate_uuid();
      m_funcs[key] = std::bind(method, obj, std::placeholders::_1);
      return key;
    }

    void disconnect(std::string key) 
    {
      auto it = m_funcs.find(key);
      if (it != m_funcs.end())
        m_funcs.erase(it);
    }

    void emit(event& e)
    {
      if (m_funcs.size() == 0)
      {
        hack::warn()("emit funs size is empty", m_funcs.size());
        return;
      }
      else if (!e.m_event_log_message.empty())
      {
        hack::log()("EVENT LOG:", e.m_event_id, e.m_event_log_message);
      }

      try
      {
        for(auto [key, f] : m_funcs) 
        {
          m_funcs[key](e);
          if (!e.m_event_log_message.empty()) 
            hack::warn()("EVENT KEY:", key, e.m_event_log_message, e.m_event_id);
        }
      }
      catch(const std::exception& ex)
      {
        hack::error()(ex.what());
        hack::log()("size funcs", m_funcs.size());
      }
      catch(...)
      {
        hack::error()("ooops...");
      }
    }

    std::map<std::string, event_fn<event>> m_funcs;
  };
}
