/***************************************************************************
                          directconnectionbase.h -  description
                             -------------------
    begin                : Tue 12 27 2005
    copyright            : (C) 2005 by Diederik van der Boor
    email                : vdboor --at-- codingdomain.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef DIRECTCONNECTIONBASE_H
#define DIRECTCONNECTIONBASE_H

#include <QAbstractSocket>
#include <QTime>
#include <QTimer>


class QTcpSocket;
class QTcpServer;
class QBuffer;



/**
 * The class for receiving and sending files.
 *
 * @author Diederik van der Boor
 * @ingroup NetworkExtra
 */
class DirectConnectionBase : public QObject
{
  Q_OBJECT

  public:
    // The constructor
                           DirectConnectionBase(QObject *parent = 0);
    // The destructor
    virtual               ~DirectConnectionBase();

    // Close the connection
    virtual void           closeConnection();
    // Register a slot which will be called each time the write buffer is empty
    void                   connectWriteHandler(QObject *receiver, const char *slot);
    // Unregister the slot which will be called each time the write buffer is empty
    void                   disconnectWriteHandler(QObject *receiver, const char *slot);
    // Return true if the last write action failed.
    bool                   hasLastWriteFailed() const;
    // Return true when the write buffer is full at the moment
    bool                   hasTemporaryWriteError() const;
    // Find out if the connection has been inactive since 15 minutes
    bool                   hasTimedOut() const;
    // Initialize the connection, return true when this was succesful
    virtual bool           initialize();
    // Return whether the connection login was successful.
    virtual bool           isAuthorized() const;
    // Return true if a connection is active
    bool                   isConnected() const;
    // Return true if this class acts as server, false if it acts as client.
    bool                   isServer() const;
    // Return true when a write handler is connnected.
    bool                   isWriteHandlerConnected() const;
    // Get the server port that will be used
    quint16                getLocalServerPort();
    // Get the remote ip the socket is connected with.
    QString                getRemoteIp() const;
    // Get the remote port the socket is connected with.
    quint16                getRemotePort() const;
    // Return the error description
    QString                getSocketError() const;
    // Connect to a host
    bool                   openConnection( const QString &ipAddress, const quint16 port );
    // Wait for an incoming connection
    bool                   openServerPort();

  protected slots:
    // This is called when the connection is established
    virtual void           slotConnectionEstablished();
    // This is called when the connection could not be made.
    virtual void           slotConnectionFailed();
    // This is called when data is received from the socket.
    virtual void           slotSocketDataReceived() = 0;

  private slots:
    // Accept incoming connections on the socket.
    void                   slotAcceptConnection();
    // A timeout occured to connect a socket
    void                   slotConnectionTimeout();
    // Signal that the connection was established
    void                   slotSocketConnected();
    // Signal that the connection was closed
    void                   slotSocketDisconnected();
    // Signal that the connection could not be made.
    virtual void           slotSocketError( QAbstractSocket::SocketError error );
    // Slot called when the socket is ready to write data.
    void                   slotSocketReadyWrite( qint64 bytesWritten );

  protected: // Protected methods
    // Close and delete the server socket
    bool                   closeServerSocket();
    // Return the number of bytes which are already received in the local buffer
    qint64                 getAvailableBytes() const;
    // Return the name of the locally opened port.
    QString                getListeningServiceName() const;
    // Verify how many bytes the read buffer has. Note this actually reads the data to test it.
    qint64                 peekBlock( const qint64 size );
    // Read data from the socket
    qint64                 readBlock( char *buffer, const qint64 size );
    // Read data from the socket (uses the QByteArray size() as block size)
    qint64                 readBlock( QByteArray &buffer, const qint64 maxSize = 0, const qint64 offset = 0 );
    // Read data from the socket (stored it in a QBuffer)
    qint64                 readBlock( QBuffer &buffer, const qint64 maxSize = 0 );
    // Mark the remote host as authorized (usually after the handshake was successful)
    void                   setAuthorized(bool authorized);
    // Write data to the socket
    bool                   writeBlock( const char *block, const qint64 size );
    // Write data to the socket
    bool                   writeBlock( const QByteArray &block );

  private:  // Private methods
    // Close and delete the client socket
    bool                   closeClientSocket();

  protected: // Protected attributes
    // Time of last activity
    QTime                  lastActivity_;

  private: // Private attributes
    // Additional write buffer when the socket reports it can't write all data.
    QByteArray             additionalWriteBuffer_;
    // Whether the connection handshake was successful
    bool                   authorized_;
    // The location openConnection() is connecting to, for debugging
    QString                connectingTo_;
    // The timeout handling for openConnection()
    QTimer                 connectionTimer_;
    // The higher limit to the interval of server ports this class will use
    quint16                highestServerPortLimit_;
    // Whether the class acts as server or client
    bool                   isServer_;
    // Whether the last write action failed.
    bool                   lastWriteFailed_;
    // The lower limit to the interval of server ports this class will use
    quint16                lowestServerPortLimit_;
    // The server socket which listens for incoming connections.
    QTcpServer            *server_;
    // The server port this class will use
    quint16                serverPort_;
    // The next server port used with a openServerPort() call.
    static quint16         nextServerPort_;
    // The socket over which data is sent or received.
    QTcpSocket            *socket_;
    // Whether an timeout occured
    bool                   timeout_;
    // True if the user cancelled the session
    bool                   userCancelled_;
    // The number of write handlers.
    int                    writeHandlerCount_;

  signals:
    // Signal that the connection was autorized
    void                   connectionAuthorized();
    // Signal that the connection was closed
    void                   connectionClosed();
    // Signal that the connection was established
    void                   connectionEstablished();
    // Signal that the connection was failed
    void                   connectionFailed();
    // Signal that the socket is ready to write data (use connectWriteHandler() instead)
    void                   writeHandlerReady();
};

#endif
