import inRange from 'lodash-es/inRange';

import {ConsoleState, ConsoleEntry, ConsoleError} from '../records';

const initialState = new ConsoleState();

function updateConsoleForHistoryIndex(index, state) {
  const expressionHistory = state.history.toList().
    map(entry => entry.expression).
    filter(expression => expression !== null).
    concat(state.nextConsoleEntry).
    reverse();

  if (!inRange(index, expressionHistory.size)) {
    return state;
  }

  const expression = expressionHistory.get(index);

  return state.
    set('historyEntryIndex', index).
    set('currentInputValue', expression);
}

function setNextConsoleEntry(newHistoryEntryIndex, state) {
  const firstUp = newHistoryEntryIndex === 1;

  if (firstUp && !state.history.isEmpty()) {
    return state.set('nextConsoleEntry', state.currentInputValue);
  }

  return state;
}

export default function console(stateIn, {type, payload, meta}) {
  let state = stateIn;
  if (state === undefined) {
    state = initialState;
  }

  switch (type) {
    case 'CONSOLE_VALUE_PRODUCED':
      return state.updateIn(
        ['history', payload.key],
        input => input.set(
          'value',
          payload.value,
        ).set(
          'evaluatedByCompiledProjectKey',
          payload.compiledProjectKey,
        ),
      );
    case 'CONSOLE_ERROR_PRODUCED':
      return state.updateIn(
        ['history', payload.key],
        input => input.set(
          'error',
          new ConsoleError({name: payload.name, message: payload.message}),
        ).set(
          'evaluatedByCompiledProjectKey',
          payload.compiledProjectKey,
        ),
      );
    case 'EVALUATE_CONSOLE_ENTRY':
      return payload.trim(' ') === '' ? state : state.setIn(
        ['history', meta.key],
        new ConsoleEntry({expression: payload}),
      ).
        delete('currentInputValue').
        delete('nextConsoleEntry').
        delete('historyEntryIndex');
    case 'CLEAR_CONSOLE_ENTRIES':
      return initialState;
    case 'CONSOLE_INPUT_CHANGED':
      return state.set('currentInputValue', payload.value);
    case 'CONSOLE_LOG_PRODUCED':
      return state.setIn(
        ['history', meta.key],
        new ConsoleEntry({
          value: payload.value,
          evaluatedByCompiledProjectKey: payload.compiledProjectKey,
        }),
      );
    case 'PREVIOUS_CONSOLE_HISTORY': {
      const newHistoryEntryIndex = state.historyEntryIndex + 1;

      return updateConsoleForHistoryIndex(
        newHistoryEntryIndex,
        setNextConsoleEntry(state),
      );
    }
    case 'NEXT_CONSOLE_HISTORY': {
      const newHistoryEntryIndex = state.historyEntryIndex - 1;

      return updateConsoleForHistoryIndex(newHistoryEntryIndex, state);
    }
    default:
      return state;
  }
}

@@ -189,20 +189,20 @@
 dex(
-index, state
+state, index
 ) %7B%0A
@@ -643,35 +643,27 @@
 try(
-newHistoryEntryIndex, state
+state, historyIndex
 ) %7B%0A
@@ -680,29 +680,21 @@
 rstUp = 
-newHistoryEnt
+histo
 ryIndex 
@@ -2363,37 +2363,29 @@
       const 
-newHistoryEnt
+histo
 ryIndex = st
@@ -2463,36 +2463,56 @@
         
-newHistoryEnt
+setNextConsoleEntry(state, histo
 ryIndex
+)
 ,%0A      
@@ -2517,34 +2517,20 @@
     
-setNextConsoleEntry(state)
+historyIndex
 ,%0A  
@@ -2578,75 +2578,8 @@
 RY':
- %7B%0A      const newHistoryEntryIndex = state.historyEntryIndex - 1;%0A
 %0A   
@@ -2621,12 +2621,22 @@
 dex(
-newH
+state, state.h
 isto
@@ -2651,23 +2651,14 @@
 ndex
-, state);%0A    %7D
+ - 1);
 %0A   

Make console reducer style more consistent