import { Action, Reducer } from 'redux'

// -----------------
// STATE - This defines the type of data maintained in the Redux store.

export interface LoaderState {
  visible: boolean
}

interface RequestAction {
  type: 'SHOW_LOADER'
}

interface ReceiveAction {
  type: 'HIDE_LOADER'
}

// Declare a 'discriminated union' type. This guarantees that all references to 'type' properties contain one of the
// declared type strings (and not any other arbitrary string).
export type KnownAction = RequestAction | ReceiveAction

// ----------------
// ACTION CREATORS - These are functions exposed to UI components that will trigger a state transition.
// They don't directly mutate state, but they can have external side-effects (such as loading data).

export const actionCreators = {
  show: () => ({ type: 'SHOW_LOADER' } as RequestAction),
  hide: () => ({ type: 'HIDE_LOADER' } as ReceiveAction)
}

// ----------------
// REDUCER - For a given state and action, returns the new state. To support time travel, this must not mutate the old state.

const unloadedState: LoaderState = {
  visible: false
}

export const reducer: Reducer<LoaderState> = (state: LoaderState | undefined, incomingAction: Action): LoaderState => {
  if (state === undefined) {
    return unloadedState
  }

  const action = incomingAction as KnownAction
  switch (action.type) {
    case 'SHOW_LOADER':
      return { visible: true }
    case 'HIDE_LOADER':
      return { visible: false }
  }

  return state
}