local export = {}

local lang = require("Module:languages").getByCode("ary")
local sc = require("Module:scripts").getByCode("Arab")

local str_gsub = string.gsub
local ugsub = mw.ustring.gsub

local correspondences = {
    ["ʾ"] = "ʔ",  -- 이 글자는 모로코 아랍어에서 거의 발음되지 않으므로 생략할 수 있습니다.
    ["ṯ"] = "t",  -- "θ" 대신 모로코 아랍어에서는 주로 "t"로 발음됩니다.
    ["j"] = "ʒ",  -- "d͡ʒ" 대신 "ʒ"가 사용됩니다.
    ["ḥ"] = "ħ",  -- 그대로 유지
    ["ḵ"] = "x",  -- 그대로 유지
    ["ḏ"] = "d",  -- "ð" 대신 "d"로 발음됩니다.
    ["š"] = "ʃ",  -- 그대로 유지
    ["ṣ"] = "sˤ",  -- 그대로 유지
    ["ḍ"] = "dˤ",  -- 그대로 유지
    ["ṭ"] = "tˤ",  -- 그대로 유지
    ["ẓ"] = "zˤ",  -- "ðˤ" 대신 "zˤ"로 발음됩니다.
    ["ž"] = "ʒ",  -- 그대로 유지
    ["ʿ"] = "",  -- 이 글자는 모로코 아랍어에서 거의 발음되지 않으므로 생략할 수 있습니다.
    ["ḡ"] = "ɣ",  -- 그대로 유지
    ["ḷ"] = "l",  -- "ɫ" 대신 "l"로 발음됩니다.
    ["ū"] = "u",  -- "uː" 대신 "u"로 단축 발음됩니다.
    ["ī"] = "i",  -- "iː" 대신 "i"로 단축 발음됩니다.
    ["ā"] = "a",  -- "aː" 대신 "a"로 단축 발음됩니다.
    ["y"] = "j",  -- 그대로 유지
    ["g"] = "ɡ",  -- 그대로 유지
    ["ē"] = "e",  -- "eː" 대신 "e"로 단축 발음됩니다.
    ["ō"] = "o",  -- "oː" 대신 "o"로 단축 발음됩니다.
    [""] = "",  -- 공백 유지
}

local vowels = "aāeēiīoōuū"
local vowel = "[" .. vowels .. "]"
local long_vowels = "āēīōū"
local long_vowel = "[" .. long_vowels .. "]"
local consonant = "[^" .. vowels .. ". -]"
local syllabify_pattern = "(" .. vowel .. ")(" .. consonant .. "?)(" .. consonant .. "?)(" .. vowel .. ")"
local tie = "‿"
local closed_syllable_shortening_pattern = "(" .. long_vowel .. ")(" .. tie .. ")" .. "(" .. consonant .. ")"

local function syllabify(text)
	text = ugsub(text, "%-(" .. consonant .. ")%-(" .. consonant .. ")", "%1.%2")
	text = str_gsub(text, "%-", ".")

	-- Add syllable breaks.
	for _ = 1, 2 do
		text = ugsub(
				text,
				syllabify_pattern,
				function(a, b, c, d)
					if c == "" and b ~= "" then
						c, b = b, ""
					end

					return a .. b .. "." .. c .. d
				end
		)
	end

	-- Add ties between word-final vowels and word-initial consonant clusters.
	text = ugsub(text, "(" .. vowel .. ") (" .. consonant .. ")%.?(" ..
			consonant .. ")", "%1" .. tie .. "%2.%3")

	return text
end

