#ifndef __JSYSTEM__JKEYPRESS__
#define __JSYSTEM__JKEYPRESS__

#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <istream>
#include <ostream>

#include "JLang/JFileDescriptorMask.hh"
#include "JLang/JTimeval.hh"


/**
 * \file
 * Keyboard settings for unbuffered input.
 * \author mdejong
 */
namespace JSYSTEM {}
namespace JPP { using namespace JSYSTEM; }

namespace JSYSTEM {

  using JLANG::JFileDescriptorMask;
  using JLANG::JTimeval;


  /**
   * Enable unbuffered terminal input.
   */
  class JKeypress {
  public:
    /**
     * Constructor.
     *
     * The settings are modified by the constructor and
     * the original settings are reset by the destructor.
     *
     * \param  echo         enable/disable echo of input character
     */
    JKeypress(const bool echo = true) 
    {
      tcgetattr(STDIN_FILENO, &termcap);

      termios buffer = termcap;

      // Disable canonical mode, and set buffer size to 1 byte.
 
      buffer.c_lflag     &= ~ICANON;
      buffer.c_lflag     &= (echo ? ECHO : ~ECHO);
      buffer.c_cc[VTIME]  = 0;
      buffer.c_cc[VMIN]   = 1;

      tcsetattr(STDIN_FILENO, TCSANOW, &buffer);
    }


    /**
     * Destructor.
     */
    ~JKeypress()
    {
      tcsetattr(STDIN_FILENO, TCSANOW, &termcap);
    }


    /**
     * Get single character.
     * This method returns as soon as input from terminal is available.
     *
     * \return              character
     */
    char get()
    {
      char c;

      ::read(STDIN_FILENO, &c, 1);

      return c;
    }


    /**
     * Timeout method.
     * This method returns immediatly if input from terminal is available,
     * else after the specified timeout period.
     *
     * \param  timeout      timeout 
     * \return              true if input available; else false
     */
    bool timeout(JTimeval timeout)
    {
      mask.set(STDIN_FILENO);
      
      return mask.in_avail(timeout);
    }
    

  private:
    termios             termcap;
    JFileDescriptorMask mask;

    JKeypress(const JKeypress&);
    JKeypress(JKeypress&&);
    JKeypress& operator=(const JKeypress&);
    JKeypress& operator=(JKeypress&&);
  };
}

#endif