// Path: redux-core/src/main/java/me/tatarka/redux/middleware/Middleware.java
// public interface Middleware<A, R> {
// 
//     /**
//      * Called when an action is dispatched.
//      *
//      * @param next   Dispatch to the next middleware or actually update the state if there is none.
//      *               You can chose to call this anywhere to see the state before and after it has
//      *               changed or not at all to drop the action.
//      * @param action This action that was dispatched.
//      */
//     R dispatch(Next<A, R> next, A action);
// 
//     interface Next<A, R> {
//         R next(A action);
//     }
// }


import me.tatarka.redux.middleware.Middleware;
import java.util.Arrays;
import java.util.Iterator;
package me.tatarka.redux;



/**
 * Dispatches actions with {@link Reducer}s and updates the state in the {@link Store}. You can chain {@link Middleware}
 * to implement cross-cutting concerns.
 *
 * @param <A> The action type.
 * @param <R> The return type of the dispatcher. This is implementation-defined.
 */
public abstract class Dispatcher<A, R> {

    /**
     * Constructs a {@code Dispatcher} from the given {@link Store} and {@link Reducer}. {@link #dispatch(Object)} will
     * run the action through the reducer and update the store with the resulting state.
     *
     * @param <S> The type of state in the store.
     * @param <A> The type of action.
     * @return the action dispatched.
     */
    public static <S, A> Dispatcher<A, A> forStore(final Store<S> store, final Reducer<A, S> reducer) {
        if (store == null) {
            throw new NullPointerException("store==null");
        }
        if (reducer == null) {
            throw new NullPointerException("reducer==null");
        }
        return new Dispatcher<A, A>() {
            @Override
            public A dispatch(A action) {
                store.setState(reducer.reduce(action, store.getState()));
                return action;
            }
        };
    }

    /**
     * Dispatches the given action.
     */
    public abstract R dispatch(A action);

    /**
     * Returns a new {@code Dispatcher} that runs the given {@link Middleware}.
     */
// Path: redux-core/src/main/java/me/tatarka/redux/middleware/Middleware.java
// public interface Middleware<A, R> {
// 
//     /**
//      * Called when an action is dispatched.
//      *
//      * @param next   Dispatch to the next middleware or actually update the state if there is none.
//      *               You can chose to call this anywhere to see the state before and after it has
//      *               changed or not at all to drop the action.
//      * @param action This action that was dispatched.
//      */
//     R dispatch(Next<A, R> next, A action);
// 
//     interface Next<A, R> {
//         R next(A action);
//     }
// }


// Path: redux-core/src/main/java/me/tatarka/redux/Dispatcher.java
import me.tatarka.redux.middleware.Middleware;
import java.util.Arrays;
import java.util.Iterator;

package me.tatarka.redux;



/**
 * Dispatches actions with {@link Reducer}s and updates the state in the {@link Store}. You can chain {@link Middleware}
 * to implement cross-cutting concerns.
 *
 * @param <A> The action type.
 * @param <R> The return type of the dispatcher. This is implementation-defined.
 */
public abstract class Dispatcher<A, R> {

    /**
     * Constructs a {@code Dispatcher} from the given {@link Store} and {@link Reducer}. {@link #dispatch(Object)} will
     * run the action through the reducer and update the store with the resulting state.
     *
     * @param <S> The type of state in the store.
     * @param <A> The type of action.
     * @return the action dispatched.
     */
    public static <S, A> Dispatcher<A, A> forStore(final Store<S> store, final Reducer<A, S> reducer) {
        if (store == null) {
            throw new NullPointerException("store==null");
        }
        if (reducer == null) {
            throw new NullPointerException("reducer==null");
        }
        return new Dispatcher<A, A>() {
            @Override
            public A dispatch(A action) {
                store.setState(reducer.reduce(action, store.getState()));
                return action;
            }
        };
    }

    /**
     * Dispatches the given action.
     */
    public abstract R dispatch(A action);

    /**
     * Returns a new {@code Dispatcher} that runs the given {@link Middleware}.
     */
    public final Dispatcher<A, R> chain(final Middleware<A, R> middleware) {