#include "socket.hpp"


//------------------------- SOCKET Module -----------------------//
//						  v 05 . 03 .  2007						 //
//																 //
//								MT								 //
//---------------------------------------------------------------//


//--- Connect To Host ---//
void CSocket :: ConnectTo (char *host, int portno)
{
	socketfd = socket(AF_INET,SOCK_STREAM,0);
	
	if(socketfd==-1)   
		error.OnError(ERROR_SOCKET_CREATE);

	addr.sin_family = AF_INET;
	addr.sin_port = htons(portno);
	
	if(! inet_aton (host, & addr.sin_addr))
			error.OnError(ERROR_SOCKET_WRONG_IP);
	
	if(connect(socketfd, (struct sockaddr*)&addr, sizeof(addr)) != 0)
			error.OnError(ERROR_SOCKET_OPEN_HOST);
}


//--- Close Host ---//
void CSocket :: CloseHost() 
{
	close (socketfd);
	socketfd = -1;
	
};


//--- Allocate Buffer ---//
void CSocket :: bufalloc(int new_size, char copy)
{
	int old_size = buf_size;


		// --- realloc
	if ( (new_size > old_size) && (copy == 1))
	{
		char *buf_cpy = new char [old_size];

		for (int i = 0; i<old_size; i++)
			buf_cpy[i] = buf [i];

		buffree();
		buf = new char [new_size];

		for (int i = 0; i<old_size; i++) 
			buf [i] = buf_cpy[i];

	} else {
		//--- simple new
		buffree();
		buf = new char [new_size];
	}

	buf_size = new_size;
};


//--- Buffer Free ---//
void CSocket :: buffree()
{
	if (buf_size == 1) 
		delete buf; 
	else delete[] buf;  

	buf_size = 0;
};


//--- Socket Read ---//
void CSocket :: Read(int size)
{
	bufalloc(size, BUF_NOT_COPY);

	if(!read(socketfd, buf, size)) 
		error.OnError(ERROR_SOCKET_CONNECTION_FAULT);	
};


//--- Socket ReadNext ---//
void CSocket :: ReadNext(int size)
{
	int old_size = buf_size;
	int new_size = buf_size + size;
    	
	bufalloc(new_size);

	if(!read(socketfd, & buf[old_size], size)) 
		error.OnError(ERROR_SOCKET_CONNECTION_FAULT);
};


//--- Socket Read ---//
void CSocket :: Write (char *s)
{ 
	if ( !write(socketfd, s, strlen(s)) )
		error.OnError(ERROR_SOCKET_CONNECTION_FAULT);
};


//--- Send Game Command ---// 
void CSocket :: SendCommand (char *s)
// In end of string s will 
// be automatical add "\n"
{ 
	int size = strlen(s);
	char *tmp = new char [size + 2];
		strcpy(tmp, s); 
		tmp[size] = '\n';
		tmp[size+1] = '\0';

	Write(tmp);
	delete[] tmp;
};

//--- Send Game Command With Int ---// 
void CSocket :: SendCommandWithInt(char *s, int i)
{
	#define INT_SIZE 10
	char tmp[INT_SIZE] = {0};
	char *tmp2 = new char [strlen(s)+INT_SIZE+1];

	snprintf (tmp, INT_SIZE, "%d", i);
	strcpy(tmp2, s);
	strcat(tmp2, tmp);
		SendCommand(tmp2);
	delete[] tmp2;
};


// --- Wait a phrase ---//
int CSocket :: Wait(char* s)
{ 
	int size = strlen(s);
	char *tmp = new char [size+1];
	int i, j;
	
	tmp[size] = '\0';
	
		do {
			Read(sizeof(char));
			for (i=0;  i<size-1; i++)
				tmp[i] = tmp[i+1];
			tmp[i] = (*buf);
			 				
				//==== test
		} while( strncmp(tmp, s, size) );

	buf = strdup(tmp);
	buf_size = strlen(buf) + 1;
	delete[] tmp;

 return 1; 
}


// --- Wait 2 - or ---//
int CSocket :: Wait2(char *s, char *s2)
{ 
	int size = strlen(s);
	int size2 = strlen(s2);
	char *tmp = new char[size+1];
	char *tmp2 = new char[size2+1];
	int i;
	
	tmp[size] = '\0';
	tmp2[size2] = '\0';
		
		do {
			Read(sizeof(char));
			for (i=0;  i<size-1; i++)
				tmp[i] = tmp[i+1];
			tmp[i] = (*buf);
			 
			for (i=0;  i<size2-1; i++)
				tmp2[i] = tmp2[i+1];
			tmp2[i] = (*buf);
				
		} while( strncmp(tmp, s, size) && strncmp(tmp2, s2, size2) );

 //----------------------------------
	int res = 1;

	if (!strncmp(tmp2, s2, size2))
	 { buf = strdup(tmp2); res = -1; } 
	else buf = strdup(tmp);
//----------------------------------	

	buf_size = strlen(buf) + 1;
	delete[] tmp;
	delete[] tmp2;

 return res; 
}





// --- ReadAfterWait a phrase ----//
int CSocket :: ReadAfterWait_Int(char *s, int space, int length)
// and than read int symbols 
//     size of length. 
//    Processing space.
{	
	if ( (length < 1) && (length != -1) ) 
	{ error.OnError(ERROR_SOCKET_LENGTH_ERROR); return 0; };
	
		if (Wait(s) == -1) {
			error.OnQuietError(ERROR_SOCKET_QUIET_NOT_FIND_S);
			return -1;
		}
	
		Read(sizeof(char));
		while ( (buf [buf_size-1] != '\n') && (buf_size != length) )
			ReadNext(sizeof(char));
			    
		if ( buf [buf_size-1] != '\n') 
			bufalloc(buf_size+1);
		   
		buf [buf_size-1] = '\0';

 return atoi(buf);
}


// --- ReadAfterWait2 ----//
int CSocket :: ReadAfterWait2_Int(char *s,  char *s2, int space, int length)
// and than read int symbols 
//     size of length. 
//    Processing space.
{	
	if ( (length < 1) && (length != -1) ) 
	{ error.OnError(ERROR_SOCKET_LENGTH_ERROR); return 0; };
	
		if (Wait2(s, s2) == -1) {
			error.OnQuietError(ERROR_SOCKET_QUIET_NOT_FIND_S);
			return -1;
		}

		Read(sizeof(char));
		while ( (buf [buf_size-1] != '\n') && (buf_size != length) )
			ReadNext(sizeof(char));

		if ( buf [buf_size-1] != '\n') 
			bufalloc(buf_size+1);
		   
		    buf [buf_size-1] = '\0';

 return atoi(buf);
}



int  Read_Int();