/*
* Author:          Patrick-Christopher Mattulat
* Co-Author:       Claude Sonnet 4.6 (LLM)
* Company:         Lynar Studios
* E-Mail:          webmaster@lynarstudios.com
* Created:         2024-05-16
* Changed:         2026-06-23
*
* */

#include <ls-std/core/evaluator/NullPointerEvaluator.hpp>
#include <ls-std/event/EventListener.hpp>
#include <ls-std/event/EventManager.hpp>

using ls::standard::core::Class;
using ls::standard::core::NullPointerEvaluator;
using ls::standard::event::Event;
using ls::standard::event::EventListener;
using ls::standard::event::EventManager;
using ls::standard::event::EventParameter;
using ls::standard::event::type::event_action;
using ls::standard::event::type::listener_id;
using ::std::dynamic_pointer_cast;
using ::std::shared_ptr;

EventListener::EventListener() : Class("EventListener")
{}

EventListener::~EventListener() noexcept = default;

listener_id EventListener::getId() const
{
  return this->id;
}

void EventListener::setId(const listener_id _id)
{
  this->id = _id;
}

void EventListener::setParameter(const EventParameter &_parameter)
{
  this->parameter = _parameter;
}

bool EventListener::subscribe(const Event &_event, const event_action &_action)
{
  NullPointerEvaluator(_event.getManager(), "no event manager is provided for " + _event.getClassName()).evaluate();
  this->_requestListenerId(_event.getManager());

  return this->_subscribe(_event, _action);
}

bool EventListener::unsubscribe(const Event &_event)
{
  NullPointerEvaluator(_event.getManager(), "no event manager is provided for " + _event.getClassName()).evaluate();
  return this->_unsubscribe(_event);
}

void EventListener::_requestListenerId(const shared_ptr<Class> &_manager)
{
  const shared_ptr<EventManager> manager = dynamic_pointer_cast<EventManager>(_manager);

  if (this->id == 0)
  {
    this->setId(manager->requestListenerId());
  }
}

bool EventListener::_subscribe(const Event &_event, const event_action &_action)
{
  bool subscribed{};

  if (const shared_ptr<EventManager> manager = dynamic_pointer_cast<EventManager>(_event.getManager()); !manager->holdsListenerForEvent(this->id, _event))
  {
    manager->subscribeListenerForEvent(shared_from_this(), _event, _action);
    subscribed = manager->holdsListenerForEvent(this->id, _event);
  }

  return subscribed;
}

bool EventListener::_unsubscribe(const Event &_event)
{
  bool unsubscribed{};

  if (const shared_ptr<EventManager> manager = dynamic_pointer_cast<EventManager>(_event.getManager()); manager->holdsListenerForEvent(this->id, _event))
  {
    manager->unsubscribeListenerForEvent(shared_from_this(), _event);
    unsubscribed = !manager->holdsListenerForEvent(this->id, _event);
  }

  return unsubscribed;
}
