function irc.parse(str)
	local msg = {}
	local pos = 1
	local t, e = string.match(str, "^:(%S*)%s*()")
	if t then
		msg.prefix = t
		pos = e
	end
	
	local i = 1
	while true do
		t = string.match(str, "^:(.*)", pos)
		if t then
			msg[i] = t
			return msg
		end
		t, e = string.match(str, "^(%S+)%s*()", pos)
		if t then
			msg[i] = t
			pos = e
			i = i + 1
		else
			break
		end
	end
	
	return msg
end

function irc.parseCommand(str)
	local cmd = {}
	
	local t, e = string.match(str, "^/(.-)%s()")
	if not t then
		return nil
	end
	
	cmd.name = string.lower(t)
	local pos = e
	
	local i = 1
	while true do
		t, e = string.match(str, "^(%S+)%s*()", pos)
		if t then
			cmd[i] = t
			pos = e
			i = i + 1
		else
			break
		end
	end
	
	return cmd
end

function irc.load(dest, server, channel)
	gui_load_gss("irc")
	local ircWin = gui_load_xml("irc", dest)
	local textw = ircWin:child("irctext")
	local inw = ircWin:child("ircin")
	inw:set_visibility(false)
	textw:add_column("", 1)
	
	local connectw = ircWin:child("connect-irc")
	ircWin:set_sub_focus(connectw)
	connectw:set_visibility(true)

	function connectw:onAction()
		connectw:set_visibility(false)
		
		local nick = game_local_player_name(0)

		local sock
		local connected = false, nickAttempt
		
		local function setNick(nick)
			nickAttempt = nick
			sock:send("NICK " .. nickAttempt .. "\r\n")
		end
		
		local function output(msg)
			textw:insert(msg)
			textw:scroll_bottom()
		end

		inw:set_visibility(true)
		inw:focus()
		function inw:onAction()
			local t = self:get_text()
			if t ~= "" then
				if string.sub(t, 1, 1) == "/" then
					cmd = irc.parseCommand(t)
					if cmd.name == "nick" then
						if #cmd >= 1 then
							setNick(cmd[1])
						end
					elseif cmd.name == "raw" then
						if #cmd >= 1 then
							sock:send(table.concat(cmd, " ") .. "\r\n")
						end
					end
				else
					sock:send("PRIVMSG " .. channel .. " :" .. t .. "\r\n")					
					output("> " .. t)
				end
				self:set_text("")
				return true
			end
		end
	
		output("* Connecting to " .. server)

		sock = tcp_connect(server, 6667)
		sock:send("USER glip 0 * :Moo\r\n")
		setNick(nick)

		local buffer = ""
		
		function bindings.afterUpdate()
			local s = sock
			local str = s:think()
			if str then
				buffer = buffer .. str
				local matche = 1
				for w, e in string.gmatch(buffer, "(.-)\r\n()") do
					matche = e
					local msg = irc.parse(w)
					if msg and #msg > 0 then
						local nick
						if msg.prefix then
							nick = string.match(msg.prefix, "^(.-)!")
						end
						if msg[1] == "PING" then
							if #msg >= 2 then
								s:send("PONG :" .. msg[2] .. "\r\n")
							end
						elseif msg[1] == "001" then
							connected = true
							output("* Successfully connected")
							s:send("JOIN " .. channel .. "\r\n")
						elseif msg[1] == "JOIN" then
							if #msg >= 2 then
								output("* Joined " .. msg[2])
							end
						elseif msg[1] == "433" then
							if not connected then
								setNick(nickAttempt .. "_")
							else
								output("* Nickname in use")
							end
						elseif msg[1] == "NICK" then
							if nick and #msg >= 2 then
								output("* " .. nick .. " now known as " .. msg[2])
							end
						elseif msg[1] == "PRIVMSG" then
							if nick and #msg >= 3 then
								output("<" .. nick .. "> " .. msg[3])
							end
						end
					end
					print(w)
				end
							
				buffer = string.sub(buffer, matche)
			end
		end
	end
	
	return ircWin
end
