/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM 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; only version 2 of the License.      
 * 
 * NMM is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 
 * License for more details.  
 * 
 * You should have received a copy of the GNU General Public License 
 * along with NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef NMM_O_NET_STREAM_HPP
#define NMM_O_NET_STREAM_HPP NMM_O_NET_STREAM_HPP

#include "nmm/nmm_prefix.hpp"

#include "nmm/comm/serialize/OStream.hpp"

#include "visibility.hpp"

namespace NMM {

  class Sock;

  /** A network output stream.
   * This class is an output stream which writes data to a network socket.
   * The actual socket write operation, including buffering strategies, is implemented in subclasses.
   */
  class DLLEXPORT ONetStream
    : public OStream
  {
  public:
    /** @name Constructor & Destructor
     */
    //@{
    /** Constructor
     */
    ONetStream();

    /** Copy constructor.
     *
     * @param other Object to copy from
     */
    ONetStream(const ONetStream& other);

    /** Virtual destructor.
     */
    virtual ~ONetStream();

    /** virtual copy constructor.
     *
     * @return A copy of this object which has the same type
     */
    virtual ONetStream* copy() const = 0;
    //@}

    /** @name Serialization Operator
     */
    //@{
    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual ONetStream&  operator<<(const nmm_uint16& value)      ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual ONetStream&  operator<<(const nmm_int16& value)     ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual ONetStream&  operator<<(const nmm_uint32& value)      ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual ONetStream&  operator<<(const nmm_int32& value)     ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual ONetStream&  operator<<(const nmm_uint64 & value)     ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this 
     */
    virtual ONetStream&  operator<<(const nmm_int64& value)       ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual ONetStream&  operator<<(const nmm_bool& value)          ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual ONetStream&  operator<<(const nmm_double& value)        ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual ONetStream&  operator<<(const nmm_float& value)         ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual ONetStream&  operator<<(const nmm_char& value)          ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual ONetStream&  operator<<(const nmm_uchar& value)  ;

    /** Output serialization operator.
     * This is the output serialization operator for a basic type.
     * This implementation converts the value to binary form and invokes the socket write method.
     *
     * @param value Reference to variable to be serialized
     * @return *this
     */
    virtual ONetStream&  operator<<(const string& value)         ;
    //@}

    /** @name Buffer Writing
     */
    //@{
    /** Write raw data to this stream.
     * This method writes the given number of raw bytes from the buffer to the stream.
     *
     * @param buffer Pointer to buffer that stores the data to be written
     * @param size Number of bytes to write
     */
    virtual void writeBuffer(const char* buffer, nmm_uint32 size);

    /** Write raw data to this stream.
     * This method writes the given number of raw bytes from the buffer to the stream.
     *
     * @param buffer Pointer to buffer that stores the data to be written
     * @param size Number of bytes to write
     */
    virtual void writeBuffer(const unsigned char* buffer, nmm_uint32 size);
    //@}

    /** @name Network Stream Methods
     */
    //@{
    /** Set the socket this stream writes to.
     * This method sets the socket this stream writes to.
     * The stream stores a pointer to the socket. The socket must not be destroyed
     * as long as this stream is using it.
     *
     * @param sock A pointer to a socket that is usable by this stream
     */
    void setSock(Sock* sock) {
      __sock = sock;
    }

    /** Get the socket this stream writes to.
     * This method gets the socket this stream writes to.
     * The returned pointer must not be deleted.
     *
     * @return A pointer to the socket that is used by this stream
     */
    Sock* getSock() {
      return __sock;
    }

    /** Get the socket this stream writes to.
     * This method gets the socket this stream writes to.
     * The returned pointer must not be deleted.
     *
     * @return A pointer to the socket that is used by this stream
     */
    const Sock* getSock() const {
      return __sock;
    }
    //@}

    /** @name Quality of Service
     */
    //@{
    /** Reset the write counter.
     * This method resets the counter which counts the number of bytes written from the socket to zero.
     */
    inline void resetWriteCounter()               { __write_counter = 0; }

    /** Count written bytes.
     * This method increases the counter which counts the number of bytes written to the socket
     * by the given amount. Subclasses call this method in their implementation of the socket write
     * method.
     *
     * @param count Number of written bytes
     */
    inline void countWriteBytes(u_int32_t count)  { __write_counter += count; }

    /** Get number of written bytes.
     *
     * @return Total number of written bytes since last reset of the counter
     */
    inline u_int32_t getWriteCounter()            { return __write_counter; }
    //@}

  protected:
    /** Subclass constructor.
     * This constructor must be used by subclasses when initializing the base class.
     * Every subclass must also define this subclass constructor as a protected constructor.
     *
     * @param ti Type information for this object
     */
    ONetStream(const TypeInfo& ti);

    /** Socket write method.
     * This method performs the actual socket write operation. It is invoked by the implementation
     * of the serialization operators. Subclasses must implement this method.
     *
     * @param data Binary data to be serialized
     * @param size Size of binary data to serialize (in bytes)
     */
    virtual void writeValue(const void* data, size_t size) = 0;

  private:
    Sock*         __sock;             ///< socket to read to write to
    ostream*      __stream;           ///< debug output stream
    u_int32_t     __write_counter;    ///< Total written bytes
  };
  
}

#include "nmm/nmm_suffix.hpp"

#endif
