local p = {}
local getArgs = require('Module:Arguments').getArgs

local UTF8_char = "[%z\1-\127\194-\244][\128-\191]*"

local frame
local sum = 0
local wordSum = 0

local rightToLeft = {
	["ar"] = true,
	["he"] = true
}

local greekTable = {
  ["α"] = {value=1, name="Alpha"},
  ["β"] = {value=2, name="Beta"},
  ["γ"] = {value=3, name="Gamma"},
  ["δ"] = {value=4, name="Delta"},
  ["ε"] = {value=5, name="Epsilon"},
  ["ϝ"] = {value=6, name="Digamma"},
  ["ϛ"] = {value=6, name="Stigma"},
  ["ζ"] = {value=7, name="Zeta"},
  ["η"] = {value=8, name="Eta"},
  ["θ"] = {value=9, name="Theta"},
  ["ι"] = {value=10, name="Iota"},
  ["κ"] = {value=20, name="Kappa"},
  ["λ"] = {value=30, name="Lambda"},
  ["μ"] = {value=40, name="Mu"},
  ["ν"] = {value=50, name="Nu"},
  ["ξ"] = {value=60, name="Xi"},
  ["ο"] = {value=70, name="Omicron"},
  ["π"] = {value=80, name="Pi"},
  ["ϙ"] = {value=90, name="Koppa"},
  ["ρ"] = {value=100, name="Rho"},
  ["σ"] = {value=200, name="Sigma"},
  ["τ"] = {value=300, name="Tau"},
  ["υ"] = {value=400, name="Upsilon"},
  ["φ"] = {value=500, name="Phi"},
  ["χ"] = {value=600, name="Chi"},
  ["ψ"] = {value=700, name="Psi"},
  ["ω"] = {value=800, name="Omega"},
  ["ϡ"] = {value=900, name="Sampi"},
}

local arabicTable = {
	--Aleph
	["ا"] = {value=1, name="ʾalif"},
	["ب"] = {value=2, name="bāʾ"},
	["ج"] = {value=3, name="ǧīm"},
	["د"] = {value=4, name="dāl"},
	["ه"] = {value=5, name="hāʾ"},
	["و"] = {value=6, name="wāw"},
	["ز"] = {value=7, name="zāy"},
	["ح"] = {value=8, name="ḥāʾ"},
	["ط"] = {value=9, name="ṭāʾ"},
	["ي"] = {value=10, name="yāʾ"},
	["ك"] = {value=20, name="kāf"},
	["ل"] = {value=30, name="lām"},
	["م"] = {value=40, name="mīm"},
	["ن"] = {value=50, name="nūn"},
	["س"] = {value=60, name="sīn"},
	["ع"] = {value=70, name="ʿayn"},
	["ف"] = {value=80, name="fāʾ"},
	["ص"] = {value=90, name="ṣād"},
	["ق"] = {value=100, name="qāf"},
	["ر"] = {value=200, name="rāʾ"},
	["ش"] = {value=300, name="shīn"},
	["ت"] = {value=400, name="tāʾ"},
	["ث"] = {value=500, name="thāʾ"},
	["خـ"] = {value=600, name="khāʾ"},
	["ذ"] = {value=700, name="dhāl"},
	["ض"] = {value=800, name="ḍād"},
	["ظ"] = {value=900, name="ẓāʾ"},
	["غ"] = {value=1000, name="ghayn"},
}

local hebrewTable = {
	["א"] = {value=1, name="Aleph"},
	["ב"] = {value=2, name="Bet"},
	["ג"] = {value=3, name="Gimel"},
	["ד"] = {value=4, name="Dalet"},
	["ה"] = {value=5, name="He"},
	["ו"] = {value=6, name="Vav"},
	["ז"] = {value=7, name="Zayin"},
	["ח"] = {value=8, name="Het"},
	["ט"] = {value=9, name="Tet"},
	["י"] = {value=10, name="Yod"},
	["כ"] = {value=20, name="Kaf"},
	["ל"] = {value=30, name="Lamed"},
	["מ"] = {value=40, name="Mem"},
	["נ"] = {value=50, name="Nun"},
	["ס"] = {value=60, name="Samekh"},
	["ע"] = {value=70, name="Ayin"},
	["פ"] = {value=80, name="Pe"},
	["צ"] = {value=90, name="Tsadi"},
	["ק"] = {value=100, name="Qoph"},
	["ר"] = {value=200, name="Resh"},
	["ש"] = {value=300, name="Shin"},
	["ת"] = {value=400, name="Tav"},
	["ך"] = {value=500, name="Kaf (final)"},
	["ם"] = {value=600, name="Mem (final)"},
	["ן"] = {value=700, name="Nun (final)"},
	["ף"] = {value=800, name="Pe (final)"},
	["ץ"] = {value=900, name="Tsadi (final)"},
}

