/** @module users/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 = {
    loginRequest: (data) => {
        return {
            type: 'USER/LOGIN_REQUEST',
            data
        }
    },
    loginSuccess: (data) => {
        return {
            type: 'USER/LOGIN_SUCCESS',
            data
        }
    },
    loginFailure: (error) => {
        return {
            type: 'USER/LOGIN_FAILURE',
            error
        }
    },
    getUserListRequest: (data) => {
        return {
            type: 'USER/GET_USER_LIST_REQUEST',
            data
        }
    },
    getUserListSuccess: (data) => {
        return {
            type: 'USER/GET_USER_LIST_SUCCESS',
            data
        }
    },
    getUserListFailure: (error) => {
        return {
            type: 'USER/GET_USER_LIST_FAILURE',
            error
        }
    },
    addUserRequest: (data) => {
        return {
            type: 'USER/ADD_USER_REQUEST',
            data
        }
    },
    addUserSuccess: (data) => {
        return {
            type: 'USER/ADD_USER_SUCCESS',
            data
        }
    },
    addUserFailure: (error) => {
        return {
            type: 'USER/ADD_USER_FAILURE',
            error
        }
    }
}
console.log('State actions', actions)

/** state definition */

// Check, if there is a valid token.
const token = localStorage.getItem('accessToken')
const tokenData = token ? JSON.parse(localStorage.getItem('accessTokenData')) : null
const tokenValid = tokenData ? tokenData.expires > Date.now() : false

export const state = {
    loginRequested: false,
    userListRequested: false,
    userListInitialized: false,
    users: [],
    token,
    tokenData,
    tokenValid
}
console.log('State state', state)

/** reducer is called by the redux dispatcher and handles all component actions */
export function reducer (state = [], action) {
    let token
    let tokenData
    let tokenValid
    switch (action.type) {
        case 'USER/LOGIN_REQUEST':
            return { ...state, loginRequested: true }
        case 'USER/LOGIN_SUCCESS':
            localStorage.setItem('accessToken', action.data.token)
            token = action.data.token
            tokenData = token ? JSON.parse(localStorage.getItem('accessTokenData')) : null
            tokenValid = tokenData ? tokenData.expires > Date.now() : false
            return { ...state, loginRequested: false, token, tokenData, tokenValid }
        case 'USER/LOGIN_FAILURE':
            return { ...state, loginRequested: false }
        case 'USER/GET_USER_LIST_REQUEST':
            return { ...state, userListRequested: true, userListInitialized: true }
        case 'USER/GET_USER_LIST_SUCCESS':
            return { ...state, userListRequested: false, users: action.data }
        case 'USER/GET_USER_LIST_FAILURE':
            return { ...state, userListRequested: false }
        case 'USER/ADD_USER_REQUEST':
            return { ...state, userListRequested: true, userListInitialized: true }
        case 'USER/ADD_USER_SUCCESS':
            return { ...state, userListRequested: false, users: [ ...state.users, action.data ] }
        case 'USER/ADD_USER_FAILRE':
            return { ...state, userListRequested: false }
        default:
            return state
    }
}

function * login (action) {
    yield put(api.actions.apiRequest({
      path: `authenticate/login`,
      method: 'POST',
      body: JSON.stringify(action.data),
      onSuccess: actions.loginSuccess,
      onFailure: actions.loginFailure
    }))
}

function * getUserList (action) {
    yield put(api.actions.apiRequest({
      path: `api/users`,
      method: 'GET',
      onSuccess: actions.getUserListSuccess,
      onFailure: actions.getUserListFailure
    }))
}

function * addUser (action) {
    yield put(api.actions.apiRequest({
      path: `api/users`,
      method: 'POST',
      body: JSON.stringify(action.data),
      onSuccess: actions.addUserSuccess,
      onFailure: actions.addUserFailure
    }))
}

function * editUser (action) {
    yield put(api.actions.apiRequest({
      path: `api/users`,
      method: 'PUT',
      body: JSON.stringify(action.data),
      onSuccess: actions.editUserSuccess,
      onFailure: actions.editUserFailure
    }))
}

/** sagas are asynchronous workers (JS generators) to handle the state. */
export function * saga () {
    console.log('User saga started.')
    yield takeEvery('USER/LOGIN_REQUEST', login)
    yield takeEvery('USER/GET_USER_LIST_REQUEST', getUserList)
    yield takeEvery('USER/ADD_USER_REQUEST', addUser)
    yield takeEvery('USER/EDIT_USER_REQUEST', editUser)
}
