import createTest, { isTestLibrarySupported } from './create-test';

const reduxRecord = function({
  reducer, 
  includeReducer = false, 
  stateKey,
  actionSubset,
  equality = '(result, nextState) => result === nextState',
  imports = '',
  testLib = 'tape',
  numTestsToSave = 5,
  includeShowTestsButton = false
}) { 
  let actions = [];
  let recording = false;
  let showingTest = false;
  let testIndex = undefined;
  let prevTests = [];
  let listeners = [];
  let stringifiedReducer = '/* import reducer from YOUR_REDUCER_LOCATION_HERE */';
  if (includeReducer) {
    stringifiedReducer = `var reducer = ${reducer.toString()}`;
  }

  const updateListeners = () => {
    if (listeners.length) {
      let newTestState = {
        recording,
        showingTest,
        tests: prevTests,
        testIndex
      }
      listeners.forEach(fn => fn(newTestState));
    }
  }
  
  // we can skip type checking to see if equality arg is a string since string.toString() returns same string
  const equalityFunction = equality.toString();
  const startRecord = () => {
    recording = true;
    updateListeners();
  };
  const stopRecord = () =>  {
    recording = false;
    showingTest = true;
    updateListeners();
  }

  const hideTest = () => {
    showingTest = false;
    updateListeners();
  };

  const showTest = () => {
    showingTest = true;
    updateListeners();
  };

  const emptyActions = () => {
    actions = [];
    updateListeners();
  };

  const updateTestIndex = (index) => {
    testIndex = index;
    updateListeners();
  }

  const genTest = typeof testLib === 'function' ? testLib : createTest;
  if (typeof testLib !== 'string' && typeof testLib !== 'function') {
    throw new Error('testLib argument must be a string or a function');
  }
  if (typeof testLib === 'string' && !isTestLibrarySupported(testLib)) {
    throw new Error('testLib argument does not contain a supported testing library. ' + 
      'Feel free to make a pr adding support or use a custom test generation function for testLib arg');
  }

  const createNewTest = () => {
    const test = (
      genTest({
        actions,
        imports,
        equalityFunction,
        reducer: stringifiedReducer,
        testLib: testLib
      })
    );
    if (prevTests.length === numTestsToSave) {
      prevTests = prevTests.slice(1, prevTests.length);
    }
    prevTests.push(test);
    testIndex = prevTests.length - 1;
    updateListeners();
    return test;
  }

  const middleware = ({getState}) => (next) => (action) => {
    if (recording) {
      const prevState = stateKey ? getState()[stateKey] : getState();
      next(action);
      const nextState = stateKey ? getState()[stateKey] : getState();
      if (!actionSubset || actionSubset[action.type]) {
        actions.push({action, prevState, nextState});
      }
    }
    else {
      next(action);
    }
  };

  const listen = (fn) => {
    listeners.push(fn);
    updateListeners();
    return () => listeners.splice(listeners.splice(listeners.indexOf(fn), 1));
  }
  const props = { 
    startRecord, 
    stopRecord, 
    createNewTest, 
    hideTest, 
    showTest,
    emptyActions,
    updateTestIndex,
    listen,
    includeShowTestsButton
  };
  return { middleware, props };
};

export default reduxRecord;

@@ -103,17 +103,16 @@
 reducer,
- 
 %0A  inclu
@@ -129,17 +129,16 @@
 = false,
- 
 %0A  state
@@ -313,17 +313,16 @@
 lse%0A%7D) %7B
- 
 %0A  let a
@@ -879,11 +879,9 @@
   %7D%0A
-  
 %0A
+
   //
@@ -1926,17 +1926,16 @@
 ary. ' +
- 
 %0A      '
@@ -3043,17 +3043,16 @@
 rops = %7B
- 
 %0A    sta
@@ -3056,25 +3056,24 @@
 startRecord,
- 
 %0A    stopRec
@@ -3076,17 +3076,16 @@
 pRecord,
- 
 %0A    cre
@@ -3091,25 +3091,24 @@
 eateNewTest,
- 
 %0A    hideTes
@@ -3109,17 +3109,16 @@
 ideTest,
- 
 %0A    sho

remove trailing spaces