import jwt_decode from 'jwt-decode';

async function login ({commit, dispatch}, loginRequest) {
  const url = "/login";
  const init = {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: loginRequest
  }
  const res = await dispatch('api', [url, init]);
  if (res && res.ok) {
    await dispatch('setCredentials', true);
    await dispatch('loadUserPreferences');
  }
}

async function logout ({commit, dispatch}) {
  commit('setCookie', null);
  commit('setUser', null);
  // Should delete JWT cookie
  await dispatch('api', ["/logout"]);

  // Clear preferences
  commit('setPreferences', {});
}

function browserCookie (state) {
  return document.cookie.split(/; */).find(i => /^JWT=.+/.test(i));
}

function cookieChanged (cookie) {
  return browserCookie != cookie;
}

function setCredentials ({state, commit, getters, dispatch}, force = false) {
  if (cookieChanged(state.cookie) || force) {
    try {
      const cookie = browserCookie();
      const decoded = cookie ? jwt_decode(cookie.split("=")[1]) : null;
      commit('setCookie', cookie);
      commit('setUser', decoded);
    } catch (err) {
      if (err.name == "InvalidTokenError") {
        console.warn("Failed to decode", browserCookie());
      } else {
        console.error("setCredentials", err);
      }
    }
  }
  dispatch('loadUserPreferences');
}

/**
 * Save user preferences to localStorage and store.
 * 
 * User preferences are identified by a key that gets
 * prefixed with the user name and role. The value can
 * be anything that JSON.stringify can parse.
 */
function saveUserPreference ({state, commit}, [key, value]) {
  const k = `${state.user?.name}.${state.user?.role}.${key}`;

  if (value !== undefined) {
    localStorage.setItem(k, JSON.stringify(value));

    const preferences = state.preferences;
    preferences[key] = value;
    commit('setPreferences', preferences);
  } else {
    localStorage.removeItem(k);

    const preferences = state.preferences;
    delete preferences[key];
    commit('setPreferences', preferences);
  }
}

async function loadUserPreferences ({state, commit}) {
  // Get all keys which are of interest to us
  const prefix = `${state.user?.name}.${state.user?.role}`;
  const keys = Object.keys(localStorage).filter( k => k.startsWith(prefix) );

  // Build the preferences object
  const preferences = {};
  keys.map(str => {
    const value = JSON.parse(localStorage.getItem(str));
    const key = str.split(".").slice(2).join(".");
    preferences[key] = value;
  });

  // Commit it
  commit('setPreferences', preferences);
}


export default {
  login,
  logout,
  setCredentials,
  saveUserPreference,
  loadUserPreferences
};
