#include "MsgQ.h"
#include <string.h>

#ifdef MS_WIN
#include <winsock.h>
#else
#include <netinet/in.h>
#endif

#include "server.h"
#include "defs.h"
#include "move.h"

const long CommandId = 0xbadbeef;

MsgQ::~MsgQ()
{
  mesgl = mesgs;
  while (mesgl) {
    Msg m = mesgl.Delete();
    delete m.buf;
  }
}

int operator>>(MsgQ &q, long &n)
{
  Msg m;
  int ret;
  if (ret = q >> m) {
    n = ntohl(*(long *)m.buf);
    delete m.buf;
  }
  return ret;
}

int operator>>(MsgQ &q, int &n)
{
  Msg m;
  int ret;
  if (ret = q >> m) {
    long l = ntohl(*(long *)m.buf);
    delete m.buf;
    n = l;
  }
  return ret;
}

void operator<<(MsgQ &q, long n)
{
  long *buf = new long;
  *buf = htonl(n);
  q << Msg((char *)buf, sizeof(long));
}

int operator>>(MsgQ &q, PieceMove &move)
{
  Msg m;
  int ret;
  if (ret = q >> m) {
    memcpy((char *)&move, m.buf, sizeof(PieceMove));
    move.HostOrder();
    delete m.buf;
  }
  return ret;
}

void operator<<(MsgQ &q, PieceMove move)
{
  PieceMove *ptr = new PieceMove(move);
  ptr->NetworkOrder();
  q << Msg((char *)ptr, sizeof(PieceMove));
}

int operator>>(MsgQ &q, char *(&str))
{
  Msg m;
  int ret;
  if (ret = q >> m)
    str = m.buf;
  return ret;
}

void operator<<(MsgQ &q, char *str)
{
  q << Msg(strdup(str), strlen(str)+1);
}

void operator<<(MsgQ &q, MsgQ &q1)
{
  Msg m;
  while (q1 >> m)
    q << m;
}

int MsgQ::IsCmd(long &cmd, long &arg)
{
  if (Count() == 0) return 0;
  Msg m;
  PeekHead(m);
  if (m.len != sizeof(long)*3) return 0;
  long *buf = (long *)m.buf;
  if (buf[0] != htonl(CommandId)) return 0;
  *this >> m;
  cmd = ntohl(buf[1]);
  arg = ntohl(buf[2]);
  delete [] buf;
  return 1;
}

void MsgQ::AddCmd(long cmd, long arg)
{
  long *buf = new long[3];
  buf[0] = htonl(CommandId);
  buf[1] = htonl(cmd);
  buf[2] = htonl(arg);
  *this << Msg((char *)buf, sizeof(long)*3);
}

MsgQ *MsgQ::Copy()
{
  MsgQ *q = new MsgQ;
  Lister<Msg> lister = mesgs;
  while (lister) {
    Msg m = lister.Elem();
    char *buf = new char[m.len];
    memcpy(buf, m.buf, m.len);
    *q << Msg(buf, m.len);
    lister.Next();
  }
  return q;
}

// send's a queue to the server
void SendQ(MsgQ *q)
{
  if (playerId == 0) // we're the server
    ServerGotData(q, -1, 0);
  else // sock is the conn to the server
    SendQ(sock, q);
}
