package com.jscape.util.fsm;

import java.util.LinkedList;
import java.util.Queue;

/**
 * @author Alex Usun
 */
public abstract class AbstractEventSource
        implements EventSource {

    protected final Queue<Event> innerEvents;

    protected AbstractEventSource() {
        this.innerEvents = new LinkedList<Event>();
    }

    public Event nextEvent()
            throws FSMException {
        try {
            Event event = nextInnerEvent();
            return event != null ? event : nextExternalEvent();
        } catch (Exception e) {
            throw FSMException.wrap(e);
        }
    }

    public void postEvent(Event event)
            throws FSMException {
        boolean eventPosted = this.innerEvents.offer(event);
        assertEventPosted(eventPosted);
    }

    @Override
    public String toString() {
        return "AbstractEventSource {"
                + "innerEvents=" + this.innerEvents
                + '}';
    }

    private Event nextInnerEvent() {
        return this.innerEvents.poll();
    }

    protected abstract Event nextExternalEvent()
            throws Exception;

    private void assertEventPosted(boolean eventPosted)
            throws FSMException {
        if (!eventPosted) {
            throw new FSMException("Error posting event to the source.");
        }
    }
}
