import { fromJS, Map, OrderedMap } from 'immutable';

import WorkflowExecutionsConstants
  from '../constants/WorkflowExecutionsConstants';
import { WorkflowExecution } from '../immutableRecords/workflowExecutions';

const initialState = Map({
  executionsLoaded: false,
  isFetching: false,
  executions: OrderedMap()
});

export default function workflowExecutionsReducer(
  state = initialState,
  action
) {
  switch (action.type) {
    case WorkflowExecutionsConstants.FETCH_WORKFLOW_EXECUTIONS_PENDING:
      return state.set('isFetching', true);

    case WorkflowExecutionsConstants.FETCH_WORKFLOW_EXECUTIONS_SUCCESS: {
      const executions = fromJS(action.payload)
        .map(execution => new WorkflowExecution(parseExecutionAttrs(execution)))
        .sortBy(execution => execution.updated_at);
      return state
        .set('executions', executions)
        .set('executionsLoaded', true)
        .set('isFetching', false);
    }

    case WorkflowExecutionsConstants.FETCH_WORKFLOW_EXECUTIONS_FAILED:
      return state.set('executionsLoaded', true).set('isFetching', false);

    case WorkflowExecutionsConstants.ADD_WORKFLOW_EXECUTION:
      return state.update('executions', executions =>
        executions.set(
          action.payload.id,
          new WorkflowExecution(parseExecutionAttrs(fromJS(action.payload)))
        )
      );

    case WorkflowExecutionsConstants.UPDATE_WORKFLOW_EXECUTION_PENDING:
      return state.mergeIn(
        ['executions', action.payload.id],
        fromJS(action.payload.patch)
      );

    default:
      return state;
  }
}

/**
 * Executions properties input, output and params are JSON strings, this function parses them into
 * objects
 */
const parseExecutionAttrs = execution =>
  execution
    .set('input', fromJS(JSON.parse(execution.get('input', '{}'))))
    .set('output', fromJS(JSON.parse(execution.get('output', '{}'))))
    .set('params', fromJS(JSON.parse(execution.get('params', '{}'))))
    .set('updated_at', fromJS(Date.parse(execution.get('updated_at'))));
