import Vue from 'vue'
import Vuex from 'vuex'
import VuexPersist from 'vuex-persist'

Vue.use(Vuex)
const USER = `convene_${ window.location.hostname }_user`
const SETTINGS = `convene_${ window.location.hostname }_settings`

// A Vuex plugin to persist the user object to either session or local storage, based on flag in the store state.
//
const persistUserPlugin = store => {
    var user;
    if (store.state.useLocalStorage) {
        user = JSON.parse(window.localStorage.getItem(USER));
    } else {
        user = JSON.parse(window.sessionStorage.getItem(USER));
    }
    const initialState = user ? { status: { loggedIn: true }, user } : { status: { loggedIn: false }, user: null };
    store.state.auth = initialState;

    store.subscribe((mutation, state) => {
        if (mutation.type == 'setUser' || mutation.type == 'setUseLocalStorage') {
            if (state.useLocalStorage) {
                window.localStorage.setItem(USER, JSON.stringify(state.auth.user));
                window.sessionStorage.removeItem(USER);
            } else {
                window.sessionStorage.setItem(USER, JSON.stringify(state.auth.user));
                window.localStorage.removeItem(USER);
            }
        }
    })
}


const vuexPersistLocalStorage = new VuexPersist({
    key: SETTINGS,
    storage: localStorage,
    reducer: state => {
        if (state.useLocalStorage) {
            return {
                language: state.language,
                currentRoomId: state.currentRoomId,
                hasShownMissedItemsHint: state.hasShownMissedItemsHint,
                globalNotification: state.globalNotification,
            };
        } else {
            return {};
        }
    }
})

const vuexPersistSessionStorage = new VuexPersist({
    key: SETTINGS,
    storage: sessionStorage,
    reducer: state => {
        if (!state.useLocalStorage) {
            return {
                language: state.language,
                currentRoomId: state.currentRoomId,
                hasShownMissedItemsHint: state.hasShownMissedItemsHint,
            };
        } else {
            return {};
        }
    }
})

const defaultUseSessionStorage = (sessionStorage.getItem(USER) != null);

export default new Vuex.Store({
    state: { language: null, currentRoomId: null, auth: null, tempuser: null, useLocalStorage: !defaultUseSessionStorage, globalNotification: false },
    mutations: {
        loginSuccess(state, user) {
            state.auth.status.loggedIn = true;
            state.auth.user = user;
        },
        loginFailure(state) {
            state.auth.status.loggedIn = false;
            state.auth.user = null;
        },
        logout(state) {
            state.auth.status.loggedIn = false;
            state.auth.user = null;
        },
        setLanguage(state, locale) {
            state.language = locale;
        },
        setCurrentRoomId(state, roomId) {
            state.currentRoomId = roomId;
        },
        setUser(state, user) {
            state.auth.user = user; // Don't stringify, our persistUserPlugin handles that!
        },
        setTempUser(state, user) {
            state.tempuser = JSON.stringify(user);
        },
        setUseLocalStorage(state, useLocalStorage) {
            state.useLocalStorage = useLocalStorage;
        },
        setHasShownMissedItemsHint(state, flag) {
            state.hasShownMissedItemsHint = flag;
        },
        setGlobalNotification(state, flag) {
            state.globalNotification = flag;
        }
    },
    actions: {
        login({ commit }, { user, registrationFlowHandler }) {
            return this._vm.$matrix.login(user, registrationFlowHandler).then(
                user => {
                    commit('loginSuccess', user);
                    return Promise.resolve(user);
                },
                error => {
                    commit('loginFailure');
                    return Promise.reject(error);
                }
            );
        },
        createUser({ commit }, { user, registrationFlowHandler }) {
            return this._vm.$matrix.login(user, registrationFlowHandler, true).then(
                user => {
                    commit('loginSuccess', user);
                    return Promise.resolve(user);
                },
                error => {
                    commit('loginFailure');
                    return Promise.reject(error);
                }
            );
        },
        logout({ commit }) {
            this._vm.$matrix.logout();
            commit('logout');
        },
    },
    getters: {
        storage: state => {
            if (state.useLocalStorage) {
                return window.localStorage;
            } else {
                return window.sessionStorage;
            }
        }
    },
    plugins: [vuexPersistLocalStorage.plugin, vuexPersistSessionStorage.plugin, persistUserPlugin]
})
