    'use strict';

    /* This file will be used by server for online game, and by app for local game
    Therfore it should not have any dependency on any of those environments.

    It is a state machine that follows the game steps

    It receives a dataStore to get and share data but doesn't care what is
    behind (socket.io comm for online, direct call to vuex store for local)
    Is gives an interface in order to receive notifications

    Receiving interface :
      - dataStore : provides methods :
        - .load()          : to get saved game data
        - .save(data)      : to store game data and propagate (returns true if it succeeded, false otherwise)
        - .getHeroesJson() : to get JSON file with all heroes cards described

    Provides interface :
      - duelControllerProxy : provides methods :
        - endTurn(data) : notifies the controller that players ended current turn with attached data */

    import { initHeroesFromJson } from './heroesHelper';
    import gameStates from './gameStates/gameStates';
    let DuelController = function(dataStore) {
      let gameData = {
        game: {},
        bluePlayer: {},
        redPlayer: {}
      };
      let allHeroes = null;

      /** ***** STATE MACHINE internal methods ***** */

      // Holds current running state
      let currentGameState = null;

      // Set new current State
      let setCurrentState = stateName => {
        currentGameState = states[stateName];
        gameData.game.gameState = stateName;
        console.log('Set new state : ', stateName);
      };

      // get new State
      let getCurrentState = () => {
        return currentGameState;
      };

      // Start the current state
      let startCurrentState = (payload = null) => {
        currentGameState.start(payload);
      };

      // Update the current state
      let updateCurrentState = (payload = null) => {
        currentGameState.update(payload);
      };

      // End the current state
      let endCurrentState = (payload = null) => {
        currentGameState.end(payload);
      };

      let getGameData = () => gameData;

      // Interface to set data and store it
      let storeData = (data = null) => {
        if (data) {
          setData(data);
        }
        return dataStore.save(gameData);
      };

      // Interface to set data only
      let setData = data => {
        gameData = data;
      };

      // Interface to load data
      let loadData = () => {
        gameData = dataStore.load();
      };

      // Interface to get set of all heroes
      let getAllHeroes = () => {
        if (!allHeroes) {
          allHeroes = initHeroesFromJson(dataStore.getHeroesJson());
        }
        return allHeroes;
      };

      // Pass those state machine methods to each state
      let stateCtrl = {
        setCurrentState,
        getCurrentState,
        startCurrentState,
        updateCurrentState,
        endCurrentState,
        storeData,
        setData,
        getGameData,
        loadData,
        getAllHeroes
      };

      // declare all states
      // First state to be set after public APIs (start or resume game) are called
      let states = {
        '0_INIT': new gameStates.initState(stateCtrl),
        '1_SELECT_FACTION': new gameStates.selectFactionState(stateCtrl),
        '1_SELECT_DRAFT': new gameStates.selectDraftState(stateCtrl),
        '1_SELECT_TOURNAMENT': new gameStates.selectTournamentState(stateCtrl),
        '2_CHANGE_UP_TO_3_CARDS': new gameStates.changeUpTo3Cards(stateCtrl)
      };

      /** ***** Following are public methods ***** */

      // Method to create and start a new game (both players are there)
      let startNewGame = function(player1Name, player2Name, gameOptions) {
        // 1st state is init
        setCurrentState('0_INIT');
        //Start it
        startCurrentState({
          player1Name,
          player2Name,
          gameOptions
        });
      };

      // Method to resume existing game, gameData is passed already
      let resumeGame = function(data) {
        gameData = data;
        // Just set state per data in DB
        // This state will wait for update
        setCurrentState(gameData.game.gameState);
      };

      // Provide an interface so that players can notify the DuelController
      let DuelControllerProxy = () => {
        return {
          endTurn: data => {
            console.log('data from player :>> ', data);
            currentGameState.update(data);
          }
        };
      };

      // Return public methods
      return {
        startNewGame,
        resumeGame,
        duelControllerProxy: new DuelControllerProxy()
      };
    };

    export default DuelController;