#ifndef __JDAQHIT__
#define __JDAQHIT__

#ifndef __CINT__
#include <netinet/in.h>
#endif

#include "JIO/JSerialisable.hh"
#include "JDAQ/JDAQ.hh"
#include "JDAQ/JDAQRoot.hh"
#include "JDAQ/JDAQException.hh"


namespace KM3NETDAQ {

  namespace {
    using JIO::JReader;
    using JIO::JWriter;
  }


  /**
   * Hit data structure.
   *
   * The pragma statement is necessary to ensure the correct size of this object.
   * This also implies that the destructor cannot be virtual.
   */
#pragma pack(push,1)
  class JDAQHit
  {
  public:

    typedef  unsigned char             JPMT_t;    //!< PMT channel in FPGA
    typedef  unsigned int              JTDC_t;    //!< leading edge [ns]
    typedef  unsigned char             JTOT_t;    //!< time over threshold [ns]


    /**
     * Default constructor.
     */
    JDAQHit()
    {}


    /**
     * Constructor.
     *
     * \param  pmt_id         PMT channel
     * \param  tdc_ns         time of hit         [ns]
     * \param  tot_ns         time over threshold [ns]
     */
    JDAQHit(const JPMT_t pmt_id,
	    const JTDC_t tdc_ns,
	    const JTOT_t tot_ns) :
      pmt(pmt_id),
      tdc(htonl(tdc_ns)),
      tot(tot_ns)
    {}
    

    /**
     * No virtual destructor!
     */
    /*
    virtual ~JDAQHit()
    {}
    */


    /**
     * Get PMT.
     *
     * \return                PMT
     */
    inline JPMT_t getPMT() const
    { 
      return pmt;
    }


    /**
     * Get time.
     *
     * \return                tims [ns]
     */
    inline JTDC_t getT() const
    { 
      return ntohl(tdc);
    }


    /**
     * Get pulse tot.
     *
     * \return                pulse tot [ns]
     */
    inline JTOT_t getToT() const
    { 
      return tot;
    }


    /**
     * Read DAQ hit from input.
     *
     * \param  in             JReader
     * \param  hit            JDAQHit
     * \return                JReader
     */
    friend inline JReader& operator>>(JReader& in, JDAQHit& hit)
    {
      in >> hit.pmt;
      in >> hit.tdc;
      in >> hit.tot;

      return in;
    }


    /**
     * Write DAQ hit to output.
     *
     * \param  out           JWriter
     * \param  hit           JDAQHit
     * \return               JWriter
     */
    friend inline JWriter& operator<<(JWriter& out, const JDAQHit& hit)
    {
      out << hit.pmt;
      out << hit.tdc;
      out << hit.tot;
      
      return out;
    }


    /**
     * Get size of object.
     *
     * \return               number of bytes
     */
    static int sizeOf()
    {
      return sizeof(JDAQHit);
    }


    ClassDefNV(JDAQHit,1);


  protected:
    JPMT_t pmt;       //!< PMT channel in FPGA
    JTDC_t tdc;       //!< leading edge        [ns]
    JTOT_t tot;       //!< time over threshold [ns]
  };
#pragma pack(pop)


  /**
   * Less than operator for DAQ hits.
   *
   * \param  first   hit
   * \param  second  hit
   * \result         true if first hit earlier than second; else false
   */
  inline bool operator<(const JDAQHit& first,
			const JDAQHit& second)
  {
    if (first.getT() != second.getT())
      return first.getT()   < second.getT();
    else
      return first.getPMT() < second.getPMT();
  }


  /**
   * Equal operator for DAQ hits.
   *
   * \param  first   hit
   * \param  second  hit
   * \result         true if first hit earlier than second; else false
   */
  inline bool operator==(const JDAQHit& first,
			 const JDAQHit& second)
  {
    return first.getT() == second.getT() && first.getPMT() == second.getPMT();
  }
}

#endif