import { ITrackHistoryState , IJsonDiff , IStoreEnhancer , IReduxCreateStore } from './ITypes' ; import * as Actions from './Actions' ; let jsonDiffPatch = require ( 'jsondiffpatch' ) ; let extend = require ( 'extend' ) ; import { compose } from 'redux' ; let initialState = { stateHistory : { history : [ ] , timestamps : [ ] , actions : [ ] , current : - 1 , } } ; function mergeDiff ( target , diff ) { jsonDiffPatch . patch ( target , diff ) ; return target ; } function rebuildState ( history , position ) { return history . slice ( 0 , position + 1 ) . map ( hydratingState => extend ( true , { } , hydratingState ) ) . reduce ( ( hydratingState , diff ) => mergeDiff ( hydratingState , diff ) , { } ) ; } export function selectHistory ( state = initialState , action ) { switch ( action . type ) { case Actions . SELECT_HISTORY : if ( action . payload <= 0 ) { return state ; } let newState = rebuildState ( state . stateHistory . history , action . payload ) ; return extend ( true , { } , newState , { stateHistory : state . stateHistory } , { stateHistory : { current : action . payload } } ) ; default : return state ; } } ; function uploadHistory ( state = initialState , action ) { switch ( action . type ) { case Actions . UPLOAD_HISTORY : const newState = rebuildState ( action . payload . history , action . payload . history . length ) ; return Object . assign ( { } , newState , { stateHistory : action . payload } ) ; default : return state ; } } const reducerReducer = ( reducers , state , action ) => reducers . reduce ( ( previousState , reducer ) => reducer ( previousState , action ) , state ) ; /**
 * Add history module reducers to the root reducer
 */ export function addExtraReducers ( reducer ) { return ( state , action ) => reducerReducer ( [ uploadHistory , selectHistory , reducer ] , state , action ) ; } /**
 * Store enhancer that adds state history (stored within the state)
 */ const debugStateHistory = ( createStore ) => ( reducer , state ) => createStore ( addExtraReducers ( reducer ) , state ) ; export default debugStateHistory ;