'use strict';
import { socketService } from '../../../main';
import cloneDeep from 'lodash.clonedeep';

/** @type {import('type/game').TH_PlayerGameState} */
const initPlayerState = {
  // Username of this player
  name: '',
  // Color of this player (blue or red)
  color: '',
  // Faction chosen (will stay empty if not faction mode)
  faction: '',
  // Will contain the IDs of the heroes selectable for draft mode
  draftHeroesIds: [],
  // the 12 heroes the player will be playing with
  twelveHeroes: [],
  heroesInPile: [],
  heroesInHand: [],
  heroesInCamp: [],
  heroesInDiscard: [],
  heroesInBattleLeft: [],
  heroesInBattleCenter: [],
  heroesInBattleRight: [],
  foodInCamp: 0,
  // Can see already we might have issues with left/right depending from where we look :)
  'foodInBattle/left': 0,
  'foodInBattle/center': 0,
  'foodInBattle/right': 0,
  // During military phase it will contain actions made by player to be replayed by other
  actionsPerformed: [],
  playerAvailActions: { canDrawCards: 0, canEndTurn: false, canPass: false },
  instructions: ''
};

/**
 * Description of game state model for a player
 *
 * @returns {object} Player state in vuex format
 */
export default function AnyPlayer() {
  const state = cloneDeep(initPlayerState);

  const getters = {
    color: state => {
      return state.color;
    },
    draftIds: state => {
      return state.draftHeroesIds;
    },
    twelveHeroes: state => {
      return state.twelveHeroes;
    },
    heroesInPile: state => {
      return state.heroesInPile;
    },
    heroesInHand: state => {
      return state.heroesInHand;
    },
    heroesInCamp: state => {
      return state.heroesInCamp;
    },
    heroesInDiscard: state => {
      return state.heroesInDiscard;
    },
    heroesInBattleLeft: state => {
      return state.heroesInBattleLeft;
    },
    heroesInBattleCenter: state => {
      return state.heroesInBattleCenter;
    },
    heroesInBattleRight: state => {
      return state.heroesInBattleRight;
    },
    heroesIn: (state, getters) => position => {
      return getters['heroesIn' + position];
    },
    playerAvailActions: state => state.playerAvailActions,
    canDrawCards: state => state.playerAvailActions.canDrawCards,
    canPass: state => state.playerAvailActions.canPass,
    canEndTurn: state => state.playerAvailActions.canEndTurn,
    instructions: state => state.instructions
  };

  const mutations = {
    SET_FULL_PLAYER_STATE: (state, payload) => {
      Object.assign(state, payload);
    },
    INIT_PLAYER_STATE: state => {
      Object.assign(state, initPlayerState);
      state.heroesInHand = [];
      state.heroesInPile = [];
    },
    ADD_IN_DRAFT_IDS: (state, payload) => {
      state.draftHeroesIds.push(payload);
    },
    REMOVE_IN_DRAFT_IDS: (state, payload) => {
      state.draftHeroesIds = state.draftHeroesIds.filter(id => id !== payload);
    },
    SET_HEROES_IN_POSITION: (state, payload) => {
      let position = payload.position;
      let ids = payload.ids;
      state['heroesIn' + position] = ids;
    },
    SET_PLAYER_AVAIL_ACTIONS: (state, payload) => {
      state.playerAvailActions = payload;
    },
    SET_TWELVE_HEROES: (state, payload) => {
      state.twelveHeroes = payload;
    }
  };

  const actions = {
    submitFaction: ({ commit, state }, payload) => {
      commit(
        'game/SET_WAITING_FOR',
        { color: state.color, value: false },
        { root: true }
      );
      socketService
        .endTurn({ color: state.color, faction: payload })
        .catch(err => {
          console.log('Error sending data : ', err);
          //Unvalid submit
          commit(
            'game/SET_WAITING_FOR',
            { color: state.color, value: true },
            { root: true }
          );
        });
    },
    submitChosenIds: ({ commit, state, rootGetters }) => {
      commit(
        'game/SET_WAITING_FOR',
        { color: state.color, value: false },
        { root: true }
      );
      socketService
        .endTurn({ color: state.color, chosenIds: rootGetters.chosenIds })
        .then(() => {
          commit('CLEAR_CHOSEN_IDS', null, { root: true });
        })
        .catch(err => {
          console.log('Error sending data : ', err);
          //Unvalid submit
          commit(
            'game/SET_WAITING_FOR',
            { color: state.color, value: true },
            { root: true }
          );
        });
    },
    submitReplace3CardsTurn: ({ commit, state, rootState }) => {
      commit(
        'game/SET_WAITING_FOR',
        { color: state.color, value: false },
        { root: true }
      );
      let heroesInHand = state.heroesInHand;
      let heroesInPile = state.heroesInPile;
      let chosenIds = rootState.chosenIds;
      heroesInPile.push(...chosenIds);
      heroesInHand = heroesInHand.filter(heroId => !chosenIds.includes(heroId));

      commit('SET_HEROES_IN_POSITION', {
        position: 'Pile',
        ids: heroesInPile
      });
      commit('SET_HEROES_IN_POSITION', {
        position: 'Hand',
        ids: heroesInHand
      });
      commit('CLEAR_CHOSEN_IDS', null, { root: true });
      /**@type {import('type/comm').TH_MessageReplace3CardsStep} */
      let message = {};
      message.color = state.color;
      message.heroesInHand = state.heroesInHand;
      message.heroesInPile = state.heroesInPile;
      socketService
        .endTurn(message)
        .then(() => {})
        .catch(err => {
          console.log('Error sending data : ', err);
          //Unvalid submit
          commit(
            'game/SET_WAITING_FOR',
            { color: state.color, value: true },
            { root: true }
          );
        });
    },
    addInDraftIds: ({ commit }, payload) => {
      commit('ADD_IN_DRAFT_IDS', payload);
    },
    removeInDraftIds: ({ commit }, payload) => {
      commit('REMOVE_IN_DRAFT_IDS', payload);
    },
    draw: ({ commit, getters }, payload = 1) => {
      // Possibility to draw multiple cards
      for (let index = 0; index < payload; index++) {
        /** @type {number[]} */
        let heroesInPile = getters.heroesIn('Pile');
        let heroesInHand = getters.heroesIn('Hand');

        heroesInHand.push(heroesInPile.shift());
        commit('SET_HEROES_IN_POSITION', {
          position: 'Pile',
          ids: heroesInPile
        });
        commit('SET_HEROES_IN_POSITION', {
          position: 'Hand',
          ids: heroesInHand
        });
      }
      let actions = getters.playerAvailActions;
      actions.canDrawCards = 0;
      actions.canEndTurn = true;
      commit('SET_PLAYER_AVAIL_ACTIONS', actions);
    }
  };
  return {
    namespace: true,
    state,
    getters,
    mutations,
    actions
  };
}