local function closed_syllable_shortening(text)
	local shorten = {
    ["ā"] = "a",  -- 장모음 "ā"는 단모음 "a"로 변환됩니다.
    ["ē"] = "i",  -- "ē"는 모로코 아랍어에서 보통 "i"로 발음됩니다.
    ["ī"] = "i",  -- 장모음 "ī"는 단모음 "i"로 변환됩니다.
    ["ō"] = "u",  -- "ō"는 모로코 아랍어에서 보통 "u"로 발음됩니다.
    ["ū"] = "u",  -- 장모음 "ū"는 단모음 "u"로 변환됩니다.
}

	text = ugsub(text,
			closed_syllable_shortening_pattern,
			function(vowel, tie, consonant)
				return shorten[vowel] .. tie .. consonant
			end)

	return text
end

function export.link(term)
	return require("Module:also/link").full_link { term = term, lang = lang, sc = sc }
end

function export.toIPA(list, silent_error)
	local translit

	if list.tr then
		translit = list.tr
	elseif list.Arabic then
		--	Returns an error if the word contains alphabetic characters that are not Arabic.
		require("Module:script utilities").checkScript(list.Arabic, "Arab")

		translit = lang:transliterate(list.Arabic)

		if not translit then
			if silent_error then
				return ''
			else
				error('Module:ary-translit failed to generate a transliteration from "' .. list.Arabic .. '".')
			end
		end
	else
		if silent_error then
			return ''
		else
			error('모로코 아랍어 텍스트가 입력되지 않았습니다.')
		end
	end

	translit = str_gsub(translit, "llāh", "ḷḷāh")
	translit = ugsub(translit, "([iī] ?)ḷḷ", "%1ll")

	-- Remove the transliterations of any tāʾ marbūṭa not marked with a sukūn.
	translit = str_gsub(translit, "%(t%)", "")
	-- Prodelision after tāʾ marbūṭa
	translit = ugsub(translit, "(" .. vowel .. ") " .. vowel, "%1 ")
	
	translit = ugsub(translit, "%-?l%-?", "l")

	translit = syllabify(translit)
	translit = closed_syllable_shortening(translit)

	local output = ugsub(translit, ".", correspondences)

	output = str_gsub(output, "%-", "")

	return output
end

function export.show(frame)
	local params = {
		[1] = { list = true, allow_holes = true },
		["tr"] = { list = true, allow_holes = true },
		["qual"] = { list = true, allow_holes = true },
		["nl"] = {type = "boolean"},
	}

	local args = require("Module:parameters").process(frame:getParent().args, params)
	mw.logObject(args)
	local Arabic_words = args[1]
	local transliterations = args.tr
	local qualifiers = args.qual
	local nl = args.nl

	if not (Arabic_words.maxindex > 0 or transliterations.maxindex > 0) then
		if mw.title.getCurrentTitle().nsText == "Template" then
			Arabic_words[1] = "كَلِمَة"
			Arabic_words.maxindex = 1
		else
			error('Please provide vocalized Arabic in the first parameter of {{[[Template:ar-IPA|ar-IPA]]}}, or transliteration in the "tr" parameter.')
		end
	end

	local pronunciations = {}
	local function parameter(name)
		return "|" .. name .. "="
	end
	for i = 1, math.max(Arabic_words.maxindex, transliterations.maxindex) do
		local Arabic = Arabic_words[i]
		local tr = transliterations[i]
		local qual = qualifiers[i]

		if not (Arabic or tr) then
			error("There is a gap in the parameters. Provide either "
					.. parameter(i) .. " or " .. parameter("tr" .. i) .. ".")
		elseif Arabic and tr then
			mw.logObject("Duplicate parameters " .. parameter(i) .. " and "
					.. parameter("tr" .. i) .. " in {{ar-IPA}},")
		end

		-- Could check here that there isn ot
		local pron = export.toIPA { Arabic = Arabic, tr = tr }
		table.insert(pronunciations, { pron = "/" .. pron .. "/", qualifiers = { qual } })
	end

	if nl then
		return require("Module:IPA").format_IPA_multiple(lang, pronunciations)
	else
		return require("Module:IPA").format_IPA_full { lang = lang, items = pronunciations }
	end
end

return export