Luacurl = {}
Luacurl.__index = Luacurl
setmetatable(Luacurl, {
	__call = function (cls, ...)
		return cls.new(...)
	end,
})
function Luacurl.new(server, port, ssl)
	local self = setmetatable({}, Luacurl)
	self.sockconnected = false
	self.server = server
	self.port = port
	self.ssl = ssl
	self.cookies = {}
	return self
end

function Luacurl:get(method,url,headers,data)
	core.Info("MAKING SOCKET")
	if self.sockconnected == false then
	  self.sock = core.tcp()
	  if self.ssl then
		local r = self.sock:connect_ssl(self.server,self.port)
	  else
		local r = self.sock:connect(self.server,self.port)
	  end
	  self.sockconnected = true
	end
	core.Info("SOCKET MADE")
	local request = method.." "..url.." HTTP/1.1"
	if data ~= nil then
		request = request .. "\r\nContent-Length: "..string.len(data)
	end
	if headers ~= null then
		for h,v in pairs(headers) do
			request = request .. "\r\n"..h..": "..v
		end
	end
	cookstring = ""
	for cook,cookval in pairs(self.cookies) do
		cookstring = cookstring .. cook.."="..cookval.."; "
	end
	if string.len(cookstring) > 0 then
		request = request .. "\r\nCookie: "..cookstring
	end

	request = request .. "\r\n\r\n"
	if data and string.len(data) > 0 then
		request = request .. data
	end
--print(request)
	core.Info("SENDING REQUEST")
	self.sock:send(request)

--	core.Info("PROCESSING RESPONSE")
	return processhttpresponse(self.sock)
end

function processhttpresponse(socket)
	local res = {}
core.Info("1")
	res.status = socket:receive("*l")
core.Info("2")

	if res.status == nil then
		core.Info(" processhttpresponse RECEIVING status: NIL")
		return res
	end
	core.Info(" processhttpresponse RECEIVING status:"..res.status)
	res.headers = {}
	res.headerslist = {}
	repeat
core.Info("3")
		local header = socket:receive("*l")
		if header == nil then
			return "error"
		end
		local valuestart = header:find(":")
		if valuestart ~= nil then
			local head = header:sub(1,valuestart-1)
			local value = header:sub(valuestart+2)
			table.insert(res.headerslist, {head,value})
			res.headers[head] = value
		end
	until header == ""
	local bodydone = false
	if res.headers["Connection"] ~= nil and res.headers["Connection"] == "close" then
--		core.Info("luacurl processresponse with connection:close")
		res.body = ""
		repeat
core.Info("4")
			local d = socket:receive("*a")
			if d ~= nil then
				res.body = res.body .. d
			end
		until d == nil or d == 0
		bodydone = true
	end
	if bodydone == false and res.headers["Content-Length"] ~= nil then
		res.contentlength = tonumber(res.headers["Content-Length"])
		if res.contentlength == nil then
		  core.Warning("res.contentlength ~NIL = "..res.headers["Content-Length"])
		end
--		core.Info("luacur, contentlength="..res.contentlength)
		res.body = ""
		repeat
			local d = socket:receive(res.contentlength)
			if d == nil then
--				core.Info("luacurl, ERROR?: recieved NIL, expecting "..res.contentlength.." bytes only got "..string.len(res.body).." sofar")
				return
			else
				res.body = res.body..d
--				core.Info("luacurl, COMPLETE?: expecting "..res.contentlength.." bytes, got "..string.len(res.body))
				if string.len(res.body) >= res.contentlength then
--					core.Info("luacurl, COMPLETE?: expecting "..res.contentlength.." bytes, got "..string.len(res.body))
					break
				end
			end
--			core.Info("processhttpresponse, Loopy, get more body data! to recieve complete contentlenght")
		until false
	end
	if res.headers["Transfer-Encoding"] ~= nil and res.headers["Transfer-Encoding"] == "chunked" then
		local chunksize = 0
		res.contentlength = 0
		res.body = ""
		repeat
core.Info("5")
			local chunksizestr = socket:receive("*l")
			if chunksizestr == nil then
				break
			end
			chunksize = tonumber("0x"..chunksizestr)
			if chunksize ~= nil then
				res.contentlength = res.contentlength + chunksize
				if chunksize ~= 0 then
					local chunk = socket:receive(chunksize)
					res.body = res.body .. chunk
					chunksizestr = socket:receive("*l")
					if chunksizestr ~= "" then
						return "ERROR Chunk-end expected."
					end
				end
			else
				break
			end
		until false
	end
core.Info("6")
	return res
end

function Luacurl:close()
	if self.sockconnected == true then
		self.sock:close()
		self.sockconnected = false
	end
end

function print_r_string(object)
	local res = ""
	print_r(object,false,function(x) res = res .. x end)
	return res
end

core.register_service("fakeserv", "http", function(applet)
	core.Info("APPLET START")
	local mc = Luacurl("127.0.0.1",8443, true)
	local headers = {}
	local body = ""
	core.Info("APPLET GET")
	local res = mc:get("GET", "/", headers, body)
	core.Info("APPLET GET done")
	local response = print_r_string(res)
	applet:add_header("Server", "haproxy/webstats")
	applet:add_header("Content-Length", string.len(response))
	applet:add_header("Content-Type", "text/html")
	applet:start_response()
	applet:send(response)
	core.Info("APPLET DONE")
end)
