package lc.mecha.event;

import lc.mecha.log.MechaLogger;
import lc.mecha.log.MechaLoggerFactory;

import java.util.Set;

/**
 * This classes provides base eventing mechanics for the <code>EO</code> family of classes.
 *
 * @author Alex Leigh
 * @since mk11 (ZERO CONTRAST)
 */
public class EventBaseObject implements EventTarget {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(EventTarget.class);
    private EventListenerBinder listeners;
    private EventBaseObject parent;

    private void allocateStorage() {
        if (listeners == null) listeners = new EventListenerBinder();
    }

    @Override
    public void addListener(String eventType, EventListener listener) {
        allocateStorage();
        listeners.addEventListener(eventType, listener);
    }

    /**
     * Returns a set of listeners on this target for the given event type. If no listeners are configured,
     * <code>null</code> or a empty set may be returned.
     */
    public Set<EventListener> getListeners(String eventType) {
        return listeners == null ? null : listeners.getSet(eventType);
    }


    /**
     * Return the parent for this EO, if it has been assigned to a loop.
     *
     * @since mk11 (ZERO CONTRAST)
     */
    public EventBaseObject getParent() {
        return parent;
    }

    /**
     * Set the parent loop for this EO. If <code>parent</code> is not null, then the EO must not already have a parent.
     * To clear the parent status, set it to <code>null</code> first. This mechanic is intended to reduce bugs from
     * assigning the same EO to multiple loops.
     *
     * @since mk11 (ZERO CONTRAST)
     */
    public void setParent(EventBaseObject parent) {
        if (parent != null && this.parent != null) logger.warn("EO already has a parent.");
        this.parent = parent;
    }

    @Override
    public String toString() {
        return "EventBaseObject{" +
                "listeners=" + listeners +
                ", parent=" + parent +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        EventBaseObject that = (EventBaseObject) o;

        if (listeners != null ? !listeners.equals(that.listeners) : that.listeners != null) return false;
        return parent != null ? parent.equals(that.parent) : that.parent == null;
    }

    @Override
    public int hashCode() {
        int result = listeners != null ? listeners.hashCode() : 0;
        result = 31 * result + (parent != null ? parent.hashCode() : 0);
        return result;
    }
}