/// <summary>
    /// Called after completion of a command is finished execuing until all the queued messages are processed.
    /// When no queued Actions left, it ends the turn for the Active player and clears player/turn specific data.
    /// </summary>
    private void OnActionCompletedCallback(Component sender, bool isSuccess)
    {
        if (!isSuccess)
        {
            GameHud gameHud = GuiManager.Instance.CurrentState as GameHud;
            if (gameHud != null)
            {
                gameHud.ShowPopup(sender.name + " has failed!", new Vector2(0.5f, 0.5f), Color.red);
            }
        }

        if (_queuedActions.Count > 0)
        {
            _queuedActions.Dequeue().Invoke();
        }
        else
        {
            TryGameOver();
            if (CurrentGameState == GameState.GameOver)
            {
                return;
            }
            Ability ability = sender as Ability;
            if (ability && ability.IsPassive)
            {
                return;
            }
            ResetActiveHexes();
            _selectedHex = null;
            TurnManager.Instance.EndTurn();

            while (true)
            {
                _activeUnit = TurnManager.Instance.GetActivePlayer().GetNextUnit();
                //Unit might be dead but delayed. Check IsDead.
                //If the player has not Available units we should not be here at all. (TryGameOver handles that.)
                //Therefore we don't have to check for a case of infinite-loop.
                if (!_activeUnit.IsDead)
                {
                    break;
                }
            }

            _selectedHex = _activeUnit.GetHexTile(_hexGrid);
            SelectHex(_selectedHex);
        }
    }
    private IEnumerator ArmyBuild()
    {
        int armySize = LoadArmyData();

        //Give everyone else time to register to events.
        yield return(null);

        CurrentGameState = GameState.ArmyBuild;
        GameHud gameHud = GuiManager.Instance.CurrentState as GameHud;

        for (int i = 0; i < armySize; i++)
        {
            int     turn       = TurnManager.Instance.CurrentTurn;
            Vector2 topLeftHex =
                Camera.main.WorldToScreenPoint(_hexGrid.GetWorldPositionOfHex(_hexGrid.GetHexTileDirect(0, 0).Coord));
            Vector2 bottomRightHex =
                Camera.main.WorldToScreenPoint(
                    _hexGrid.GetWorldPositionOfHex(
                        _hexGrid.GetHexTileDirect(_hexGrid.WidthInHexes - 1, _hexGrid.HeightInHexes - 1).Coord));
            float yMax = topLeftHex.y;
            float yMin = bottomRightHex.y;
            float xMax = bottomRightHex.x;
            float xMin = topLeftHex.x;
            while (turn == TurnManager.Instance.CurrentTurn)
            {
                SelectedUnit = TurnManager.Instance.GetActivePlayer().GetNextUnit();
                _selectedUnit.gameObject.SetActive(true);
                gameHud.ShowPopup("Place Unit", new Vector2(0.5f, 0.5f), Color.white);

                Vector3 refPosition;
                Func <float, float, float> limitFunction;
                if (TurnManager.Instance.GetActivePlayer().Id % 2 == 0)
                {
                    for (int r = 0; r < _maxSpawnDistance; r++)
                    {
                        for (int q = 0; q < _hexGrid.GetRowLenght(r); q++)
                        {
                            HexTile hexTile = _hexGrid.GetHexTileDirect(q, r);
                            hexTile.HighlightTile();
                            _hexTileCache.Add(CACHE_OTHER, hexTile);
                        }
                    }
                    refPosition =
                        _hexGrid.GetWorldPositionOfHex(
                            _hexGrid.GetHexTileDirect((int)(_hexGrid.WidthInHexes / 2f), _maxSpawnDistance - 1).Coord);
                    limitFunction = Mathf.Min;
                }
                else
                {
                    for (int r = _hexGrid.HeightInHexes - _maxSpawnDistance; r < _hexGrid.HeightInHexes; r++)
                    {
                        for (int q = 0; q < _hexGrid.GetRowLenght(r); q++)
                        {
                            HexTile hexTile = _hexGrid.GetHexTileDirect(q, r);
                            hexTile.HighlightTile();
                            _hexTileCache.Add(CACHE_OTHER, hexTile);
                        }
                    }
                    refPosition =
                        _hexGrid.GetWorldPositionOfHex(
                            _hexGrid.GetHexTileDirect((int)(_hexGrid.WidthInHexes / 2f),
                                                      _hexGrid.HeightInHexes - _maxSpawnDistance).Coord);
                    limitFunction = Mathf.Max;
                }
                float xPlayerLimit = Camera.main.WorldToScreenPoint(refPosition).x;

                Transform selectedUnitTransform = _selectedUnit.transform;
                selectedUnitTransform.position = refPosition;

                //Wait until player places the Unit.
                while (_selectedUnit != null)
                {
                    Vector2 rayPos =
                        new Vector2(limitFunction(xPlayerLimit, Mathf.Clamp(Input.mousePosition.x, xMin, xMax)),
                                    Mathf.Clamp(Input.mousePosition.y, yMin, yMax));
                    Ray        ray = Camera.main.ScreenPointToRay(rayPos);
                    RaycastHit hit;
                    if (Physics.Raycast(ray, out hit))
                    {
                        selectedUnitTransform.position = hit.point;
                    }
                    yield return(null);
                }
                TurnManager.Instance.EndTurn();
                ResetActiveHexes();
            }
        }

        WaitForSeconds wait = new WaitForSeconds(1f);

        for (int i = 3; i >= 0; i--)
        {
            gameHud.ShowPopup(i == 0 ? "Battle!" : i.ToString(), new Vector2(0.5f, 0.5f), Color.white);
            yield return(wait);
        }

        CurrentGameState = GameState.Battle;
        _activeUnit      = TurnManager.Instance.GetActivePlayer().GetNextUnit();
        _selectedHex     = _activeUnit.GetHexTile(_hexGrid);
        SelectHex(_selectedHex);
    }