//MySocket MySocket MySocket MySocket MySocket MySocket MySocket MySocket 
//MySocket MySocket MySocket MySocket MySocket MySocket MySocket MySocket 
//MySocket MySocket MySocket MySocket MySocket MySocket MySocket MySocket 
//MySocket MySocket MySocket MySocket MySocket MySocket MySocket MySocket 
class MySocket {
public:
	bool CONNECTED;
	bool debugmode;
	int Port;
	string Hostname;
	int packetsize;
	int sockfd, numbytes;
	char buf[4096];
	char sendbuf[1024];
	MySocket();
	int Connect();
	void SetHost(string host);
	void SetPort(int port);
	int getz(string *getdata);
	int putz(string putdata);
	void Disconnect();
	string GetIP(string hname);
private:
	struct hostent *he;
	struct sockaddr_in their_addr;
};


int MySocket::putz(string putdata) { 
	strcpy(sendbuf,putdata.c_str());
	//cout<<"SENDBUF = " << sendbuf<<endl;
	if (send(sockfd, sendbuf,putdata.length(), 0) == -1) {
		
		closesocket(sockfd); // bye!
		return -1;
	} else {
		return 0;
	}
};

int MySocket::getz(string *getdata){
	int fdmax;
	fd_set master;
	fd_set read_fds;
	FD_ZERO(&read_fds);
	FD_ZERO(&master);
	FD_SET(sockfd, &master);
	fdmax = sockfd;
	int nbytes;
	read_fds = master; // copy it

	if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
		perror("select");
		return -1;
	}
	if (FD_ISSET(sockfd, &read_fds)) {
		// handle data from a client
		if ((nbytes = recv(sockfd, buf, sizeof buf, 0)) <= 0) {
			// got error or connection closed by client
			if (nbytes == 0) {
				// connection closed
				if(debugmode){cout<<":SOCKET> Server Hung up On Socket "<<sockfd<<endl;}
			} else {
				if(debugmode){cout<<":SOCKET> Server Connection Error.\n";}
				perror("recv");
			}
			closesocket(sockfd); // bye!
			FD_CLR(sockfd, &master); // remove from master set
			return -1;
		} else {
			//finally got some data.
			buf[nbytes] = '\0';
			getdata->assign(buf);
		}
	}
	return 0;
};

void MySocket::SetPort(int port) {Port = port;};

void MySocket::SetHost(string host) {Hostname = host;};

string MySocket::GetIP(string hname){
	string ipaddress;
	struct hostent *h;
	if ((h=gethostbyname(hname.c_str())) == NULL) { // get the host info
		cout<<":SOCKET> Error Getting Host\n";
	}
	ipaddress = (inet_ntoa(*((struct in_addr *)h->h_addr)));
	return ipaddress;
};

MySocket::MySocket() {
	CONNECTED = 0;
	if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
		perror("socket");
		exit(1);
	}
};

int MySocket::Connect() {
	string ipaddress = GetIP(Hostname);
	if(debugmode){cout<<":SOCKET> Hostname "<<Hostname.c_str()<<" Resolved To "<<ipaddress<<"\n";}
	if(debugmode){cout<<":SOCKET> Connecting To "<<ipaddress<<" On Port "<<Port<<endl;}
	if ((he=gethostbyname(Hostname.c_str())) == NULL) { // get the host info
		cout<<":SOCKET> Error Getting Host\n";
	}
	their_addr.sin_family = AF_INET; // host byte order
	their_addr.sin_port = htons(Port); // short, network byte order
	their_addr.sin_addr = *((struct in_addr *)he->h_addr);
	memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
	if (connect(sockfd, (struct sockaddr *)&their_addr,sizeof their_addr) == -1) {
		perror("connect");
		return -1;
	} else {
		if(debugmode){cout<<":SOCKET> Connected!\n\n";}
		CONNECTED = 1;
		return 0;
	}
};
