#include <UdpSocket.h>
#include "NudpSocketDefines.h"

class NudpSocket : public UdpSocket
{
public:
    NudpSocket(
	    SocketHandler& h,
	    int ibufsz = NUDP_DATA_LENGTH+NUDP_HEADER_LENGTH,
	    int obufsz = NUDP_DATA_LENGTH );
    ~NudpSocket( void );

    int Bind( ipaddr_t iface, port_t port );
    bool Open( ipaddr_t host, port_t port );
    bool Suspend( void );
    
    bool SendCmd( const char number[4], const char* data = NULL, const size_t data_length = 0, const char top = 0 );
    bool SendCmd( unsigned int number, const char* data = NULL, const size_t data_length = 0, const char top = 0 );
    bool GetResponse( unsigned int* number, char* data, size_t* data_length, char* top );
    
    void OnRawData( const char* buf, size_t len, struct sockaddr* sender_addr, socklen_t sa_len );

    bool PrepareForData( char* buf_addr );
    void EmergencyDataStandBy( void );
    bool FragmentReceivedByOffset( int offset );
    bool FragmentReceivedByIndex( int index );
    bool AllDataReceived( void );
    int GetDataCount( void ) { return _data_packet_count; }
    int GetLastRawNumber( void ) { return _last_raw_num; }

    char GetLastTop( void ) { return _last_top; }
    char GetState( void ) { return _state; }
    bool GotPacket( void );
    void StopWaiting( void );
    void StopData( void );

    bool SetLogFile( FILE* log );
    bool SetErrLogFile( FILE* err_log );

private:
    char ChkSum( const char* buf );

    void Log( const char* msg );
    void LogErr( const char* msg );

    char  _state, _last_top, _chk_header[NUDP_HEADER_LENGTH];
    char* _out_packet;
    char* _in_packet;
    char* _data_buf;
    bool* _data_frag;
    bool _got_packet;
    int _data_packet_count, _last_raw_num;
    std::string _my_address;
    ipaddr_t _remote_host;
    port_t _remote_port;
    size_t _last_data_length, _obufsz;
    FILE *_log, *_err_log;
};
