#ifndef CNETMESSAGE_H
#define CNETMESSAGE_H

enum type_netmessage { MESSAGE_NONE, MESSAGE_MOVE, MESSAGE_PROMOTION };

////////////////////////////////////////
//                                    //
//  Class representing the data that  //
//  will travel over the network.     //
//                                    //
////////////////////////////////////////

class CNetMessage
{
  long type;
  long size;
  unsigned char * data;

 public:
  // Destructor
  ~CNetMessage() { if (data) delete []data; }

  // Constructors
  CNetMessage(type_netmessage newtype = MESSAGE_NONE)
    {
      SetType(newtype);
      SetSize(0);
      data = 0;
    }

  template <class T>
    CNetMessage(type_netmessage newtype, T* newdata, int newsize = -1)
    {
      if (newsize == -1)
        newsize = sizeof(T);

      SetType(newtype);
      SetSize(newsize);
      if (newdata)
        {
          data = new unsigned char[newsize];
          if (data == 0)
            {
              std::cerr << MEMORY_ERROR.GetErrorString();
              exit(1);
            }
          memcpy(data, newdata, newsize);
        }
      else
        {
          data = 0;
        }
    }

  // Copy constructor
  CNetMessage(const CNetMessage& copy)
    {
      type = copy.type;
      size = copy.size;
      if (copy.data)
        {
          data = new unsigned char[GetSize()];
          if (data == 0)
            {
              std::cerr << MEMORY_ERROR.GetErrorString();
              exit(1);
            }
          memcpy(data, copy.data, GetSize());
        }
      else
        {
          data = 0;
        }
    }

  // Assignment operator
  const CNetMessage& operator = (const CNetMessage& copy)
    {
      if (data)
        delete []data;

      type = copy.type;
      size = copy.size;
      if (copy.data)
        {
          data = new unsigned char[GetSize()];
          if (data == 0)
            {
              std::cerr << MEMORY_ERROR.GetErrorString();
              exit(1);
            }
          memcpy(data, copy.data, GetSize());
        }
      else
        {
          data = 0;
        }

      return (*this);
    }


  // Function to add data
  template <class T>
    void Add(T* newdata, int newsize = -1)
    {
      if (newsize == -1)
        newsize = sizeof(T);

      void * buffer = (void *) new unsigned char[GetSize() + newsize];
      if (buffer == 0)
        {
          std::cerr << MEMORY_ERROR.GetErrorString();
          exit(1);
        }

      if (data)
        {
          memcpy(buffer, data, GetSize());
          delete data;
        }

      data = buffer;
      memcpy((void *) ( (unsigned char*) (data) + GetSize()),
             newdata, newsize);
      SetSize(GetSize() + newsize);
    }


  // Data manipulation functions
  type_netmessage GetType() const { return (type_netmessage) ntohl(type); }
  const long& GetTypeLong() const { return type; }
  void SetType(type_netmessage newtype) { type = htonl((long) newtype); }
  int GetSize() const { return ntohl(size); }
  void SetSize(int newsize) { size = htonl((long) newsize); }
  const long& GetSizeLong() const { return size; }
  void SetData(void * newdata) { data = (unsigned char *) newdata; }
  void* GetData() const { return data; }


  // Message handler
  void Handle(void);
};

void* ListenNetworkMessage(void *);

// Receiving function
//
// void* ListenNetworkMessage(void *)
// {
//   static CNetMessage Mess;
//
//   while (!(n_in_out->fail()))
//     {
//       n_in_out >> Mess;
//       Mess.Handle();
//     }
// }



#endif
