local export = {}
local U = mw.ustring.char
local gsub = mw.ustring.gsub
local match = mw.ustring.match
local sub = mw.ustring.sub
local pesh = U(0x64F)
local cons = "ببپتثجچحخدذرزژسشصضطظعغفقکگلࣇمنݨویہھٹڈڑ"
local cons5 = "ببپتثجچحخدذرزژسشصضطظعغفقکگلࣇمنݨوہھٹڈڑ"
local cons3 = "ھ"
local vowels = "اآیئےۓوؤ"
local ZZP = "َُِ"
local conv = {
		["क"] = "ک", ["ख"] = "کھ", ["ग"] = "گ", ["घ"] = "گھ", ["ङ"] = "ن", 
		["च"] = "چ", ["छ"] = "چھ", ["ज"] = "ج", ["झ"] = "جھ", ["ञ"] = "ڃ", 
		["ट"] = "ٹ", ["ठ"] = "ٹھ", ["ड"] = "ڈ", ["ढ"] = "ڈھ", ["ण"] = "ݨ", 
		["त"] = "ت", ["थ"] = "تھ", ["द"] = "د", ["ध"] = "دھ", ["न"] = "ن", 
		["प"] = "پ", ["फ"] = "پھ", ["ब"] = "ب", ["भ"] = "بھ", ["म"] = "م", 
		["य"] = "+ی+", ["र"] = "ر", ["ल"] = "ل", ["व"] = "+و+", ["ळ"] = "ࣇ", 
		["श"] = "ش", ["ष"] ="شؕ", ["स"] = "س", ["ह"] = "ہ", 
['क़'] = 'ق', ['ख़'] = 'خ', ['ग़'] = 'غ', ['ऴ'] = 'ࣇ',
	['ज़'] = 'ز', ['ष़'] = 'ࣇ', ['झ़'] = 'ژ', ['श़'] = 'ژ', ['ड़'] = 'ڑ', ['ढ़'] = 'ڑھ',
	['फ़'] = 'ف', ['थ़'] = 'ث', ['ऩ'] = 'ن', ['ऱ'] = 'ر',
	-- ['ज्ञ'] = 'گْی',
	
		["अ"] = "اَ", ["आ"] = "آ", ["इ"] = "اِ", ["ई"] = "اِی", ["उ"] = "اُ", ["ऊ"] = "اُو", ["ऋ"] = "ر", ["ॠ"] = "ر",
		["ऌ"] = "ل", ["ॡ"] = "ل", ["ए"] = "اَی", ["ऐ"] = "ایٖ", ["ओ"] = "او", ["औ"] = "اَو", 
 ["ऑ"] = "آ", 
 ["ऍ"] = "ای", 
 ["ऒ"] = "آ", 
 ["ऎ"] = "ای",
		
["ा"] = "ا", ["ि"] = "ِ",  ["ी"] = "ِی", 
["ु"] = "ُ", ["ू"] = "ُو",
["ृ"] = "ر", 
["ॄ"] = "ر", 
["ॢ"] = "ل",
["ॣ"] = "ل", 
["े"] = "َی",
["ै"] = "یٖ",
["ो"] = "ٗو", 
["ौ"] = "َو",
["ॉ"] = "‍ا",
["ॅ"] = "ی", 
["ॊ"] = "آ", 
["ॆ"] = "ای",
["्"] = "ْ", 
	
		["ँ"] = "ں",
 ["ं"] = "ں", ["ः"] = "ہ", ["ऽ"] = "",

		["०"] = "۰", ["१"] = "۱", ["२"] = "۲", ["३"] = "۳", ["४"] = "۴", ["५"] = "۵", ["६"] = "۶", ["७"] = "۷", ["८"] = "۸", ["९"] = "۹",
	        
	    ["॥"] = " ", ["।"] = "۔",
 ["?"] = "؟", ["—"] = ":",
 [";"] = "؛", ["%"] = "٪",  [","] = "،", ["!"] = "!", 
	    
	    ["ᳵ"] = "خ", ["ᳶ"] = "ف",
    
		["ॐ"] = "اوم",
    	
    	["*"] = "*",
	['॰'] = '.',
}

