using System;
using System.Linq;
using UnityEditor;
namespace Unity.Play.Publisher.Editor
{
///
/// Defines the structure of a method that can be called when an action is dispatched
///
/// The action to dispatch
///
public delegate object Dispatcher(object action);
///
/// Defines the structure of a method that can be called when the State reducer
///
///
///
///
///
public delegate State Reducer(State previousState, object action);
///
/// Defines the structure of a method that can be called in order to alter the state of the application
///
///
///
///
public delegate Func Middleware(Store store);
///
/// Defines the structure of a method that can be called when the state of an object changes
///
///
///
public delegate void StateChangedHandler(State action);
///
/// Manages the communication between all the application components
///
///
public class Store
{
///
/// Delegate that reacts on state change
///
public StateChangedHandler stateChanged;
State _state;
readonly Dispatcher _dispatcher;
readonly Reducer _reducer;
///
/// Initializes and returns an instance of Store
///
///
///
///
public Store(
Reducer reducer, State initialState = default(State),
params Middleware[] middlewares)
{
this._reducer = reducer;
this._dispatcher = this.ApplyMiddlewares(middlewares);
this._state = initialState;
}
///
/// Dispatches an action
///
///
/// Returns an object affected by the action
public object Dispatch(object action)
{
return this._dispatcher(action);
}
///
/// The state
///
public State state
{
get { return this._state; }
}
Dispatcher ApplyMiddlewares(params Middleware[] middlewares)
{
return middlewares.Reverse().Aggregate, Dispatcher>(this.InnerDispatch,
(current, middleware) => middleware(this)(current));
}
object InnerDispatch(object action)
{
this._state = this._reducer(this._state, action);
if (this.stateChanged != null)
{
this.stateChanged(this._state);
}
return action;
}
}
}