import { FETCH_CONFIG } from './helper.js'
import {
  TIMEZONE,
  setTimezone,
  LANG,
  updateLangList,
  USER_LOGIN,
  USER_DATA,
  USER_ROLE,
  USER_CONNECTED,
  setUserConnected,
  updateUserData,
  setUserRole,
  WORKSPACE,
  setWorkspaceData,
  WORKSPACE_LIST,
  updateWorkspaceListData,
  FOLDER,
  setFolderData,
  APP_LIST,
  setAppList,
  setWorkspaceListIsOpenInSidebar
} from './action-creator.sync.js'

/*
 * fetchWrapper(obj)
 *
 * Params:
 *   An Object with the following attributes :
 *     url - string - url of the end point to call
 *     param - object - param to send with fetch call (eg. header)
 *       param.method - string - REQUIRED - method of the http call
 *     actionName - string - name of the action to dispatch with 'PENDING' and 'SUCCESS' respectively before and after the http request
 *     dispatch - func - redux dispatcher function
 *
 * Returns:
 *   An object Response generated by whatwg-fetch with a new property 'json' containing the data received or informations in case of failure
 *
 * This function create a http async request using whatwg-fetch while dispatching a PENDING and a SUCCESS redux action.
 * It also adds, to the Response of the fetch request, the json value so that the redux action have access to the status and the data
 */
const fetchWrapper = async ({url, param, actionName, dispatch, debug = false}) => {
  dispatch({type: `${param.method}/${actionName}/PENDING`})

  const fetchResult = await fetch(url, param)
  fetchResult.json = await (async () => {
    switch (fetchResult.status) {
      case 200:
      case 304:
        return fetchResult.json()
      case 204:
      case 400:
      case 404:
      case 409:
      case 500:
      case 501:
      case 502:
      case 503:
      case 504:
        return '' // @TODO : handle errors
    }
  })()
  if (debug) console.log(`fetch ${param.method}/${actionName} result: `, fetchResult)

  if ([200, 204, 304].includes(fetchResult.status)) dispatch({type: `${param.method}/${actionName}/SUCCESS`, data: fetchResult.json})
  else if ([400, 404, 500].includes(fetchResult.status)) dispatch({type: `${param.method}/${actionName}/FAILED`, data: fetchResult.json})

  return fetchResult
}

export const getLangList = () => async dispatch => {
  const fetchGetLangList = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/lang`,
    param: {...FETCH_CONFIG.header, method: 'GET'},
    actionName: LANG,
    dispatch
  })
  if (fetchGetLangList.status === 200) dispatch(updateLangList(fetchGetLangList.json))
}

export const getTimezone = () => async dispatch => {
  const fetchGetTimezone = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/timezone`,
    param: {...FETCH_CONFIG.header, method: 'GET'},
    actionName: TIMEZONE,
    dispatch
  })
  if (fetchGetTimezone.status === 200) dispatch(setTimezone(fetchGetTimezone.json))
}

export const userLogin = (login, password, rememberMe) => async dispatch => {
  const fetchUserLogin = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/user/login`,
    param: {
      ...FETCH_CONFIG.header,
      method: 'POST',
      body: JSON.stringify({
        login,
        password,
        remember_me: rememberMe
      })
    },
    actionName: USER_LOGIN,
    dispatch
  })
  if (fetchUserLogin.status === 200) dispatch(setUserConnected(fetchUserLogin.json))
}

export const getIsUserConnected = () => async dispatch => {
  const fetchUserLogged = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/user/is_logged_in`,
    param: {...FETCH_CONFIG.header, method: 'GET'},
    actionName: USER_CONNECTED,
    dispatch
  })
  if (fetchUserLogged.status === 200) dispatch(setUserConnected(fetchUserLogged.json))
}

export const getUserRole = user => async dispatch => {
  const fetchGetUserRole = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/user/${user.id}/roles`,
    param: {...FETCH_CONFIG.header, method: 'GET'},
    actionName: USER_ROLE,
    dispatch
  })
  if (fetchGetUserRole.status === 200) dispatch(setUserRole(fetchGetUserRole.json))
}

export const updateUserLang = newLang => async dispatch => { // unused
  const fetchUpdateUserLang = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/user`,
    param: {...FETCH_CONFIG.header, method: 'PATCH', body: JSON.stringify({lang: newLang})},
    actionName: USER_DATA,
    dispatch
  })
  if (fetchUpdateUserLang.status === 200) dispatch(updateUserData({lang: fetchUpdateUserLang.json.lang}))
}

// export const testResponseNoData = () => async dispatch => {
//   const fetchResponseNoData = await fetchWrapper({
//     url: 'http://localhost:3001/deletenodata',
//     param: {...FETCH_CONFIG.header, method: 'DELETE'},
//     actionName: 'TestNoData',
//     dispatch
//   })
//   console.log('jsonResponseNoData', fetchResponseNoData)
// }

export const getWorkspaceList = (userId, workspaceIdToOpen) => async dispatch => {
  const fetchGetWorkspaceList = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/user/${userId}/workspace`,
    param: {...FETCH_CONFIG.header, method: 'GET'},
    actionName: WORKSPACE_LIST,
    dispatch
  })
  if (fetchGetWorkspaceList.status === 200) {
    dispatch(updateWorkspaceListData(fetchGetWorkspaceList.json))
    dispatch(setWorkspaceListIsOpenInSidebar(workspaceIdToOpen, true))
  }
}

export const getWorkspaceContent = (workspaceId, filterStr) => async dispatch => {
  const fetchGetWorkspaceContent = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/workspace/${workspaceId}`,
    param: {...FETCH_CONFIG.header, method: 'GET'},
    actionName: WORKSPACE,
    dispatch
  })
  if (fetchGetWorkspaceContent.status === 200) dispatch(setWorkspaceData(fetchGetWorkspaceContent.json, filterStr))
}

export const getFolderContent = (workspaceId, folderId) => async dispatch => {
  const fetchGetFolderContent = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/workspace/${workspaceId}/folder/${folderId}`,
    param: {...FETCH_CONFIG.header, method: 'GET'},
    actionName: `${WORKSPACE}/${FOLDER}`,
    dispatch
  })
  if (fetchGetFolderContent.status === 200) dispatch(setFolderData(folderId, fetchGetFolderContent.json))
}

export const getAppList = () => async dispatch => {
  const fetchGetAppList = await fetchWrapper({
    url: `${FETCH_CONFIG.apiUrl}/app/config`,
    param: {...FETCH_CONFIG.header, method: 'GET'},
    actionName: APP_LIST,
    dispatch
  })
  if (fetchGetAppList.status === 200) dispatch(setAppList(fetchGetAppList.json))
}
