void ConvertToLowerCase(std::string& str)
{
	std::transform(str.begin(),str.end(),str.begin(),tolower);
	// You may need to cast the above line to (int(*)(int)) tolower
}
///IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT
///IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT
///IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT  IRCBOT IRCBOT IRCBOT
class IrcBot {
public:
	string indata;
	string Hostname;
	int Port;
	char myhost[256];
	string MyNick;
	string MyPass;
	MySocket IrcSock;
	IrcBot(string host,int port,string nick, string pass);
	int Start();
	void ProcessIrc();
	void Parse(string data);
	void putz(string data);
	bool Die;
private:
	string GodMode;
	string God;
	bool Connected;
};

IrcBot::IrcBot(string host,int port,string nick, string pass) {
	IrcSock.SetHost(host);
	IrcSock.SetPort(port);
	Hostname = host;
	Port = port;
	MyNick = nick;
	MyPass = pass;
	Connected = 0;
	Die = 0;
};

int IrcBot::Start() {
	IrcSock.debugmode = 1;
	if(IrcSock.Connect() != -1) {
		return 1;
	} else {
		return 0;
	}

};

void IrcBot::putz(string data) {
	if ( IrcSock.putz(data) != -1 ) {
		//Success
		
	} else {
		//Disconnected
		cout<<":MRC0DE> OH SHIT LOST CONNECTION"<<endl;
		while(1){}
	}
};

void IrcBot::ProcessIrc() {
	if(IrcSock.getz(&indata) != -1) {
		if(indata.length() > 0) {
			string line;
			while(indata.find("\n") != string::npos && indata.length() > 0) {
				line = indata.substr(0,indata.find("\n"));
				Parse(line);
				indata.replace(0,indata.find("\n")+1,"");
			}
		}
	} else {
		//OH SHIT LOST CONNECTION
		cout<<":MRC0DE> OH SHIT LOST CONNECTION"<<endl;
		while(1){}
	}

};

