#pragma region CPL License
/*
Nuclex Native Framework
Copyright (C) 2002-2013 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library 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
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#pragma endregion // CPL License
#ifndef NUCLEX_INPUT_INPUTMANAGER_H
#define NUCLEX_INPUT_INPUTMANAGER_H
#include "Config.h"
#include "Devices/GamePad.h"
#include "Devices/Keyboard.h"
#include "Devices/Mouse.h"
#include "Devices/TouchPanel.h"
namespace Nuclex { namespace Input {
  // ------------------------------------------------------------------------------------------- //
  /// Provides access to the system's input devices
  /// 
  ///   
  ///     This service provides a uniform way to access all input devices connected
  ///     to the system. Its design philosophy is that the you are guaranteed the existence
  ///     of 1 mouse, 1 keyboard, 8 game pads / joysticks and 1 touch panel. If any
  ///     of these devices are not available, they're replaced by a dummy device which
  ///     returns a neutral state. 
  ///   
  ///   
  ///     So instead of putting the burden of querying the number of input devices,
  ///     adjusting your input handlers to cope with devices disappearing and reappearing
  ///     while the game runs, your game can simply continue. You can optionally query
  ///     IsAttached() if you want to stop the game and tell the player to reattach his
  ///     controller or something, but this is entirely optional.
  ///   
  /// 
  class InputManager {
    /// Initializes a new input manager
    protected: InputManager() : snapshotCount(0) {}
    /// Destroys the input manager
    public: virtual ~InputManager() {}
    /// Counts the number of keyboards present
    /// The number of keyboards present on the system
    /// 
    ///   You are guaranteed at least 1 keyboard in all cases, including on mobile
    ///   platforms, where you will be provided with a dummy.
    /// 
    public: virtual std::size_t CountKeyboards() const = 0;
    /// Accesses a keyboard
    /// Index of the keyboard that will be returned
    /// The keyboard with the specified index
    public: virtual const Devices::Keyboard &GetKeyboard(std::size_t index) const = 0;
    /// Accesses a keyboard
    /// Index of the keyboard that will be returned
    /// The keyboard with the specified index
    public: virtual Devices::Keyboard &GetKeyboard(std::size_t index) = 0;
    /// Counts the number of mice present
    /// The number of mice present on the system
    /// 
    ///   You are guaranteed at least 1 mouse in all cases, including on mobile
    ///   platforms, where you will be provided with a dummy.
    /// 
    public: virtual std::size_t CountMice() const = 0;
    /// Accesses a mouse
    /// Index of the mouse that will be returned
    /// The mouse with the specified index
    public: virtual const Devices::Mouse &GetMouse(std::size_t index) const = 0;
    /// Accesses a mouse
    /// Index of the mouse that will be returned
    /// The mouse with the specified index
    public: virtual Devices::Mouse &GetMouse(std::size_t index) = 0;
    /// Counts the number of game pads present
    /// The number of game pads present on the system
    /// 
    ///   You are guaranteed at least 4 game pads in all cases, including on mobile
    ///   platforms. If fewer than 4 game pads are connected, dummies will take
    ///   the place of the missing devices.
    /// 
    public: virtual std::size_t CountGamePads() const = 0;
    /// Accesses a game pad
    /// Index of the game pad that will be returned
    /// The game pad with the specified index
    public: virtual const Devices::GamePad &GetGamePad(std::size_t index) const = 0;
    /// Accesses a game pad
    /// Index of the game pad that will be returned
    /// The game pad with the specified index
    public: virtual Devices::GamePad &GetGamePad(std::size_t index) = 0;
    /// Counts the number of touch panels present
    /// The number of touch panels present on the system
    /// 
    ///   You are guaranteed at least 1 touch panel in all cases, including on
    ///   gaming consoles, where you will be provided with a dummy.
    /// 
    public: virtual std::size_t CountTouchPanels() const = 0;
    /// Accesses a touch panel
    /// Index of the touch panel that will be returned
    /// The game pad with the specified index
    public: virtual const Devices::TouchPanel &GetTouchPanel(std::size_t index) const = 0;
    /// Accesses a touch panel
    /// Index of the touch panel that will be returned
    /// The game pad with the specified index
    public: virtual Devices::TouchPanel &GetTouchPanel(std::size_t index) = 0;
    /// Updates the state of all input devices
    public: NUCLEX_INPUT_API virtual void Update();
    /// Takes a snapshot of the current state of all input devices
    /// 
    ///   
    ///     The snapshot will be queued until the user calls the Update() method, at which
    ///     point the next stored snapshot will be taken from the queue and provided as
    ///     the current state.
    ///   
    ///   
    ///     This can be used to make input independent of the game's frame rate - instead
    ///     of polling input once per frame, a thread can take snapshots of all input devices
    ///     at regular intervals and these snapshots can then be processed one after another
    ///     during the next update phase (note that this requires time-stepped instead of
    ///     a time-scaled updates)
    ///   
    ///   
    ///     If the snapshot queue is empty, a call to update will poll the input devices
    ///     right then and there at no additional overhead, so feel free to ignore this method
    ///     if your game doesn't need that kind of complexity!
    ///   
    /// 
    public: NUCLEX_INPUT_API virtual void TakeSnapshot();
    /// Clears the snapshot queue
    public: NUCLEX_INPUT_API virtual void ClearSnapshots();
    /// Returns the number of snapshots currently queued
    /// The number of input device snapshots currently in the queue
    public: virtual std::size_t CountSnapshots() const { return this->snapshotCount; }
    private: InputManager(const InputManager &);
    private: InputManager &operator =(const InputManager &);
    /// Number of snapshots the input devices should have
    private: std::size_t snapshotCount;
  };
  // ------------------------------------------------------------------------------------------- //
}} // namespace Nuclex::Input
#endif // NUCLEX_INPUT_INPUTMANAGER_H