#!/usr/bin/env lua5.3
local lpeg = require'lpeg'

local function template(str, args)
	return (str:gsub("%%(%w+)%%", args))
end

local function urldecode(s)
	return s:gsub('+',' ')
		:gsub('%%(%x%x)',function(x)
			return string.char(tonumber(x,16))
		end)
end
local function parse_qs(s)
	local ix = 1
	local res = {}
	while true do
		local _,next_ix,ek,ev = s:find("([^=]+)=([^&]*)&?",ix)
		if not ek then break end
		local k,v = urldecode(ek), urldecode(ev)
		res[k] = v
		ix = next_ix + 1
	end
	return res
end

local function eprint(...)
	local s = {}
	for i = 1, select('#',...) do
		s[i] = tostring(select(i, ...))
	end
	io.stderr:write(table.concat(s, "\t"), "\n")
end

local document_template
do
	local template_file = assert(io.open"template.html")
	document_template = template_file:read"a"
	template_file:close()
end

local function load_dict(filename)
	local res = {}
	for line in io.lines(filename) do
		local word, pos, def = line:match "^(.-)\t(.-)\t(.-)$"
		if word then
			res[word] = {pos=pos, def=def, word=word}
		end
	end
	return res
end

local function format_def(found_word, entry)
	local defc
	if entry then
		defc = template("<b>%word%</b> <i>%pos%</i>. %def%", entry)
	else
		defc = "????"
	end
	return template(
		"<word><def>%defc%</def><wi>%wi%</wi></word>",
		{defc=defc, wi=found_word}
	)
end

local glossors = {}

function glossors.sanila(text)
	local words = load_dict "sanila.tsv"

	local items = {}
	-- sanila morphology is easy enough
	for word in text:gmatch("%S+") do
		local stripped = word:match("^(.-)[.,]*$"):lower()
		local entry = words[stripped]
		table.insert(items, format_def(word, entry))
	end

	return table.concat(items, "\n")
end

glossors["vötgil"] = function(text)
	local words = load_dict "vötgil.tsv"
	local function norm(s)
		return s:lower():gsub("Ð","ð"):gsub("Ö","ö"):gsub("0","ö"):gsub("9","ð")
	end

	local letter = lpeg.R("az","AZ") + lpeg.S"09" + "ö" + "Ö" + 'ð' + 'Ð'
	local word = (letter*letter*letter) / function (w)
		return format_def(w, words[norm(w)])
	end * lpeg.Cp()

	local i = 1
	local out = ""
	while i <= #text do
		local item, ni = lpeg.match(word, text, i)
		if item then
			out = out .. item
			i = ni
		else
			out = out .. text:sub(i,i)
			i = i + 1
		end
	end
	return out
end

local function engloss(langue, text)
	local text = glossors[langue](text)
	return template([[
	<section>%text%</section>
	<section id=place></section>
	<section><a href="%path%">&lt; return</a></section>
	]], {text=text,path=os.getenv"SCRIPT_NAME"})
end

local function enform()
	local options = {}
	for k in pairs(glossors) do
		table.insert(options, template('<option value="%x%" >%x%</option>', {x=k}))
	end
	table.sort(options)
	return template([[
<section>
<form>
	<textarea name=q></textarea>
	<label for=langue>select con-langue:</label>
	<select name=langue id=langue>
		%options%
	</select>
	<br><button>perform <i>conglossatio</i></button>
</form>
</section>
<footer>
<a href=//g.gh0.pw/conglossor/>source code</a>
<p>langues incorporated:<ul>
<li><a href=//viba.neocities.org/sanila/>sanila</a> (by <a href=//viba.neocities.org>viba</a>)</li>
<li><a href=//www.ostracodfiles.com/votgil/main.html>vötgil</a> (by <a href=//ostracodfiles.com>jack eisenmann</a>)</li>
</ul></p></footer>
]], {
		options=table.concat(options, "\n"),

	})
end

local function response(content)
	print("Content-Type: text/html")
	print()
	print(template(document_template, {content=content}))
end

local function main()
	local langue, text
	local qs = os.getenv"QUERY_STRING"
	if qs then
		local pqs = parse_qs(qs)
		langue = pqs.langue
		text = pqs.q
	end

	if not text then
		response(enform())
	elseif not glossors[langue] then
		response("unknown langue "..langue)
	else
		response(engloss(langue, text))
	end
end

main()