local export = {}
local m_string_utils = require("Module:string utilities")

local find = m_string_utils.find
local match = m_string_utils.match

local initialConv = {
	["b"] = "p", ["p"] = "pʰ", ["bb"] = "b", ["m"] = "m",
	["d"] = "t", ["t"] = "tʰ", ["dd"] = "d", ["n"] = "n",  ["l"] = "l", 
	["z"] = "t͡s", ["c"] = "t͡sʰ", ["zz"] = "d͡z", ["s"] = "s",
	["j"] = "t͡ɕ", ["q"] = "t͡ɕʰ", ["jj"] = "d͡ʑ", ["x"] = "ɕ", ["xx"] = "ʑ",
	["g"] = "k", ["k"] = "kʰ", ["ng"] = "ŋ",
	["h"] = "x", ["gh"] = "ɣ", [""] = ""
}

local finalConv = {
	["r"] = "z̩",
	["i"] = "i", ["ui"] = "u̯i", ["yi"] = "y̯i",
	["u"] = "u", ["euu"] = "ɤu̯",
	["y"] = "y", 
	["a"] = "a̠", ["ia"] = "i̯a", ["ua"] = "u̯a",
	["e"] = "e̞", ["ie"] = "i̯e̞", ["ue"] = "u̯e̞", ["ye"] = "y̯e̞", 
	["o"] = "ɔ", ["io"] = "i̯ɔ", 
	["uo"] = "ʊ", ["iou"] = "i̯ʊ", 
	["eu"] = "ɤ", ["ieu"] = "i̯ɤ",
	["in"] = "in", ["un"] = "un", ["yn"] = "yn",
	["ong"] = "ɔŋ", ["iong"] = "i̯ɔŋ", ["uong"] = "u̯ɔŋ",
	["eng"] = "ɤŋ", ["ieng"] = "i̯ɤŋ", ["ueng"] = "u̯ɤŋ",
	["ann"] = "ã̠", ["uann"] = "u̯ã",
	["enn"] = "ẽ̞", ["uenn"] = "u̯ẽ̞",
	["onn"] = "ɔ̃", ["ionn"] = "i̯ɔ̃", 
	["inn"] = "ĩ", ["uinn"] = "u̯ĩ", ["yinn"] = "yĩ",
	["m"] = "m̩", ["n"] = "n̩", ["ng"] = "ŋ̍"
}

local toneConv = {
	["1"] = "⁴⁴", ["2"] = "¹³", ["3"] = "⁴²", ["4"] = "³⁵", ["5"] = "¹¹",
	["1*"] = "⁴⁴⁻³³", ["2*"] = "¹³⁻³³", ["3*"] = "⁴²⁻¹", ["4*"] = "³⁵⁻⁵", ["5*"] = "¹¹⁻¹",
	["0"] = "³",
}

function export.ipa(text)
	if type(text) == "table" then
		text = text.args[1]
	end
	local result = {}
	for word in mw.text.gsplit(text, "/") do
		local syllables = mw.text.split(word, " ")
		local ipa = {}
		for index, syllable in ipairs(syllables) do
			local initial, final, tone
			local initial_orig = nil
			initial = syllable:match("^([bpmdtlnzcsjqxgkh]?([bdzjxhg]?))")
			final = syllable:match("^" .. initial .. "([^1-5%*]*)")
			if final == "" then
				final = initial
				initial = ""
			end
			if (find(final, "^r$") and not find(initial, "^[zcs]z?$")) or (find(initial, "^[jqx][jx]?$") and find(final, "^[aeou]")) or (find(final, "[mn]") and initial == "l") then
				error("Invalid input \"" .. syllable .. "\": initial " .. initial .. " cannot go with final " .. final .. ".")
			end	
			tone = syllable:match("[1-5%*]+$") or "0"
			if (match(initial, "[dtlzcs][dz]?")) and final == "u" then
				final = "euu"
			end
			if (match(tone, "[345]%*") and match(initial, "^[zcjq]$")) then
				initial_orig = initialConv[initial]
				initial = initial:gsub("^[zcjq]$", { ["z"] = "zz", ["c"] = "zz", ["j"] = "jj", ["q"] = "jj", })
			end
			initial = initialConv[initial] or error(("Unrecognised initial: \"%s\""):format(initial))
			final = finalConv[final] or error(("Unrecognised final: \"%s\""):format(final))
			tone = toneConv[tone] or error(("Unrecognised tone: \"%s\""):format(tone))
			ipa[index] = (initial_orig and ("<sup>(" .. initial_orig .. "-)</sup>") or "") .. initial .. final .. tone
		end
		local wordipa = table.concat(ipa, " ")
		if not (find(word, "%d")) then
			wordipa = wordipa:gsub("³", "")
		end
		table.insert(result, wordipa)
	end
	return table.concat(result, "/, /")
end

function export.rom(text)
	return (text
		:gsub("/", " / ")
		:gsub("([%d-]+%*?)", "<sup>%1</sup>"))
end

return export