local langTable = {
  ["grc"] = {lookupTable=greekTable, scriptTemplate='Script/Greek', transliterate='grc-transl'},
  ["ar"] = {lookupTable=arabicTable, scriptTemplate='Script/Arabic'},
  ["he"] = {lookupTable=hebrewTable, scriptTemplate='Script/Hebrew'},
}

local function processLetter(lang, chr)
	local function formatLetter(c)
		return frame:expandTemplate{
			title = langTable[lang].scriptTemplate,
			args = {c}
		}
	end
	
	local function formatTransliteration(c)
		if langTable[lang].transliterate then
			return frame:expandTemplate{
				title = langTable[lang].transliterate,
				args = {c}
			}
		end
	end

	local function formatNumber(c)
		indexC = string.ulower(c)
		if langTable[lang].lookupTable[indexC] then
			local value = langTable[lang].lookupTable[indexC].value
			wordSum = wordSum + value
			return value
		end
		return ' '
	end

	local div = mw.html.create("div")
					:addClass("letter")
	local p1 = div:tag("p"):wikitext(formatLetter(chr))
	local p2 = div:tag("p"):wikitext(formatTransliteration(chr))
	local p3 = div:tag("p"):wikitext(formatNumber(chr))
	return div
end

local function processWord(lang, word)
	local html = ""
	wordSum = 0
	for i, c in ipairs(word) do
		if (i ~= 1) then
	    	html = html .. '<div class="symbol">+</div>'
		end
		if langTable[lang] then
	    	html = html .. tostring(processLetter(lang, c))
	    else
	    	html = html .. c
	    end
	end
	sum = sum + wordSum
	html = '<div class="letters">'
				.. '<div class="symbol">(</div>'
				.. html
				.. '<div class="symbol">)</div>'
			.. '</div>'
			.. '<div class="word-sum">' .. wordSum .. '</div>'
	return mw.html.create("div")
				:addClass("word")
				:wikitext(html)
end

function parseStrToTable(str)
	local wordsTable = {}
	for word in str:gmatch("[^%s]+") do
		local wordTable = {}
		for letter in word:gmatch(UTF8_char) do
			table.insert(wordTable, letter)
		end
		table.insert(wordsTable, wordTable)
	end
	return wordsTable
end

function ReverseTable(myTable)
	if myTable and #myTable > 1 then
		local temp = nil
		for n = 1,math.floor(#myTable/2) do
			temp = myTable[n]
			myTable[n] = myTable[#myTable-(n-1)]
			myTable[#myTable-(n-1)] = temp
		end 
	end
end

function p.isopsephy(frameArg)
	frame = frameArg
	local args = getArgs(frame, {wrappers = 'Template:Isopsephy'})
	str = args[1]

	local html = ""
	sum = 0
	
	if args.lang and str then
		local words = parseStrToTable(str)
		if rightToLeft[args.lang] then
			ReverseTable(words)
			for i, word in ipairs(words) do
				ReverseTable(word)
			end
		end
	
		for i, word in ipairs(words) do
			if (i ~= 1) then
		    	html = html .. '<div class="symbol">+</div>'
			end
			html = html .. tostring(processWord(args.lang, word))
		end
		html = html .. '<div class="symbol">=</div>'
					.. '<div class="symbol">' .. sum .. '</div>'
	end
	
	return tostring(
			mw.html.create("div")
				:addClass("isopsephy")
				:wikitext(html)
			)
end

return p