local export = {}

-- Split the word into syllables of C(C)V(V) shape
function export.split_syllables(word)
	local syllables = {}
	local remainder = word
	
	while remainder ~= "" do
		local syll = ""
		
		if mw.ustring.find(remainder, "^([^aeiouäëöü%-]+)") then
			syll = syll .. mw.ustring.match(remainder, "^([^aeiouäëöü%-]+)")
			remainder = mw.ustring.gsub(remainder, "^([^aeiouäëöü%-]+)", "")
		end
		
		if mw.ustring.find(remainder, "^([aeiouäëöü%-]+)") then
			syll = syll .. mw.ustring.match(remainder, "^([aeiouäëöü%-]+)")
			remainder = mw.ustring.gsub(remainder, "^([aeiouäëöü%-]+)", "")
		end
		
		table.insert(syllables, syll)
	end
	
	-- Assume that suffixes are attached to words of at least two syllables.
	if mw.ustring.find(word, "^%-") then
		table.insert(syllables, 1, "")
	end
	
	return syllables
end

-- Apply gradation to a word
function export.apply_gradation(word)
	local syllables = export.split_syllables(word)
	
	for i, syll in ipairs(syllables) do
		-- The first and last consonant do not gradate
		if i > 1 then
			-- Apply suffixal gradation to single consonants at the beginning of odd-numbered syllables
			if i % 2 == 1 and mw.ustring.find(syll, "^[ptks][aeiouäëöü]") then
				syll = mw.ustring.gsub(syll, "^p", "b")
				syll = mw.ustring.gsub(syll, "^t", "d")
				syll = mw.ustring.gsub(syll, "^k", "g")
				syll = mw.ustring.gsub(syll, "^s", "h")
			end
			
			-- Apply radical gradation
			-- Does the next syllable begin with more than one consonant, or does it contain no vowels (final consonant)?
			if i < #syllables and (mw.ustring.find(syllables[i+1], "^[^aeiouäëöü][^aeiouäëöü]") or not mw.ustring.find(syllables[i+1], "[aeiouäëöü]")) then
				syll = mw.ustring.gsub(syll, "^([lrmn]?)pp([aeiouäëöü])", "%1p'%2")
				syll = mw.ustring.gsub(syll, "^([lrmn]?)tt([aeiouäëöü])", "%1t'%2")
				syll = mw.ustring.gsub(syll, "^([lrmn]?)kk([aeiouäëöü])", "%1k'%2")
				syll = mw.ustring.gsub(syll, "^([lrmn]?)cc([aeiouäëöü])", "%1c'%2")
				syll = mw.ustring.gsub(syll, "^([lrmn]?)p([aeiouäëöü])", "%1b%2")
				syll = mw.ustring.gsub(syll, "^([lrmn]?)t([aeiouäëöü])", "%1d%2")
				syll = mw.ustring.gsub(syll, "^([lrmn]?)k([aeiouäëöü])", "%1g%2")
			end
		end
		
		syllables[i] = syll
	end
	
	return table.concat(syllables, "")
end