local nasal_assim_short = {
	['क'] = 'ङ्', ['ख'] = 'ङ्', ['ग'] = 'ङ्', ['घ'] = 'ङ्', ['ङ'] = 'ङ्',
	['च'] = 'ञ्', ['छ'] = 'ञ्', ['ज'] = 'ञ्', ['झ'] = 'ञ्', ['ञ'] = 'ञ्',  
	['ट'] = 'ण्', ['ठ'] = 'ण्', ['ड'] = 'ण्', ['ढ'] = 'ण्', ['ण'] = 'ण्',
	['त'] = 'न्', ['थ'] = 'न्', ['द'] = 'न्', ['ध'] = 'न्', ['न'] = 'न्',
	['प'] = 'म्', ['फ'] = 'म्', ['ब'] = 'म्', ['भ'] = 'म्', ['म'] = 'म्',
	['व'] = 'म्', ['य'] = 'ँ', ['ष'] = 'न्', ['श'] = 'न्', ['स'] = 'न्',
	['ह'] = 'ँ'
}

local nasal_assim_long = {
	['क'] = 'ँ', ['ख'] = 'ँ', ['ग'] = 'ङ्', ['घ'] = 'ङ्', ['ङ'] = 'ङ्',
	['च'] = 'ँ', ['छ'] = 'ँ', ['ज'] = 'ञ्', ['झ'] = 'ञ्', ['ञ'] = 'ञ्',  
	['ट'] = 'ँ', ['ठ'] = 'ँ', ['ड'] = 'ण्', ['ढ'] = 'ण्', ['ण'] = 'ण्',
	['त'] = 'न्', ['थ'] = 'न्', ['द'] = 'न्', ['ध'] = 'न्', ['न'] = 'न्',
	['प'] = 'ँ', ['फ'] = 'ँ', ['ब'] = 'म्', ['भ'] = 'म्', ['म'] = 'म्',
	['ह'] = 'ँ'
}

-- These clusters when occurring word-finally will not trigger a schwa added
-- after them even though the second consonant is in special_cons, which normally
-- causes the extra schwa to be added. NOTE: The clusters are reversed from their
-- ultimate effect, e.g. the first cluster is written 'ml' but actually applies
-- to words ending in 'lm'. The clusters below overall refer to the six clusters
-- describable by [rl][mnv], i.e. rm, rn, rv, lm, ln, lv.
local perm_cl = {
	['म्ल'] = true, ['व्ल'] = true, ['न्ल'] = true,
	['म्र'] = true, ['व्र'] = true, ['न्र'] = true,
}

local all_cons, special_cons = 'कखगघङचछजझञटठडढतथदधपफबभशषसयरलवहणनम', 'यरलवहनम'
local vowel, vowel_sign = '*َaिुृेोाीूैौॉॅॆॊ\'', 'अइउएओआईऊऋऐऔऑऍ\''
local long_vowel, short_vowel = 'ाीूआईऊ', '*َaिुृॉॅॆॊअइउऋऑऍोैौेओऔएऐ\''
local syncope_pattern = '([' .. vowel .. vowel_sign .. '])(़?[' .. all_cons .. '])َ(़?[' .. all_cons .. '])([ंँ]?[' .. vowel .. vowel_sign .. '])'

local function rev_string(text)
	local result, length = {}, mw.ustring.len(text)
	for i = length, 1, -1 do
		table.insert(result, mw.ustring.sub(text, i, i))
	end
	return table.concat(result)
end

