package rx.android.eventbus;

import rx.functions.Action1;
import rx.functions.Actions;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * A descriptor type representing an event queue. Use {@link Builder} to obtain
 * instances of this class:
 * <pre>
 *     Queue<MyEventType> queue = Queue.of(MyEventType.class).get();
 * </pre>
 * There are several ways to modify the queue behavior:
 * <h3>Replaying queues</h3>
 * If by the time a subscriber subscribes to a queue you want the last event the queue has seen to be
 * emitted immediately to the subscriber, you can create a replaying queue, optionally specifying an event
 * instance that is emitted in case there were zero events prior to subscribing:
 * <pre>
 *     Queue<MyEventType> queue1 = Queue.of(MyEventType.class).replay().get();
 *     Queue<MyEventType> queue2 = Queue.of(MyEventType.class).replay(MyEventType.DEFAULT_EVENT).get();
 * </pre>
 * <h3>Custom error hooks</h3>
 * Event queues do not process <code>onError</code> notifications (or completed events) as this would lead
 * to the queue being closed and entering a terminal state. However, you can be notified of error by
 * providing a custom hook:
 * <pre>
 *     Queue<MyEventType> queue = Queue.of(MyEventType.class).onError(myErrorHook).get();
 * </pre>
 * A convenient way to group event queues together is in a sealed container class:
 * <pre>
 *     public final class EventQueue {
 *         public static final Queue<Event1> EVENT1 = Queue.of(Event1.class).get();
 *         public static final Queue<Event2> EVENT2 = Queue.of(Event2.class).get();
 *         ...
 *     }
 * </pre>
 */
public final class EventQueue<T> {

    private static final AtomicInteger runningId = new AtomicInteger();

    public final String name;
    public final Class<T> eventType;

    final int id;
    final boolean replayLast;
    final T defaultEvent;
    final Action1<Throwable> onError;

    public static final class Builder<T> {
        private String name;
        private final Class<T> eventType;
        private boolean replayLast;
        private T defaultEvent;
        private Action1<Throwable> onError = Actions.empty();

        Builder(Class<T> eventType) {
            this.eventType = eventType;
        }

        public Builder<T> name(String name) {
            this.name = name;
            return this;
        }

        public Builder<T> replay() {
            this.replayLast = true;
            return this;
        }

        public Builder<T> replay(T defaultEvent) {
            this.replayLast = true;
            this.defaultEvent = defaultEvent;
            return this;
        }

        public Builder<T> onError(Action1<Throwable> onError) {
            this.onError = onError;
            return this;
        }

        public EventQueue<T> get() {
            if (name == null) {
                name = eventType.getSimpleName() + "Queue";
            }
            return new EventQueue<T>(name, eventType, replayLast, defaultEvent, onError);
        }
    }

    public static <T> Builder<T> build(Class<T> eventType) {
        return new Builder<T>(eventType);
    }

    EventQueue(String name, Class<T> eventType, boolean replayLast, T defaultEvent, Action1<Throwable> onError) {
        this.name = name;
        this.eventType = eventType;
        this.replayLast = replayLast;
        this.defaultEvent = defaultEvent;
        this.onError = onError;
        this.id = runningId.getAndIncrement();
    }

    @Override
    public int hashCode() {
        return this.id;
    }

    @Override
    public boolean equals(Object that) {
        return (that != null && that instanceof EventQueue && ((EventQueue) that).id == this.id);
    }

    @Override
    public String toString() {
        return this.name + "[" + this.eventType.getCanonicalName() + "]";
    }
}

@@ -253,32 +253,37 @@
  * %3Cpre%3E%0A *     
+Event
 Queue%3CMyEventTyp
@@ -289,32 +289,40 @@
 pe%3E queue = 
+Event
 Queue.
-of
+build
 (MyEventType
@@ -729,32 +729,37 @@
  * %3Cpre%3E%0A *     
+Event
 Queue%3CMyEventTyp
@@ -770,24 +770,32 @@
 ueue1 = 
+Event
 Queue.
-of
+build
 (MyEvent
@@ -821,32 +821,37 @@
 ).get();%0A *     
+Event
 Queue%3CMyEventTyp
@@ -862,24 +862,32 @@
 ueue2 = 
+Event
 Queue.
-of
+build
 (MyEvent
@@ -1232,16 +1232,21 @@
 %0A *     
+Event
 Queue%3CMy
@@ -1264,24 +1264,32 @@
 queue = 
+Event
 Queue.
-of
+build
 (MyEvent
@@ -1461,21 +1461,17 @@
 ss Event
-Queue
+s
  %7B%0A *   
@@ -1488,32 +1488,37 @@
 ic static final 
+Event
 Queue%3CEvent1%3E EV
@@ -1524,24 +1524,32 @@
 VENT1 = 
+Event
 Queue.
-of
+build
 (Event1.
@@ -1593,16 +1593,21 @@
 c final 
+Event
 Queue%3CEv
@@ -1625,16 +1625,24 @@
 2 = 
+Event
 Queue.
-of
+build
 (Eve

Fix now incorrect JavaDoc around EventQueue type