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

local gsub = m_string_utils.gsub
local gsplit = mw.text.gsplit
local match = m_string_utils.match
local lower = m_string_utils.lower
local toNFC = mw.ustring.toNFC
local toNFD = mw.ustring.toNFD

local initial_ipa = {
	["b"] = "p",	["p"] = "pʰ",	["m"] = "m",
	["d"] = "t",	["t"] = "tʰ",	["n"] = "n",	["l"] = "l",
	["c"] = "t͡s",	 ["ch"] = "t͡sʰ", ["s"] = "s",
	["g"] = "k",	["k"] = "kʰ",	["ng"] = "ŋ",	["h"] = "x",
	[""] = "",
}

local final_ipa = {
	["i"] = "i", ["u"] = "u", ["ṳ"] = "y",
	["a"] = "a", ["ia"] = "ia", ["ua"] = "ua",
	["a̤"] = "ɛ", ["ie"] = "iɛ", ["uoi"] = "uɛ", ["ṳe"] = "yɛ",
	["o̤"] = "ɔ", ["io̤"] = "iɔ",
	["e"] = "e", ["e̤"] = "œ", ["o"] = "o",
	["ai"] = "ai", ["uai"] = "uai",
	["au"] = "au", ["iau"] = "iau",
	["iu"] = "iu",
	["ing"] = "iŋ", ["uing"] = "uiŋ", ["ṳing"] = "yiŋ",
	["ang"] = "aŋ", ["iang"] = "iaŋ", ["uang"] = "uaŋ",
	["o̤ng"] = "ɔŋ", ["ong"] = "ɔŋ", ["io̤ng"] = "iɔŋ", ["iong"] = "iɔŋ", ["uo̤ng"] = "uɔŋ",
	["eng"] = "eiŋ", --missing /ieiŋ/
	["e̤ng"] = "œyŋ",
	["aing"] = "aiŋ", ["uaing"] = "uaiŋ",
}

local tone_marks = "[́̂̌̿̄̆̀]"

local tone_from_mark = {
	["́"] = 1, --陰平 (acute)
	["̂"] = 3, --陽平 (circumflex)
	["̌"] = 2, --上 (caron)
	["̿"] = 3, --陰去 (double overline)
	["̄"] = 4, --陽去 (macron)
	["̆"] = 5, --陰入 (breve)
	["̀"] = 6, --陽入 (grave)
}

local tone_value = {
	[1] = "⁵⁴", --陰平
	[2] = "²¹", --上
	[3] = "³³", --陰去
	[4] = "⁵⁵", --陽去
	[5] = "²⁴", --陰入
	[6] = "⁴²", --陽入
}

--[=[
	Given a syllable, return tone value of the syllable's tone and the syllable without the tone mark
]=]
local function get_tone_value(syllable)
	if match(syllable, "̄̄") then -- check for double macron
		local corrected = gsub(syllable, "̄̄", "̿")
		error("Please change " .. syllable .. " to " .. corrected .. ".")
	end
	local tone = match(syllable, tone_marks)
	if tone then
		return tone_value[tone_from_mark[tone]], gsub(syllable, tone, "")
	else
		error("No tone detected.")
	end
end

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

function export.ipa(text)
	text = toNFD(lower(text))
	local words_ipa = {}
	for word in gsplit(text, "/") do
		word = gsub(word, " ", "-")
		local syllables_ipa = {}
		for syllable in gsplit(word, "-") do
			syllable = match(syllable, ">(.*)$") or syllable
			local initial, final, tone_value
			tone_value, syllable = get_tone_value(syllable)
			initial, final = match(syllable, "^([bpmdtnlcsk]?[gh]?)([aeioung̤]+)$")
			initial, final = toNFC(initial), toNFC(final)
			initial, final = initial_ipa[initial], final_ipa[final]
			table.insert(syllables_ipa, initial..final..tone_value)
		end
		table.insert(words_ipa, table.concat(syllables_ipa, " "))
	end
	return "/" .. table.concat(words_ipa, "/, /") .. "/"
end

return export