void IrcBot::Parse(string data) {
	bool noparse = 1;
	string fulldata = data;
	string dtag;
	if (data.find(":") == 0) {
		data = data.substr(1,data.length()); //Strip Prefix ':'
		dtag = data.substr(0,data.find(" ")); //capture dtag (usually hostname of server)
		ConvertToLowerCase(dtag);
		ConvertToLowerCase(Hostname);
		if (dtag == Hostname) {
			data = data.substr(data.find(" ")+1,data.length()); //Strip Up To first WhiteSpace And Save * After
			//At this point both the : and hostname have been stripped... IF PRESENT.
			//This shit is tricky cuz some servers send different stuff @ different times in different ways
			//So we had to find the one pattern that could be matched by all and would miss none of them
			//If we succeed. The Bot Works Everywhere. If Not, it sinks.
		}
	}
	if ( data.find("NOTICE AUTH :") == 0) { //Wow... Undernet Doesnt Send any host data. Just NOTICE AUTH No Space 
		//Remains of Data
		//" NOTICE AUTH :*** Looking up your hostname..."
		if (!Connected) {
			Connected = 1;
			string login = "NICK " + MyNick + "\n";
			cout<<"<NICK: NICK " << MyNick<<endl;
			putz(login);
			gethostname(myhost, (sizeof myhost));
			login = "USER " + MyNick + " " + myhost + " " + MyNick + " :Bot Forged @ NeuroticNetworks.com" + "\n";
			cout<<"<USER: USER "<<MyNick<<" "<<myhost<<" "<<MyNick<< " :Bot Forged @ NeuroticNetworks.com"<<endl;
			putz(login);
		}
		cout<<":NOTICE_AUTH> "<<data.substr(data.find(":") + 1)<<endl;
		noparse = 0;
	} else if (data.find("PING :") == 0) {
		string pong = data.substr(data.find(":",0)+1,data.length());
		cout<<":PING> "<<pong<<endl;
		cout<<"<PONG: "<<pong<<endl;
		pong = "PONG " + pong + "\n";
		putz(pong);
		noparse = 0;
	} else if (data.find("001 ") == 0) {
		//001 Welcome Line
		string line001 = data.substr(data.find(":"),data.length());
		cout<<":001> "<<line001<<endl;
		noparse = 0;
	} else if (data.find("002 ") == 0) {
		//002 Welcome Line
		string line002 = data.substr(data.find(":"),data.length());
		cout<<":002> "<<line002<<endl;
		noparse = 0;
	} else if (data.find("003 ") == 0) {
		//003 Welcome Line
		string line003 = data.substr(data.find(":"),data.length());
		cout<<":003> "<<line003<<endl;
		noparse = 0;
	} else if (data.find("004 ") == 0) {
		string line004 = data.substr(data.find(MyNick),data.length());
		line004 = line004.substr(line004.find(" ") + 1,line004.length());
		cout<<":004> "<<line004<<endl;
		noparse = 0;
	} else if (data.find("005 ") == 0) {
		string line005 = data.substr(data.find(MyNick),data.length());
		line005 = line005.substr(line005.find(" ") + 1,line005.length());
		cout<<":005> "<<line005<<endl;
		noparse = 0;
	} else if (data.find("251 ") == 0) {
		string line251 = data.substr(data.find(":"),data.length());
		cout<<":251> "<<line251<<endl;
		noparse = 0;
	} else if (data.find("252 ") == 0) {
		string line252 = data.substr(data.find(MyNick),data.length());
		line252 = line252.substr(line252.find(" ") + 1,line252.length());
		cout<<":252> "<<line252<<endl;
		noparse = 0;
	} else if (data.find("254 ") == 0) {
		string line254 = data.substr(data.find(MyNick),data.length());
		line254 = line254.substr(line254.find(" ") + 1,line254.length());
		cout<<":254> "<<line254<<endl;
		noparse = 0;
	} else if (data.find("255 ") == 0) {
		string line255 = data.substr(data.find(":"),data.length());
		cout<<":255> "<<line255<<endl;
		noparse = 0;
	} else if (data.find("265 ") == 0) {
		string line265 = data.substr(data.find(":"),data.length());
		cout<<":265> "<<line265<<endl;
		noparse = 0;
	} else if (data.find("266 ") == 0) {
		string line266 = data.substr(data.find(":"),data.length());
		cout<<":266> "<<line266<<endl;
		noparse = 0;
	} else if (data.find("422 ") == 0) {
		string line422 = data.substr(data.find(":"),data.length());
		cout<<":422> "<<line422<<endl;
		putz(DEFAULT_CHANNEL);
		noparse = 0;
	} else if (data.find((MyNick + " ")) == 0) {
		//I did something Mode Like
		string action = data.substr(data.find(" ")+1,data.length());
		action = (action.substr(0,action.find(" "))); 
		//cout<<"ACTION:"<<action<<endl;
		if (action == "MODE") {
			//I set a mode.
			data=(data.substr((data.find(action) + 5)));
			cout<<":"<<MyNick<<">"<<" I Set Mode On "<<(data.substr(0,data.find(" ")))<<" "<<(data.substr(data.find(":")+1))<<endl;
			noparse = 0;
		}
	} else if (data.find((MyNick + "!")) == 0) {  //Stuff like JOINs have a mask included
		data = (data.substr((data.find(" ")+1)));  //strip it cuz I already know its me
		if (data.find("JOIN ") == 0) { //I joined a channel
			cout<<":"<<MyNick<<">"<<" I Have Joined "<<(data.substr((data.find(":")+1)))<<endl;
		}
		noparse=0;
	} else if (data.find("353 ") == 0) {
		data = (data.substr(data.find("#")));
		string nchan = (data.substr(0,data.find(" :")));
		string nlist = (data.substr((data.find(":")+1)));
		cout<<":"<<nchan<<"> "<<nlist<<endl;
		noparse = 0;
	} else if (data.find("366 ") == 0) {
		data = (data.substr((data.find("#"))));
		string nchan = (data.substr(0,data.find(" :")));
		cout<<":"<<nchan<<"> "<< (data.substr((data.find(":")+1)))<<endl;
		noparse = 0;
	} else if (data.find(" PRIVMSG ") != -1 && data.find(" PRIVMSG ") < data.find(":") ) {
		string pmfrom = (data.substr(0,data.find(" "))); //Full From nick!ident@host mask
		pmfrom = (pmfrom.substr(0,data.find("!"))); //Strip down to just nick 
		//Is a /msg or channel text?
		data = (data.substr((data.find(" PRIVMSG ") + 9)));
		string pmto = (data.substr(0,data.find(" :")));
		if (pmto == MyNick) {
			//Private Message
			cout<<"<"<<pmfrom<<"> "<<(data.substr((data.find(":")+1)))<<endl;
			noparse = 0;
		} else {
			//Channel Text 
			cout<<":"<<pmto<<"> <"<<pmfrom<<"> "<<(data.substr((data.find(":")+1)))<<endl;
			noparse = 0;
		}
	}
	if(noparse){cout<<":SERVER> "<<data<<endl;}
	//:SERVER> Neurosys!Neurosys@[HAHA]-D6A88D3B.sd.sd.cox.net PRIVMSG #bannerftp :Channel Message
	//:SERVER> Neurosys!Neurosys@[HAHA]-D6A88D3B.sd.sd.cox.net PRIVMSG MrC0de :private message
};
