
local function split(str, pat, includeBlanks)
   local t = {}  -- NOTE: use {n = 0} in Lua-5.0
   local fpat = "(.-)" .. pat
   local last_end = 1
   local s, e, cap = str:find(fpat, 1)
   while s do
      if s ~= 1 or (cap ~= "" and not includeBlanks) or (includeBlanks and cap == "") then
		 table.insert(t, cap)
      end
      last_end = e+1
      s, e, cap = str:find(fpat, last_end)
   end
   if last_end <= #str then
      cap = str:sub(last_end)
      table.insert(t, cap)
   end
   return t
end

GameList = inherited("GameList", State)

function GameList:new(game, version, listHost, listPath, listPort, token)
	local o = instance(self)
	o.gameString = game
	o.versionString = version
	o.token = token or "12345"
	o.host = listHost
	o.path = listPath or "/multiplayer/daisyMoon/"
	o.port = listPort or 80
	o.fetchDelay = 0
	return o
end

function GameList:update(time)
	if self.fetchDelay <= 0 then
		self:fetch()
		self.fetchDelay = 15
	else
		self.fetchDelay = self.fetchDelay-time
	end
end

function GameList:getDevice()
	local d = net.createDevice(true)
	d.lobby = self
	return d
end

function GameList:setList(games)
	self.games = games
	self.updated = true
end

function GameList:isListUpdated()
	if self.updated then
		self.updated = false
		return true
	end
end

function GameList:getList()
	return self.games
end

function GameList:removeListed(ip, port)
	for index, game in pairs(self.games) do
		if game.ip == ip and game.port == port then
			table.remove(self.games, index)
			self.updated = true
			break
		end
	end
end

function GameList:fetch()
	self.finder = self:getDevice()
	self.finder.games = {}
	self.finder.onConnect = function(self, localId)
			local targetFile = self.lobby.path.."list.php?version="..self.lobby.versionString.."&game="..self.lobby.gameString
			self:sendData("GET " .. targetFile .. " HTTP/1.1" .. "\r\n")
			self:sendData("Host: " .. self.lobby.host .."\r\n")
			self:sendData("\r\n")
		end
	self.finder.onFail = function(self, message)
			self.lobby:onError(message)
		end
	self.finder.onData = function(self, data)
			if string.sub(data, 1, 1) == "!" then
				self.lobby:onError(data)
			else
				local rows = split(data, "\r\n", true)
				for index, row in pairs(rows) do
					if self.bodyComing then
						if not self.oked then
							if row == "OK" then
								self.oked = true
							end
						else
							local gameData = split(row, "|")
							if #gameData >= 8 then
								local game = {ip = gameData[1], port = tonumber(gameData[2]), creator = gameData[3], players = tonumber(gameData[4]), maxPlayers = tonumber(gameData[5]), map = gameData[6], description = gameData[7], age = tonumber(gameData[8])}
								table.insert(self.games, game)
							end
						end
					else
						if row == "" then
							self.bodyComing = true
						end
					end
				end
				self.lobby:onMessage("Found "..#self.games.." games.")
				self.lobby:setList(self.games)
			end
		end
	self.finder:joinHost(self.gameString, "fetchList", self.host, self.port)
end

function GameList:registerLobby(lobby)
	self:register(lobby:getPort(), lobby:getCreator(), lobby:getNumberOfPlayers(), lobby:getMaxPlayers(), lobby:getMap(), lobby:getDescription())
end

function GameList:register(port, creator, players, playersMax, map, description)
	if not self.game then
		self.game = {}
		self.fetchDelay = 0
	end
	self.game.port = port
	self.game.creator = creator
	self.game.players = players
	self.game.playersMax = playersMax
	self.game.map = map
	self.game.description = description
	
	self.poller = self:getDevice()
	self.poller.game = self.game
	self.poller.onConnect = function(self, localId)
			local contents = "port="..self.game.port.."&creator="..string.gsub(self.game.creator, " ", "+").."&players="..self.game.players.."&playersMax="..self.game.playersMax.."&map="..self.game.map.."&description="..string.gsub(self.game.description, " ", "+").."&version="..self.lobby.versionString.."&game="..self.lobby.gameString.."&token="..self.lobby.token
			local targetFile = self.lobby.path.."update.php"
			self:sendData("GET " .. targetFile.."?"..contents .. " HTTP/1.1" .. "\r\n")
			self:sendData("Host: " .. self.lobby.host .."\r\n")
			self:sendData("\r\n")
		end
	self.poller.onFail = function(self, message)
			self.lobby:onError(message)
		end
	self.poller.onData = function(self, data)
			if not self.posted then
				self.posted = true
				self.lobby:onMessage("Posted to Master Server")
				self.lobby:onData(data)
			end
		end
	self.poller:joinHost(self.gameString, "updateList", self.host, self.port)
end

function GameList:unregister()
	if self.game then
		self.remover = self:getDevice()
		self.remover.game = self.game
			self.remover.onConnect = function(self, localId)
				local contents = "port="..self.game.port.."&game="..self.lobby.gameString.."&token="..self.lobby.token
				local targetFile = self.lobby.path.."remove.php"
				
				self:sendData("GET " .. targetFile.."?"..contents .. " HTTP/1.1" .. "\r\n")
				self:sendData("Host: " .. self.lobby.host .."\r\n")
				self:sendData("\r\n")
				
			end

			self.remover.onFail = function(self, message) 
				self.lobby:onError(message)
			end
			self.remover.onData = function(self, data)
				self.lobby:onData(data)
				self.lobby.game = nil
			end
		self.remover:joinHost(self.gameString, "removeList", self.host, self.port)
	end
end

