-- vim: ft=terra
local r = lib.srv.route
local method = lib.http.method
local http = {}

terra http.actor_profile_xid(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
	var handle = [lib.mem.ptr(int8)] { ptr = &uri.ptr[2], ct = 0 }
	for i=2,uri.ct do
		if uri.ptr[i] == @'/' or uri.ptr[i] == 0 then handle.ct = i - 2 break end
	end
	if handle.ct == 0 then
		handle.ct = uri.ct - 2
		uri:advance(uri.ct)
	else
		if handle.ct + 2 < uri.ct then
			uri:advance(handle.ct + 2)
			--uri.ptr = uri.ptr + (handle.ct + 2)
			--uri.ct = uri.ct - (handle.ct + 2)
		end
	end

	lib.dbg('looking up user by xid "', {handle.ptr,handle.ct} ,'", path: ', {uri.ptr,uri.ct})

	var path = lib.http.hier(uri) defer path:free()
	for i=0,path.ct do
		lib.dbg('got path component ', {path.ptr[i].ptr, path.ptr[i].ct})
	end

	var actor = co.srv:actor_fetch_xid(handle)
	if actor.ptr == nil then
		co:complain(404,'no such user','no such user known to this server')
		return
	end
	defer actor:free()

	lib.render.userpage(co, actor.ptr)
end

terra http.actor_profile_uid(co: &lib.srv.convo, path: lib.mem.ptr(lib.mem.ref(int8)), meth: method.t)
	if path.ct < 2 then
		co:complain(404,'bad url','invalid user url')
		return
	end

	var uid, ok = lib.math.shorthand.parse(path.ptr[1].ptr, path.ptr[1].ct)
	if not ok then
		co:complain(400, 'bad user ID', 'that user ID is not valid')
		return
	end

	var actor = co.srv:actor_fetch_uid(uid)
	if actor.ptr == nil then
		co:complain(404, 'no such user', 'no user by that ID is known to this instance')
		return
	end
	defer actor:free()

	lib.render.userpage(co, actor.ptr)
end

do local branches = quote end
	local filename, flen = symbol(&int8), symbol(intptr)
	local page = symbol(lib.http.page)
	local send = label()
	local storage = data.stmap
	for i,e in ipairs(config.embeds) do local id,mime = e[1],e[2]
		local d = data.static[id]
		branches = quote [branches];
			if lib.str.ncmp(filename, id, lib.math.biggest([#id], flen)) == 0 then
				page.headers.ptr[0].value = mime;
				page.body = [lib.mem.ptr(int8)] {
					ptr = storage[([i-1])].ptr;
					ct  = storage[([i-1])].ct;
				}
				goto [send]
			end
		end
	end
	terra http.static_content(co: &lib.srv.convo, [filename], [flen])
		var hdrs = array(lib.http.header{'Content-Type',nil})
		var [page] = lib.http.page {
			respcode = 200;
			headers = [lib.mem.ptr(lib.http.header)] {
				ptr = &hdrs[0], ct = 1
			}
		}
		[branches]
		do return false end
		::[send]:: page:send(co.con) return true
	end
end

http.static_content:printpretty()

-- entry points
terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
	if uri.ptr[0] ~= @'/' then
		co:complain(404, 'what the hell', 'how did you do that')
	elseif uri.ptr[1] == @'@' then
		http.actor_profile_xid(co, uri, meth)
	elseif uri.ptr[1] == @'s' and uri.ptr[2] == @'/' and uri.ct > 3 then
		if meth ~= method.get then goto wrongmeth end
		if not http.static_content(co, uri.ptr + 3, uri.ct - 3) then goto notfound end
	else
		var path = lib.http.hier(uri) defer path:free()
		if path.ptr[0]:cmp(lib.str.lit('user')) then
			http.actor_profile_uid(co, path, meth)
		else goto notfound end
	end

	::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this path') do return end
	::notfound:: co:complain(404, 'not found', 'no such resource available') do return end
end
