    'use strict';
    import AnyPlayer from './player/any-player';
    import allHeroesJson from '../../../server/src/client-server-shared/all-heroes.json';

    const initGameState = {
      gameState: '',
      allHeroes: [],
      deckMode: '',
      advRules: [],
      'waitingFor/blue': false,
      'waitingFor/red': false,
      currentPlayer: '',
      'battleTiles/left': [],
      'battleTiles/center': [],
      'battleTiles/right': [],
      totalFood: 0,
      allHeroesJson
    };
    const state = Object.assign({}, initGameState);

    const getters = {
      state(state) {
        return state.gameState;
      },
      allHeroes(state) {
        return state.allHeroes;
      },
      deckMode(state) {
        return state.deckMode;
      },
      myColor(state, getters, rootState) {
        let color = 'blue';
        if (rootState.username === state.redPlayer.name) {
          color = 'red';
        }
        return color;
      },
      my: (state, getters) => target => {
        return getters.myColor + 'Player/' + target;
      },
      ennemyColor(state, getters) {
        let color = 'red';
        if (getters.myColor === 'red') {
          color = 'blue';
        }
        return color;
      },
      isItMyTurn(state, getters) {
        return state['waitingFor/' + getters.myColor];
      },
      isPopularityRule(state) {
        return state.advRules.includes('popularity');
      },
      isDiscardRule(state) {
        return state.advRules.includes('discard');
      },
      heroById: state => id => {
        return state.allHeroes.find(hero => hero.id === id);
      },
      myTwelveHeroes(state, getters) {
        let myHeroesIds = getters[getters.my('twelveHeroes')].map(hero => hero.id);
        return state.allHeroes.filter(hero => {
          return myHeroesIds.includes(hero.id);
        });
      },
      myDraftIds(state, getters) {
        return getters[getters.my('draftIds')];
      },

      filterHeroes: state =>
        /**
         * Get a filtered array of heroes
         *
         * vuex : 'game/filterHeroes'
         *
         * @param {object} filter - the filter to apply on all heroes array
         * @param {string} filter.faction - Filter on faction attribute, can be : orcs humans elves meca none all
         * @param {string} filter.popularity - Filter on popularity attribute
         * can be :
         * - none : no filter on popularity
         * - with : do not return heroes that are usable only when no popularity rule
         * - without : do not return heroes that are usable only when popularity rule
         * @param {string} filter.draft - Filter on draft attribute, can be : yes no all
         * @param {number} filter.minPower - Filter on power attribute >= minPower
         * @param {number} filter.maxPower - Filter on power attribute <= maxPower
         * @param {number} filter.minCost - Filter on cost attribute >= minCost
         * @param {number} filter.maxCost - Filter on cost attribute <= maxCost
         * @param {boolean} filter.byName - Activate filter on Hero's name
         * @param {string} filter.name - Filter on Hero's name
         * @param {number[]} filter.byId - Filter on Heroes Id(s). Do not filter in Ids if array is empty
         * @param state
         * @returns {object[]} Filtered array of heroes
         */
        filter => {
          if (!filter.faction) filter.faction = 'all';
          if (!filter.popularity) filter.popularity = 'without';
          if (!filter.minPower) filter.minPower = 0;
          if (!filter.maxPower) filter.maxPower = 8;
          if (!filter.minCost) filter.minCost = 0;
          if (!filter.maxCost) filter.minCost = 8;

          let draftFilter = 'all';
          switch (filter.draft) {
            case 'yes':
              draftFilter = true;
              break;
            case 'no':
              draftFilter = false;
              break;

            default:
              draftFilter = 'all';
              break;
          }
          return state.allHeroes.filter(hero => {
            if (filter.faction !== 'all' && hero.faction !== filter.faction)
              return false;
            if (
              filter.popularity !== 'none' &&
              hero.popularity !== 'any' &&
              hero.popularity !== filter.popularity
            )
              return false;

            if (draftFilter !== 'all' && hero.isDraftable !== draftFilter)
              return false;

            if (hero.power < filter.minPower || hero.power > filter.maxPower)
              return false;
            if (hero.cost < filter.minCost || hero.cost > filter.maxCost)
              return false;

            if (
              filter.byName === true &&
              !hero.name.toLowerCase().includes(filter.name.toLowerCase())
            )
              return false;

            if (
              filter.byId &&
              filter.byId.length > 0 &&
              !filter.byId.includes(hero.id)
            ) {
              return false;
            }
            return true;
          });
        }
    };

    const mutations = {
      SET_HEROES: (state, payload) => {
        state.allHeroes = payload;
      },
      SET_FULL_GAME_STATE: (state, payload) => {
        Object.assign(state, payload);
      },
      INIT_GAME_STATE: state => {
        Object.assign(state, initGameState);
      },
      SET_WAITING_FOR: (state, payload) => {
        state['waitingFor/' + payload.color] = payload.value;
      }
    };

    const actions = {
      /**
       * Sets the array containing all heroes
       *
       * vuex : 'game/setHeroes'
       *
       * @param {object[]} payload - the array with all heroes
       */
      setHeroes: ({ commit }, payload) => {
        commit('SET_HEROES', payload);
      },
      /**
       * Update the full game state (main + players)
       *
       * Will be called by the game master to update the game state
       *
       * vuex : 'game/update'
       *
       * @param {object} Context - vuex context
       * @param {Function} Context.commit - vuex commit func
       * @param {object} payload - the full game state
       * @param {object} payload.game - match store state in game.js
       * @param {object} payload.bluePlayer - match store state in any-player.js for blue
       * @param {object} payload.redPlayer - match store state in any-player.js for red
       */
      update: ({ commit }, payload) => {
        commit('SET_FULL_GAME_STATE', payload.game);
        commit('bluePlayer/SET_FULL_PLAYER_STATE', payload.bluePlayer);
        commit('redPlayer/SET_FULL_PLAYER_STATE', payload.redPlayer);
      },
      /**
       * Reset the whole game state
       *
       * vuex : 'game/resetGameState'
       *
       * Typically to call when game is stopped or user disconnects
       *
       * @param {object} Context - vuex context
       * @param {Function} Context.commit - vuex commit func
       */
      resetGameState: ({ commit }) => {
        commit('INIT_GAME_STATE');
        commit('bluePlayer/INIT_PLAYER_STATE');
        commit('redPlayer/INIT_PLAYER_STATE');
      },
      /**
       * Submit chosen faction to the game master
       *
       * vuex : 'game/submitMyFaction'
       *
       * @param {string} payload - the faction name (lowercase)
       */
      submitMyFaction: ({ dispatch, getters }, payload) => {
        dispatch(getters.my('submitFaction'), payload);
      }
    };
    const bluePlayer = new AnyPlayer();
    const redPlayer = new AnyPlayer();
    export default {
      namespaced: true,
      state,
      getters,
      mutations,
      actions,
      modules: {
        bluePlayer: {
          namespaced: true,
          ...bluePlayer
        },
        redPlayer: {
          namespaced: true,
          ...redPlayer
        }
      }
    };