/* Blinker
   Copyright 2011-2019 Stefan Schuermans <stefan@blinkenarea.org>
   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
   a blinkenarea.org project */

#ifndef BLINKER_PONG_H
#define BLINKER_PONG_H

#include <string>
#include <vector>

#include <BlinkenLib/BlinkenFrame.h>

#include "Color.h"
#include "ColorFile.h"
#include "File.h"
#include "Format.h"
#include "FormatFile.h"
#include "Game.h"
#include "Mgrs.h"
#include "Module.h"
#include "OutStreamFile.h"
#include "Time.h"
#include "TimeCallee.h"

namespace Blinker {

/// pong game
class Pong: public Game, public TimeCallee
{
public:
  /**
   * @brief constructor
   * @param[in] name module name
   * @param[in] mgrs managers
   * @param[in] dirBase base directory
   */
  Pong(const std::string &name, Mgrs &mgrs, const Directory &dirBase);

  /// virtual destructor
  virtual ~Pong();

private:
  /// copy constructor disabled
  Pong(const Pong &that);

  /// assignment operator disabled
  const Pong & operator=(const Pong &that);

public:
  /// check for update of configuration (derived game), return true on update
  virtual bool updateConfigGame();

protected:
  /// re-initialize game (e.g. due to config change)
  virtual void reinitialize();

  /// redraw current game image, expected to call sendFrame() at end
  virtual void redraw();

  /// callback when requested time reached
  virtual void timeCall();

  /**
   * @brief delay processing for computer players
   * @param[in,out] delay delay variable of computer player
   * @return whether computer player is allowed to move
   */
  bool computerDelay(int &delay) const;

  /**
   * @brief computation of ideal pad position for computer players
   * @param[in] padBallX x coordinate of position of ball when hitting the pad
   * @param[in] padY current y coordinate of pad
   * @param[out] padYmin minimum ideal y position of pad
   * @param[out] padYmax maximum ideal y position of pad
   */
  void computerComputePadPos(int padBallX, int padY,
                             int &padYmin, int &padYmax) const;

  /**
   * @brief move pad for computer players
   * @param[in] padYmin minimum desired y position of pad
   * @param[in] padYmax maximum desired y position of pad
   * @param[in,out] padPosY y position of pad
   */
  void computerMovePad(int padYmin, int padYmax, int &padPosY) const;

  /// computer player for left pad
  void computerLeft();

  /// computer player for right pad
  void computerRight();

  /// bounce ball
  void bounceBall();

  /// bounce ball at sides
  void bounceBallSide();

  /// bounce ball at left pad
  void bounceBallLeft();

  /// bounce ball at right pad
  void bounceBallRight();

  /// request next time call - or cancel request if not needed
  void planTimeCall();

  /// move ball out of the field and halt it
  void hideBall();

  /// start ball
  void startBall();

protected:
  ColorFile m_fileBallColor; ///< color file for ball color
  ColorFile m_fileLineColor; ///< color file for center line
  ColorFile m_filePadColor;  ///< color file for player pad
  ColorData m_ballColor;     ///< ball color
  ColorData m_lineColor;     ///< center line color
  ColorData m_padColor;      ///< player pad color
  int       m_ballPosX;      ///< ball position X
  int       m_ballPosY;      ///< ball position Y
  int       m_ballDirX;      ///< ball direction X
  int       m_ballDirY;      ///< ball direction Y
  int       m_padSize;       ///< size of player pads
  int       m_leftPosY;      ///< position of top pixel of left pad
  int       m_rightPosY;     ///< position of top pixel of left pad
  int       m_leftDelay;     ///< delay for coputer moving left pad
  int       m_rightDelay;    ///< delay for coputer moving left pad
}; // class Canvas

} // namespace Blinker

#endif // #ifndef BLINKER_PONG_H