function export.make_stems(stem, overrides)
	local stems = {normal = stem}
	
	stems.final = stems.normal
	
	local da_stem = overrides and overrides.da_stem
	local ne_t_stem = overrides and overrides.ne_t_stem
	local inf_e = overrides and overrides.inf_e
	
	if mw.ustring.find(stems.normal, "[^aeiouäëöü]$") then
		da_stem = da_stem and mw.ustring.find(stems.normal, "t$")
		stems.normal = stems.normal .. export.detect_harmony(stems.normal).e
	else
		da_stem = false
	end
	
	stems.i = stems.normal .. "i"
	stems.k = stems.normal .. "k"
	stems.n = stems.normal .. "n"
	stems.t = stems.normal .. "t"
	stems.types = {"unknown"}
	
	local syllables = export.split_syllables(stems.normal)
	
	
	-- Stems ending in a long vowel replace the second vowel with a diphthong
	if mw.ustring.find(stems.normal, "([aeiouäëöü])%1$") then
		stems.types = {"long vowel"}
		stems.i = mw.ustring.gsub(stems.i, "[aeiouäëöü]i$", "i")
	-- Stems ending in a u-diphthong replace u with v
	elseif mw.ustring.find(stems.normal, "([aeioäëö])[uü]$") then
		stems.types = {"u-diphthong"}
		stems.i = mw.ustring.gsub(stems.i, "[uü]i$", "vi")
	-- Stems ending in a i-diphthong have don't get an extra -i
	elseif mw.ustring.find(stems.normal, "([aeouäëöü])i$") then
		stems.types = {"i-diphthong"}
		stems.i = mw.ustring.gsub(stems.i, "ii$", "i")
	elseif #syllables == 1 then
		stems.types = {"short monosyllable"}
	else
		-- Stems ending in a simple -i get -eji- in the plural
		if mw.ustring.find(stems.normal, "i$") then
			stems.types = {"i"}
			stems.i = mw.ustring.gsub(stems.i, "ii$", export.detect_harmony(stems.i).e .. "ji")
		elseif mw.ustring.find(stems.normal, "([ouöü])$") then
			stems.types = {"rounded"}
		-- Stems ending in -ä replace the vowel with -ei-.
		elseif mw.ustring.find(stems.normal, "([^aeiouäëöü])ä$") then
			if #syllables > 1 then
				stems.types = {"a-ei"}
				stems.i = mw.ustring.gsub(stems.i, "äi$", "ei")
			end
		-- Stems ending in -a replace the vowel with -oi- in the past stem,
		-- but only if the preceding syllable does not contain rounded vowels.
		-- Otherwise, replace with -ei- as above.
		elseif mw.ustring.find(stems.normal, "([^aeiouäëöü])a$") then
			if #syllables > 1 then
				-- *-eda adjectives do not have -oi-
				if mw.ustring.find(syllables[#syllables-1], "[ou]") or mw.ustring.find(stems.normal, "[eë]d[aä]$") then
					stems.types = {"a-ei"}
					stems.i = mw.ustring.gsub(stems.i, "ai$", "ëi")
				else
					stems.types = {"a-oi"}
					stems.i = mw.ustring.gsub(stems.i, "ai$", "oi")
				end
			end
		-- Stems ending in -e may drop the -e in some forms, resulting in contraction
		elseif mw.ustring.find(stems.normal, "[^aeiouäëöü][eë]$") then
			stems.types = {"e"}
			
			stems.final = mw.ustring.gsub(stems.final, "[eë]$", "i")
			stems.final = mw.ustring.gsub(stems.final, "ji$", "i")
			
			stems.i = mw.ustring.gsub(stems.i, "[eë]i$", "i")
			
			if mw.ustring.find(stems.normal, "cc[eë]$") then
				stems.types = {"cce"}
				if not inf_e then
					stems.t = mw.ustring.gsub(stems.t, "cc[eë]t$", "ct")
				end
			elseif mw.ustring.find(stems.normal, "[pk][cs][eë]$") then
				stems.types = {"kce, pce, kse, pse"}
				stems.k = mw.ustring.gsub(stems.k, "[kp]([cs])[eë]k$", "%1k")
				stems.n = mw.ustring.gsub(stems.n, "[kp]s[eë]n$", "ss")
				stems.t = mw.ustring.gsub(stems.t, "[kp]([cs])[eë]t$", "%1t")
			elseif mw.ustring.find(stems.normal, "[aeiouäëöü%-]c[eë]$") then
				stems.types = {"Vce"}
				stems.n = mw.ustring.gsub(stems.n, "c[eë]n$", "nn")
				stems.t = mw.ustring.gsub(stems.t, "c[eë]t$", "ct")
			elseif mw.ustring.find(stems.normal, "[aeiouäëöü%-]h[eë]$") then
				stems.types = {"Vhe"}
				stems.t = mw.ustring.gsub(stems.t, "h[eë]t$", "ht")
			elseif mw.ustring.find(stems.normal, "[aeiouäëöü%-]k[eë]$") then
				stems.types = {"Vke"}
				stems.k = mw.ustring.gsub(stems.k, "k[eë]k$", "kk")
				
				if stems.normal == "näke" or stems.normal == "teke" or #syllables > 2 then
					stems.t = mw.ustring.gsub(stems.t, "ket$", "kt")
				end
			elseif mw.ustring.find(stems.normal, "[aeiouäëöü%-]n[eë]$") and ne_t_stem then
				stems.types = {"Vne-Vt"}
				stems.k = mw.ustring.gsub(stems.k, "n[eë]k$", "tk")
				stems.n = mw.ustring.gsub(stems.n, "n[eë]n$", "nn")
				stems.t = mw.ustring.gsub(stems.t, "n[eë]t$", "tt")
			elseif mw.ustring.find(stems.normal, "[aeiouäëöü%-][lnrs][eë]$") then
				stems.types = {"Vle, Vne, Vre, Vse"}
				stems.k = mw.ustring.gsub(stems.k, "([lnrs])[eë]k$", "%1k")
				stems.n = mw.ustring.gsub(stems.n, "([lnrs])[eë]n$", "%1n")
				stems.n = mw.ustring.gsub(stems.n, "([lns])n$", "%1%1")
				stems.t = mw.ustring.gsub(stems.t, "([lnrs])[eë]t$", "%1t")
			elseif mw.ustring.find(stems.normal, "[aeiouäëöü%-]m[eë]$") then
				stems.types = {"Vme"}
				if not inf_e then
					stems.t = mw.ustring.gsub(stems.t, "m[eë]t$", "nt")
				end
			elseif mw.ustring.find(stems.normal, "[chst]t[eë]$") then
				stems.types = {"cte, hte, ste, tte"}
			elseif mw.ustring.find(stems.normal, "kt[eë]$") then
				stems.types = {"kte"}
				
				stems.final = mw.ustring.gsub(stems.final, "ti$", "ci")
				stems.i = mw.ustring.gsub(stems.i, "ti$", "ci")
				
				if not inf_e then
					stems.t = mw.ustring.gsub(stems.t, "kt[eë]t$", "kt")
				end
			elseif mw.ustring.find(stems.normal, "nt[eë]$") then
				stems.types = {"nte"}
				
				stems.final = mw.ustring.gsub(stems.final, "ti$", "ci")
				stems.i = mw.ustring.gsub(stems.i, "ti$", "ci")
				stems.n = mw.ustring.gsub(stems.n, "nten$", "nn")
				
				if not inf_e then
					stems.t = mw.ustring.gsub(stems.t, "nt[eë]t$", "tt")
				end
			elseif mw.ustring.find(stems.normal, "[aeiouäëöü%-]t[eë]$") then
				stems.types = {"Vte"}
				
				stems.final = mw.ustring.gsub(stems.final, "ti$", "ci")
				stems.i = mw.ustring.gsub(stems.i, "ti$", "ci")
				
				stems.k = mw.ustring.gsub(stems.k, "t[eë]k$", "tk")
				stems.n = mw.ustring.gsub(stems.n, "t[eë]n$", "nn")
				if not inf_e then
					stems.t = mw.ustring.gsub(stems.t, "t[eë]t$", "tt")
				end
			elseif mw.ustring.find(stems.normal, "t[eë]$") then
				stems.types = {"te"}
				
				stems.final = mw.ustring.gsub(stems.final, "ti$", "ci")
				stems.i = mw.ustring.gsub(stems.i, "ti$", "ci")
			end
			
			if #syllables >= 3 then
				stems.final = mw.ustring.gsub(stems.final, "i$", "")
			end
			
			-- Simplify final consonant clusters
			stems.final = mw.ustring.gsub(stems.final, "[^aeiouäëöü%-]+([^aeiouäëöü])$", "%1")
			stems.final = mw.ustring.gsub(stems.final, "m$", "n")
		end
	end
	
	if da_stem and stems.types[1] == "Vte" then
		stems.normal = mw.ustring.gsub(stems.normal, "[eë]$", export.detect_harmony(stems.normal).a)
		stems.types = {"Vta"}
	end
	
	return stems
end

function export.detect_harmony(stem)
	local vowels = {}
	vowels.a = "ä"
	vowels.e = "e"
	vowels.u = "ü"
	
	if mw.ustring.find(stem, "[aëou]") then
		vowels.a = "a"
		vowels.e = "ë"
		vowels.u = "u"
	end
	
	return vowels
end

return export