#include "doomtype.h"
#include "doomstat.h"
#include "p_local.h"
#include "sv_main.h"


//char str[256];

void WriteDebug(char *Message)
{
    FILE *fn;

    fn = fopen("cs.dbg", "a+");
    fprintf(fn, "%s", Message);
    fclose(fn);
}



//
// SV_SendPackets
//
void SV_SendPacket(client_t *cl)
{
    buf_t       send;
	byte        send_buf[MAX_UDP_PACKET];
	int         bps = 0; // bytes per second, not bits per second

    send.data = send_buf;
    send.maxsize = sizeof(send_buf);
	send.cursize = 0;

	if (cl->netbuf.overflowed || cl->reliablebuf.overflowed)
	{ 
		SZ_Clear(&cl->netbuf);
		SZ_Clear(&cl->reliablebuf);
	    SV_DropClient(parse_cl);
		return;
	}

	// save the reliable message 
	// it will be retransmited, if it's missed

	// the end of the buffer is reached
	if (cl->relpackets.cursize + cl->reliablebuf.cursize >= cl->relpackets.maxsize)
		cl->relpackets.cursize = 0;

	// copy the beginning and the size of a packet to the buffer
	cl->packetbegin[cl->packetnum] = cl->relpackets.cursize;
	cl->packetsize[cl->packetnum] = cl->reliablebuf.cursize;
	cl->packetseq[cl->packetnum] = cl->sequence;

	if (cl->reliablebuf.cursize)
		SZ_Write (&cl->relpackets, cl->reliablebuf.data, cl->reliablebuf.cursize);


	cl->packetnum++; // packetnum will never be more than 255
	                 // because sizeof(packetnum) == 1. Don't need
	                 // to use &0xff. Cool, eh? ;-)
	// copy sequence
	MSG_WriteLong(&send, cl->sequence);
    
	// copy the reliable message to the packet first
    if (cl->reliablebuf.cursize)
    {
		SZ_Write (&send, cl->reliablebuf.data, cl->reliablebuf.cursize);
		cl->reliable_bps += cl->reliablebuf.cursize;
    }

	cl->sequence++;

	// add the unreliable part if space is available and rate value
	// allows it
	if (gametic % 35)
	    bps = (int)((double)( (cl->unreliable_bps + cl->reliable_bps) * TICRATE)/(double)(gametic%35));

    if (bps < cl->rate)
	  if (cl->netbuf.cursize && (send.maxsize - send.cursize > cl->netbuf.cursize) )
	  {
         SZ_Write (&send, cl->netbuf.data, cl->netbuf.cursize);
	     cl->unreliable_bps += cl->netbuf.cursize;
	  }
    
	SZ_Clear(&cl->netbuf);
	SZ_Clear(&cl->reliablebuf);

	NET_SendPacket(send.cursize, send.data, cl->address);
}


//
// SV_AcknowledgePacket
//
void SV_AcknowledgePacket(void)
{
	client_t *cl = &clients[parse_cl];

	int sequence = MSG_ReadLong();

	// packet is missed
	if (sequence - cl->last_sequence > 1)
	{
		// resend
		for (int seq = cl->last_sequence+1; seq < sequence; seq++)
		{
			int  n;
			bool needfullupdate = true;

			for (n=0; n<256; n++)
				if (cl->packetseq[n] == seq)
				{
					needfullupdate = false;
					break;
				}

			if  (needfullupdate)
			{
				// do full update
				printf("need full update\n");
				cl->last_sequence = sequence;
				return;
			}

			MSG_WriteByte(&cl->reliablebuf, svc_missedpacket);
			MSG_WriteLong(&cl->reliablebuf, seq);
			MSG_WriteShort(&cl->reliablebuf, cl->packetsize[n]);
			if (cl->packetsize[n])
				SZ_Write (&cl->reliablebuf, cl->relpackets.data, 
					cl->packetbegin[n], cl->packetsize[n]);

			if (cl->reliablebuf.overflowed)
			{
				// do full update
				printf("need full update\n");
				cl->last_sequence = sequence;
				return;
			}

		}
	}

	cl->last_sequence = sequence;
}
