var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
function undoable(reducer, undoAction, redoAction, undoableActions) {
    var initialState = {
        past: [],
        present: reducer(undefined, {}),
        future: [],
    };
    return function (state, action) {
        if (state === void 0) { state = initialState; }
        var past = state.past, present = state.present, future = state.future;
        switch (action.type) {
            case undoAction:
                var previous = past[past.length - 1];
                var newPast = past.slice(0, past.length - 1);
                return {
                    past: newPast,
                    present: previous,
                    future: [present].concat(future),
                };
            case redoAction:
                var next = future[0];
                var newFuture = future.slice(1);
                return {
                    past: past.concat([present]),
                    present: next,
                    future: newFuture,
                };
            default:
                var newPresent = reducer(present, action);
                if (present === newPresent) {
                    return state;
                }
                if (!undoableActions.includes(action.type)) {
                    return __assign({}, state, { present: newPresent });
                }
                return {
                    past: past.concat([present]),
                    present: newPresent,
                    future: [],
                };
        }
    };
}
export default undoable;
//# sourceMappingURL=undoable.js.map