//  SuperTuxKart - a fun racing game with go-kart
//  Copyright (C) 2009-2015 Marianne Gagnon
//
//  This program is free software; you can redistribute it and/or
//  modify it under the terms of the GNU General Public License
//  as published by the Free Software Foundation; either version 3
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.


#ifndef STATE_MANAGER_HPP
#define STATE_MANAGER_HPP

/**
  * \defgroup states_screens
  * Contains the various screens and dialogs of the STK user interface,
  * using the facilities of the guiengine module.
  */

#include <string>


#include "../guiengine/abstract_state_manager.h"
#include "../utils/ptr_vector.h"

class InputDevice;
struct Input;


namespace GUIEngine
{
    class Widget;
}

/**
  * \brief the player ID of the "game master" player
  * the game master is the player that can perform the game setup
  * \ingroup states_screens
  */
const static int PLAYER_ID_GAME_MASTER = 0;

/**
  * \brief A concrete scene manager, derived from GUIEngine's
  * AbastractSceneManager
  * \ingroup states_screens
  */
class StateManager : public GUIEngine::AbstractStateManager
{

    void updateActivePlayerIDs();


public:

    /**
      * Represents a player that is currently playing.
      * Ties together :
      *   - a player's identity (and thus his/her highscores)
      *   - which input device is used by which player
      *  (we're very flexible on this; ActivePlayer #1
      *   can choose to e.g. use profile #5 and device #2)
      */
    class ActivePlayer
    {
        friend class StateManager;

        InputDevice   *m_device;


        /** ID of this player within the list of active players */
        int m_id;


#ifdef DEBUG
        unsigned int m_magic_number;
#endif

    public:


#ifdef DEBUG
        bool ok()
        {
            return (m_magic_number == 0xAC1EF1AE);
        }   // ok
#endif




        // --------------------------------------------------------------------
        /** ID of this player within the list of active players */
        int getID() const
        {
#ifdef DEBUG
            assert(m_magic_number == 0xAC1EF1AE);
#endif
            return m_id;
        }   // getID
        // --------------------------------------------------------------------

        /** \return Which input device this player is using, or NULL if none
         *  is set yet */
        InputDevice* getDevice() const
        {
#ifdef DEBUG
            assert(m_magic_number == 0xAC1EF1AE);
#endif
            return m_device;
        }   // getDevice

        // --------------------------------------------------------------------
        void setDevice(InputDevice* device);







    };   // ActivePlayer



    /** \return    the PlayerProfile of a given ActivePlayer.
      * \param id  the ID of the active player for whichyou want the profile
      */



    unsigned int activePlayerCount();
    void resetActivePlayers();

    /** \return whether to reduce FPS at the moment
      * \note   this can be useful to avoid being too CPU/GPU intensive in
      *         parts of the game that don't require high framerates, like
      *         menus
      */
    bool throttleFPS();

    /** \brief implementing callback from base class AbstractStateManager */
    void escapePressed();

    /** \brief implementing callback from base class AbstractStateManager */
    virtual void onGameStateChange(GUIEngine::GameState new_state);

    /** \brief implementing callback from base class AbstractStateManager */
    virtual void onStackEmptied();

    /** \brief implementing callback from base class AbstractStateManager */
    virtual void onTopMostScreenChanged();

    // singleton
    static StateManager* get();
    static void deallocate();


};

#endif
