import axios from 'axios'
import { API_GUEST_TOKEN, API_TOKEN, API_TOKEN_KEY, API_USER_IDENTIFIER } from './localStorageKeys'
import router from '@/router'
import security from '@/plugins/security'
import appSettings from '@/config/app-settings'
import Vue from 'vue'
import store from '@/store'
import helpers from '@/helpers'

export const service = axios.create()

const TOKEN_TYPE = 'Bearer'
let tokenKey = localStorage.getItem(API_TOKEN_KEY) !== null ? localStorage.getItem(API_TOKEN_KEY) : API_TOKEN
setDefaultToken(localStorage.getItem(tokenKey))
service.defaults.headers.post['Content-Type'] = 'application/json'
service.defaults.headers.common['Access-Control-Allow-Origin'] = ''
service.defaults.headers.common = { ...service.defaults.headers.common, ...appSettings.axios.headers }

// set accept language to Axios header
setCurrentLanguage()

// sets the user identifier if exists
let userIdentifier = sessionStorage.getItem(API_USER_IDENTIFIER) || ''
setUserIdentifier(userIdentifier)

// Disable if progress plugin not initialize
let progress = Vue.prototype.$Progress || { start: () => false, fail: () => false, finish: () => false }

service.interceptors.request.use(
  function(config) {
    config['headers']['Accept-Language'] = setCurrentLanguage()
    progress.start()
    return config
  },
  function(error) {
    progress.fail()
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  function(response) {
    progress.finish()
    return response
  },
  function(error) {
    progress.fail()
    return Promise.reject(error)
  }
)

export function get(url, cancelToken = null, headers = {}, params = {}) {
  return service({
    method: 'GET',
    url: url,
    params: params,
    withCredentials: false,
    responseType: 'json',
    maxRedirects: 5,
    headers: headers,
    cancelToken: cancelToken,
  }).catch(responseCatch)
}

export function post(url, payload, cancelToken = null, headers = {}) {
  return service({
    method: 'POST',
    url: url,
    data: payload,
    withCredentials: false,
    responseType: 'json',
    maxRedirects: 5,
    headers: headers,
    cancelToken: cancelToken,
  }).catch(responseCatch)
}

export function put(url, payload) {
  return service({
    method: 'PUT',
    url: url,
    data: payload,
    withCredentials: false,
    responseType: 'json',
    maxRedirects: 5,
    cancelToken: getCancelToken().token,
  }).catch(responseCatch)
}

export function patch(url, payload) {
  return service({
    method: 'PATCH',
    url: url,
    data: payload,
    withCredentials: false,
    responseType: 'json',
    maxRedirects: 5,
    cancelToken: getCancelToken().token,
  }).catch(responseCatch)
}

export function del(url, payload) {
  return service({
    method: 'DELETE',
    url: url,
    data: payload,
    withCredentials: false,
    responseType: 'json',
    maxRedirects: 5,
    cancelToken: getCancelToken().token,
  }).catch(responseCatch)
}

// Save the token to local storage
export function saveToken(token) {
  // Update the global token immediately
  service.defaults.headers.common['Authorization'] = `${TOKEN_TYPE} ${token}`
  return new Promise(resolve => {
    localStorage.setItem(API_TOKEN, token)
    resolve()
  })
}

// Save the token to local storage
export async function saveGuestToken(token) {
  // Update the global token immediately
  service.defaults.headers.common['Authorization'] = `${TOKEN_TYPE} ${token}`
  await localStorage.setItem(API_GUEST_TOKEN, token)
}

// Save the token to local storage
export function setDefaultToken(token) {
  return new Promise(resolve => {
    // Update the global token immediately
    if (Vue.prototype.$appStore !== undefined) {
      Vue.prototype.$appStore.dispatch('removeError', 'Unauthenticated')
    }
    service.defaults.headers.common['Authorization'] = `${TOKEN_TYPE} ${token}`
    if (Vue.prototype.$echo) {
      Vue.prototype.$echo.connector.options.auth.headers['Authorization'] = 'Bearer ' + token
    }
    resolve()
  })
}
// save user identifier
export function setUserIdentifier(identifier) {
  let identity = ''

  if (identifier.trim() !== '') {
    if (identifier.indexOf('eshop-') === -1) {
      identity = `eshop-${identifier}`
    } else {
      identity = identifier
    }
  }

  service.defaults.headers.common['E-User-Identifier-Key'] = identity
  sessionStorage.setItem(API_USER_IDENTIFIER, identity)
}

// Save the token to local storage
export function setVirelToken(token) {
  // Update the global token immediately
  service.defaults.headers.common['Authorization'] = `${TOKEN_TYPE} ${token}`
}

export function getCancelToken() {
  let CancelToken = axios.CancelToken
  return CancelToken.source()
}

export function responseCatch(error) {
  if (
    typeof error.response !== 'undefined' &&
    typeof error.response.status !== 'undefined' &&
    typeof error.response !== 'undefined' &&
    typeof error.response.data !== 'undefined' &&
    typeof error.response.data.error !== 'undefined' &&
    error.response.status === 401 &&
    error.response.data.error === 'Unauthenticated.'
  ) {
    if (security.routes.check(router.currentRoute, false) !== true) {
      if (Vue.prototype.$appStore !== undefined) {
        Vue.prototype.$appStore.dispatch('logoutUser')
      }
    } else {
      if (Vue.prototype.$appStore !== undefined) {
        Vue.prototype.$appStore.dispatch('logError', { Unauthenticated: true })
      }
    }
  } else {
    if (process.env.NODE_ENV !== 'production' && error.response) {
      /* eslint-disable no-console */
      console.info('------------- API ERROR')
      console.info(error.response)
      console.info('API ERROR ^^^^^^^^^^^^^')
      /* eslint-enable no-console */
    }
    throw error
  }
}

function setCurrentLanguage() {
  let localeCode = helpers.getValue(store, 'getters.getSelectedLanguage.locale_code', 'en-US')

  service.defaults.headers.common['Accept-Language'] = localeCode
  return localeCode
}

export function uploader(url, payload) {
  return service
    .post(url, payload, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    })
    .then(res => {
      return res
    })
    .catch(e => {
      return e.response
    })
}
//Todo Remove once pwa in place
// export function checkVersion(force = false) {
//   if (process.env.NODE_ENV === 'production') {
//     if (typeof window['__version_check'] === 'undefined' || window['__version_check'] !== false) {
//       let version = window['__version_check'] || null
//       if (version === null || version === 0 || force) {
//         window['__version_check'] = false
//         return axios({
//           method: 'GET',
//           url: '/version.json',
//           responseType: 'json',
//           headers: { 'Cache-Control': 'max-age=120' },
//           maxRedirects: 5,
//         })
//           .then(res => {
//             window['__version_check'] = version || 5
//             Vue.prototype.$appStore.dispatch('versionCheck', res.data)
//             // check version by interval
//             if (typeof window['__version_check_timmer'] === 'undefined') {
//               window['__version_check_timmer'] = setInterval(function() {
//                 checkVersion(true)
//               }, 1000 * 30)
//             }
//           })
//           .catch(() => {
//             window['__version_check'] = false
//           })
//       } else if (Number.isInteger(version)) {
//         window['__version_check']--
//       }
//     }
//   }
// }
