/** @module config/state */
import { put, takeEvery } from 'redux-saga/effects'
import api from '../api'

/**
 * state.js
 *
 * Collection of everything which has to do with state changes.
 **/

/** actionTypes define what actions are handeled by the reducer. */
export const actions = {
  configClearForm: () => {
    return {
      type: 'CONFIG/CLEAR_FORM'
    }
  },
  configLoadForm: (key) => {
    return {
      type: 'CONFIG/LOAD_FORM',
      key
    }
  },
  configChangeForm: (data) => {
    return {
      type: 'CONFIG/CHANGE_FORM',
      data
    }
  },
  configGetRequest: (data) => {
    return {
      type: 'CONFIG/GET_REQUEST',
      data
    }
  },
  configGetSuccess: (data) => {
    return {
      type: 'CONFIG/GET_SUCCESS',
      data
    }
  },
  configGetFailure: error => {
    return {
      type: 'CONFIG/GET_FAILURE',
      error
    }
  },
  configAddRequest: (data) => {
    return {
      type: 'CONFIG/ADD_REQUEST',
      data
    }
  },
  configAddSuccess: (data) => {
    return {
      type: 'CONFIG/ADD_SUCCESS',
      data
    }
  },
  configAddFailure: error => {
    return {
      type: 'CONFIG/ADD_FAILURE',
      error
    }
  },
  configEditRequest: (data) => {
    return {
      type: 'CONFIG/EDIT_REQUEST',
      data
    }
  },
  configEditSuccess: (data) => {
    return {
      type: 'CONFIG/EDIT_SUCCESS',
      data
    }
  },
  configEditFailure: error => {
    return {
      type: 'CONFIG/EDIT_FAILURE',
      error
    }
  },
  configDeleteRequest: (data) => {
    return {
      type: 'CONFIG/DELETE_REQUEST',
      data
    }
  },
  configDeleteSuccess: (data) => {
    return {
      type: 'CONFIG/DELETE_SUCCESS',
      data
    }
  },
  configDeleteFailure: error => {
    return {
      type: 'CONFIG/DELETE_FAILURE',
      error
    }
  },
}
console.log('State actions', actions)

const emptyForm = {
  _id: null,
  key: '',
  description: '',
  value: '',
}

/** state definition */
export const state = {
  configs: [],
  configForm: emptyForm,
  getRequested: false,
  addRequested: false,
  editRequested: false,
  deleteRequested: false
}
console.log('State state', state)

/** reducer is called by the redux dispatcher and handles all component actions */
export function reducer (state = [], action) {
  let index
  let newConfig
  switch (action.type) { 
    case 'CONFIG/CLEAR_FORM':
      return { ...state, configForm: emptyForm }
    case 'CONFIG/LOAD_FORM':
      return { ...state, configForm: { ...state.configs[action.key] } }
    case 'CONFIG/CHANGE_FORM':
      return { ...state, configForm: { ...action.data } }
    case 'CONFIG/GET_SUCCESS':
      return { ...state, configs: action.data.config, getRequested: false }
    case 'CONFIG/GET_FAILURE':
      return { ...state, getRequested: false, alert: action.error }
    case 'CONFIG/ADD_REQUEST':
      return { ...state, addRequested: true }
    case 'CONFIG/ADD_SUCCESS':
      return { ...state, configs: [ ...state.configs, action.data ], addRequested: false }
    case 'CONFIG/ADD_FAILURE':
      return { ...state, addRequested: false, alert: action.error }
    case 'CONFIG/EDIT_REQUEST':
      return { ...state, editRequested: true }
    case 'CONFIG/EDIT_SUCCESS':
      index = state.configs.findIndex(config => config._id === action.data._id)
      newConfig = [ ...state.configs.slice(0, index), action.data, ...state.configs.slice(index + 1)]
      return { ...state, configs: newConfig, editRequested: false }
    case 'CONFIG/EDIT_FAILURE':
      return { ...state, editRequested: false, alert: action.error }
    case 'CONFIG/DELETE_REQUEST':
      return { ...state, deleteRequested: true }
    case 'CONFIG/DELETE_SUCCESS':
      index = state.configs.findIndex(config => config.key === action.data.key)
      console.log('index', index)
      newConfig = [ ...state.configs.slice(0, index), ...state.configs.slice(index + 1)]
      console.log('newConfig', newConfig)
      return { ...state, configs: newConfig, deleteRequested: false }
    case 'CONFIG/DELETE_FAILURE':
      return { ...state, deleteRequested: false, alert: action.error }
    default:
      return state
  }
}

function * addConfig (action) {
  const { key, ...data } = action.data || { key: '' }
  yield put(api.actions.apiRequest({
    path: `api/config/${key}`,
    method: 'POST',
    body: JSON.stringify(data),
    onSuccess: actions.configAddSuccess,
    onFailure: actions.configAddFailure
  }))
}

function * getConfig (action) {
  const { key } = action.data || { key: '' }
    yield put(api.actions.apiRequest({
      path: `api/config/${key}`,
      onSuccess: actions.configGetSuccess,
      onFailure: actions.configGetFailure
    }))
}

function * editConfig (action) {
  const { key, ...data } = action.data || { key: '' }
  yield put(api.actions.apiRequest({
    path: `api/config/${key}`,
    method: 'PUT',
    body: JSON.stringify(data),
    onSuccess: actions.configEditSuccess,
    onFailure: actions.configEditFailure
  }))
}

function * deleteConfig (action) {
  const { key } = action.data || { key: '' }
  yield put(api.actions.apiRequest({
    path: `api/config/${key}`,
    method: 'DELETE',
    onSuccess: actions.configDeleteSuccess,
    onFailure: actions.configDeleteFailure
  }))
}

/** sagas are asynchronous workers (JS generators) to handle the state. */
export function * saga () {
  console.log('Config saga started.')
  yield takeEvery('CONFIG/GET_REQUEST', getConfig)
  yield takeEvery('CONFIG/ADD_REQUEST', addConfig)
  yield takeEvery('CONFIG/EDIT_REQUEST', editConfig)
  yield takeEvery('CONFIG/DELETE_REQUEST', deleteConfig)
}