function export.tr(text, lang, sc)
	--force word-final anusvara to behave as a pure nasal
	text = gsub(text, 'ं$', 'ں')
	text = gsub(text, 'ं ', 'ں ')
	text = gsub(text, 'ं%-', 'ں-')
    text = gsub(text, 'ं%।', 'ں۔')
    text = gsub(text, 'ं%,', 'ں،')
	--abbreviation dot
	text = gsub(text, '॰', '.')
	text = gsub(text, '([' .. all_cons .. ']़?)([' .. vowel .. '्]?)', function(c, d)
		return c .. (d == "" and 'َ' or d) end)
	for word in mw.ustring.gmatch(text, "[ऀऀ-ॿَ*]+") do
		local orig_word = word
		word = rev_string(word)
		word = gsub(word, '^َ(़?)([' .. all_cons .. '])(.)(.?)', function(opt, first, second, third)
			return (((match(first, '[' .. special_cons .. ']') and match(second, '्') and not perm_cl[first..second..third])
				or match(first .. second, 'य[ी]'))
				and 'ا' or "") .. opt .. first .. second .. third end)
		while match(word, syncope_pattern) do
			word = gsub(word, syncope_pattern, '%1%2%3%4')
		end
		word = rev_string(word)
		--sometimes chandrabindu != anusvara
		word = gsub(word, '([' .. short_vowel .. long_vowel .. '])ं([सशषवय])', function(prev, succ)
			return prev .. (nasal_assim_short[succ] or "ن") .. succ
		end)
		word = gsub(word, '([' .. short_vowel .. long_vowel .. '])ँ([सशषवय])', function(prev, succ)
			return prev .. "ن" .. succ
		end)
		--force chandrabindu to behave as anusvara
		word = gsub(word, 'ँ', 'ं')
		word = gsub(word, '([' .. short_vowel .. '])ं(.़?)', function(prev, succ)
			return prev .. (nasal_assim_short[succ] or "ن") .. succ
		end)
		word = gsub(word, '([' .. long_vowel .. '])ं(.़?)', function(prev, succ)
			return prev .. (nasal_assim_long[succ] or "ن") .. succ
		end)
		-- Convert * to %* so we can match it in a regex.
		local escaped_orig_word = gsub(orig_word, "%*", "%*")
		text = gsub(text, escaped_orig_word, word)
	end
	text = gsub(text, '.़?', conv)
    text = gsub(text, 'جْڃ', 'گْی')
    text = gsub(text, 'ڃز', 'نز')
    text = gsub(text, '%*', 'ا')
text = gsub(text, "ک़", "ق")
text = gsub(text, "کھ़", "خ")
text = gsub(text, "گ़", "غ")
text = gsub(text, "پھ़", "ف")
text = gsub(text, "ج़", "ز")
text = gsub(text, "جھ़", "ژ")
text = gsub(text, "ش़", "ژ")
text = gsub(text, "ڈ़" ,"ڑ")
text = gsub(text, "ڈھ़" ,"ڑھ")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])ی$", "%1ے")
text = mw.ustring.gsub(text, "([رجچبپدتٹثکگلسشزژخقفغنم])(ْ)%1" ,"%1ّ") 
text = mw.ustring.gsub(text, "([" .. vowels .. ZZP .. "])اِ", "%1ئِ")
text = mw.ustring.gsub(text, "([" .. vowels .. ZZP .. "])اُو", "%1ؤُ")
text = mw.ustring.gsub(text, "([" .. vowels .. ZZP .. "])اَی", "%1ئِے")
text = mw.ustring.gsub(text, "([" .. vowels .. cons .. ZZP .. "])اِی", "%1ئی")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])یٖ$", "%1َے")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])َی ", "%1ِے ")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])یٖ ", "%1َے ")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])َی۔", "%1ِے۔")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])یٖ۔", "%1َے۔")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])َی،", "%1ِے،")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])یٖ،", "%1َے،")

text = mw.ustring.gsub(text, "([" .. cons5 .. "])(ِ)$", "%1ی")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])(ُ)$", "%1و")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])(ِ) ", "%1ی ")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])(ُ) ", "%1و ")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])(ِ)۔", "%1ی۔")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])(ُ)۔", "%1و۔")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])(ِ)،", "%1ی،")
text = mw.ustring.gsub(text, "([" .. cons5 .. "])(ُ)،", "%1و،")
text = mw.ustring.gsub(text, "([" .. vowels .. cons .. ZZP .. "])او", "%1ؤَ")
text = mw.ustring.gsub(text, "+", "")
text = mw.ustring.gsub(text, "([" .. cons3 .. "])([" .. ZZP .. "])", "%2%1")
text = mw.ustring.gsub(text, "ئِی", "ئی")
text = mw.ustring.gsub(text, "ئےں","ئَیں")
text = mw.ustring.gsub(text, "یَہ","یِہ")
text = mw.ustring.gsub(text, "पे","پِہ")
text = mw.ustring.gsub(text, "اَیں","ئَیں")
text = mw.ustring.gsub(text, "کَیہ","کِہ")
text = mw.ustring.gsub(text, "وَو","وہ")
	return mw.ustring.toNFC(text)
end

return export