import Vue from "vue";
import Vuex from "vuex";
import axios from "axios";
import {
  KEYBOARDS_LOCALSTORAGE_KEY,
  DEFAULT_KEYBOARDS,
  UTF8_ASSETS_URL,
} from "../config";
import { displayUTF8 } from "../helpers.js";

Vue.use(Vuex);

// TODO Handle sync with the local storage from the store
const keyboardFromStorage = () => {
  try {
    const keyboards = JSON.parse(
      localStorage.getItem(KEYBOARDS_LOCALSTORAGE_KEY)
    );
    return keyboards || DEFAULT_KEYBOARDS;
  } catch {
    return DEFAULT_KEYBOARDS;
  }
};

export default new Vuex.Store({
  state: {
    keyboards: keyboardFromStorage(),
    scriptsList: null,
    scripts: {},
    // { name: scriptName, page: 1 }
    selectedScript: null,
  },
  mutations: {
    setScriptsList(state, data) {
      state.scriptsList = data;
    },
    setScript(state, { scriptName, data }) {
      // Override scripts objects to trigger reactivity
      state.scripts = {
        ...state.scripts,
        [scriptName]: data,
      };
    },
    setSelectedScript(state, { name, page }) {
      state.selectedScript = { name, page };
    },
    updateName(state, { index, name }) {
      if (!state.keyboards[index]) return;
      state.keyboards[index].name = name;
    },
    updateKey(state, { index, row, column, code }) {
      // Copy the keyboard if the index is correct to avoid modifying it directly in the state 
      const keyboard = state.keyboards[index] && { ...state.keyboards[index] };
      if (!keyboard) return;
      // Find the key and replace it
      const newKey = {
        character: displayUTF8(code),
        row,
        column,
        keyboard_code: null,
      };
      const keyPos = keyboard.characters.findIndex(
        (k) => k.row === row && k.column === column
      );
      if (keyPos > 0) keyboard.characters[keyPos] = newKey;
      else keyboard.characters.push(newKey);
      state.keyboards[index] = keyboard;
      // Update list reference to propagate changes across components
      state.keyboards = [...state.keyboards];
    },
  },
  actions: {
    async listScripts({ state, commit }) {
      // List the names of all available UTF-8 glyphs
      if (state.scriptsList !== null) return;
      const resp = await axios.get(`${UTF8_ASSETS_URL}/index.json`);
      commit("setScriptsList", resp.data);
    },
    async retrieveScript({ state, commit }, scriptName) {
      /*
       * Retrieve a complete set of glyphs for a specific script
       * Note that scripts are compressed using gzip
       */
      if (state.scripts[scriptName]) return;
      const resp = await axios.get(`${UTF8_ASSETS_URL}/${scriptName}.json`);
      commit("setScript", { scriptName, data: resp.data });
    },
  },
  modules: {},
  getters: {},
});