-- This module is for 玉林話 (Yulin Yue), a lect of Yue Chinese
-- Romanisation: Jyutping++ (referred to as jpp below)
-- References:
-- 1. 玉林话研究 (2010) by 梁忠东
-- Also see [[Category:Yulin Yue]]

-- Special features:
--- Tone sandhi (e.g. fung1-ce1)
--- Diminutive (e.g. da4-bek1*)

local export = {}

-- as with Jyutping, we use analysis that groups glide with initial
-- special note: 月 is njoet /ɲœt̚/
local initials = {
	b = "p",  p = "pʰ",  m = "m",  f = "f",
	d = "t",  t = "tʰ",  n = "n",  sl = "ɬ", l = "l",
	z = "t͡ʃ", c = "t͡ʃʰ", nj = "ɲ", s = "ʃ",
	g = "k",  k = "kʰ",  ng = "ŋ", h = "h",
	gw = "kʷ",  kw = "kʰʷ",
	j = "j",  w = "w",
	[""] = "", -- glottal stop?
}

-- <oeu> /əu/
local finals = {
	a="a", ai="ai", au="au", am="am", an="an", ang="aŋ", ap="ap̚", at="at̚", ak="ak̚",
	e="ɛ",          eu="ɛu", em="ɛm", en="ɛn", eng="ɛŋ", ep="ɛp̚", et="ɛt̚", ek="ɛk̚",
	oe="œ",        oeu="əu",                  oeng="œŋ",         oet="œt̚",oek="œk̚",
	o="ɔ", oi="ɔi", ou="ɔu", om="ɔm", on="ɔn", ong="ɔŋ", op="ɔp̚", ot="ɔt̚", ok="ɔk̚",
	oo="o",        
	i="i",          iu="iu", im="im",["in"]="in",        ip="ip̚", it="it̚",
	u="u", ui="ui",                   un="un", ung="ʊŋ",          ut="ut̚", uk="ʊk̚",
	yu="y",                          yun="yn",                   yut="yt̚",
	m="m̩", ng="ŋ̍"
}

-- transforms the coda for diminutives
local function diminutive_coda(text)
	text = text:gsub("([ptk])\204\154$",{p="m",t="n",k="ŋ"})
	return text
end

local entering_tone = {
	["1"] = "7", ["2"] = "8", ["4"] = "9", ["6"] = "0"
}

local tones = {
	["1"] = "54", --陰平/上陰入(7)
	["2"] = "33", --陰上/下陰入(8)
	["3"] = "42", --陰去
	["4"] = "32", --陽平/上陽入(9)
	["5"] = "24", --陽上
	["6"] = "21", --陽去/下陽入(0)
	-- for internal use only
	["7"] = "5",
	["8"] = "3",
	["9"] = "2",
	["0"] = "1",
}

local tone_sandhi = {
	["11"]="33",["12"]="33",["13"]="33",["14"]="42",["15"]="42",["16"]="42",["17"]="33",["18"]="33",["19"]="42",["10"]="42",
	["41"]="21",["42"]="21",["43"]="21",["44"]="21",["45"]="21",["46"]="21",["47"]="21",["48"]="21",["49"]="21",["40"]="21",
	["31"]="33",["32"]="33",["33"]="33",["37"]="33",["38"]="33",
	["91"]="1",["92"]="1",["93"]="1",["94"]="1",["95"]="1",["96"]="1",["97"]="1",["98"]="1",["99"]="1",["90"]="1",
}

local function tone_superscript(text)
	return text:gsub("[12345]",{["1"]="¹",["2"]="²",["3"]="³",["4"]="⁴",["5"]="⁵"})
end

local function validate(text)
	if text:match("%-%l+%d%-") then
		error("Yulin: Only two-syllable sandhi is supported.")
	end
	if text:match("%*%-") then
		error("Yulin: The diminutive sign cannot be placed on the first syllable of a sandhi chain.")
	end
	if text:match("[7890]") then
		error("Yulin: Wrong tone (use 1, 2, 4, 6 for entering tones).")
	end
	if text:match("%d%d") then
		error("Yulin: Please use a hyphen to incidate tone sandhi.")
	end
	text = text:gsub("[,%-]"," ")
	if text:sub(1,1) == " " or text:sub(-1,-1) == " " or text:match("  ") then
		error("Yulin: Empty syllable detected.")
	end
end

function export.jpp_to_ipa(text)
	validate(text)
	text = text:gsub("%f[^ptk][1246]", entering_tone)
	 :gsub("%-(%l+)(%d)", "%2 %1%2")
	 :gsub("[^ ,%-]+",function(syllable)
		local a,b,c,d = syllable:match("^([bpmfdtnslzcgkhwj]?[ljw]?)([aeiouymn]%l*)([0-9])([0-9]?%*?)$")
		if not a then
			error("Yulin: Invalid syllable: " .. syllable)
		end
		a = initials[a] or error("Yulin: Unrecognised initial: " .. a)
		b = finals[b] or error("Yulin: Unrecognised final: " .. b)
		if d == "*" then
			b = diminutive_coda(b)
		end
		local tone2 = (d == "*" and "35" or d ~= "" and tone_sandhi[c..d])
		return a .. b .. tones[c] .. (tone2 and ("⁻"..tone2) or "")
	end)
		:gsub(",", "/, /")
	return "/" .. tone_superscript(text) .. "/"
end

return export