#include <core/event/event_bus.h>

namespace extra2d::event {

ListenerContainer::~ListenerContainer() {
    ListenerEntry* curr = listenerList_;
    while (curr) {
        ListenerEntry* next = curr->next;
        delete curr;
        curr = next;
    }
    
    curr = listenersToAdd_;
    while (curr) {
        ListenerEntry* next = curr->next;
        delete curr;
        curr = next;
    }
    
    for (auto* entry : listenersToRemove_) {
        delete entry;
    }
}

void ListenerContainer::addListener(ListenerBase* listener) {
    if (!listener || !listener->entry_) return;
    
    if (broadcasting_ > 0) {
        listener->entry_->next = listenersToAdd_;
        listenersToAdd_ = listener->entry_;
    } else {
        listener->entry_->next = listenerList_;
        listener->entry_->prev = nullptr;
        if (listenerList_) {
            listenerList_->prev = listener->entry_;
        }
        listenerList_ = listener->entry_;
    }
}

void ListenerContainer::removeListener(ListenerBase* listener) {
    if (!listener || !listener->entry_) return;
    
    if (broadcasting_ > 0) {
        listenersToRemove_.push_back(listener->entry_);
        listener->entry_->listener = nullptr;
    } else {
        if (listener->entry_->prev) {
            listener->entry_->prev->next = listener->entry_->next;
        } else {
            listenerList_ = listener->entry_->next;
        }
        
        if (listener->entry_->next) {
            listener->entry_->next->prev = listener->entry_->prev;
        }
        
        delete listener->entry_;
        listener->entry_ = nullptr;
    }
}

void ListenerContainer::processPendingListeners() {
    while (listenersToAdd_) {
        ListenerEntry* entry = listenersToAdd_;
        listenersToAdd_ = entry->next;
        
        entry->next = listenerList_;
        entry->prev = nullptr;
        if (listenerList_) {
            listenerList_->prev = entry;
        }
        listenerList_ = entry;
    }
    
    for (auto* entry : listenersToRemove_) {
        if (entry->prev) {
            entry->prev->next = entry->next;
        } else {
            listenerList_ = entry->next;
        }
        
        if (entry->next) {
            entry->next->prev = entry->prev;
        }
        
        delete entry;
    }
    listenersToRemove_.clear();
}

bool ListenerContainer::hasPendingListeners() const {
    return listenersToAdd_ != nullptr || !listenersToRemove_.empty();
}

} // namespace extra2d::event
