local p = {}

local je={
	["ء"] = 0, 
	["أ"] = 1,
	["ا"] = 1,
	["إ"] = 1,
	["آ"] = 1,
	["ب"] = 2,
	["ج"] = 3,
	["د"] = 4,
	["ه"] = 5,
	["ة"] = 5,
	["و"] = 6,
	["ؤ"] = 6,
	["ز"] = 7,
	["ح"] = 8,
	["ط"] = 9,
	["ي"] = 10,
	["ى"] = 10,
	["ئ"] = 10,
	["ك"] = 20,
	["ل"] = 30,
	["م"] = 40,
	["ن"] = 50,
	["س"] = 60,
	["ع"] = 70,
	["ف"] = 80,
	["ص"] = 90,
	["ق"] = 100,
	["ر"] = 200,
	["ش"] = 300,
	["ت"] = 400,
	["ث"] = 500,
	["خ"] = 600,
	["ذ"] = 700,
	["ض"] = 800,
	["ظ"] = 900,
	["غ"] = 1000
}

local jw={
	["ء"] = 0,
    ["أ"] = 1,
    ["ا"] = 1,
    ["إ"] = 1,
    ["آ"] = 1,
    ["ب"] = 2,
    ["ج"] = 3,
    ["د"] = 4,
    ["ه"] = 5,
	["ة"] = 5,
    ["و"] = 6,
    ["ؤ"] = 6,
    ["ز"] = 7,
    ["ح"] = 8,
    ["ط"] = 9,
    ["ي"] = 10,
    ["ى"] = 10,
    ["ئ"] = 10,
    ["ك"] = 20,
    ["ل"] = 30,
    ["م"] = 40,
    ["ن"] = 50,
    ["ص"] = 60,
    ["ع"] = 70,
    ["ف"] = 80,
    ["ض"] = 90,
    ["ق"] = 100,
    ["ر"] = 200,
    ["س"] = 300,
    ["ت"] = 400,
    ["ث"] = 500,
    ["خ"] = 600,
    ["ذ"] = 700,
    ["ظ"] = 800,
    ["غ"] = 900,
    ["ش"] = 1000
}

local abjd = "ابجدهوزحطيكلمنسعفصقرشتثخذضظغ"
local abt = "ابتثجحخدذرزسشصضطظعغفقكلمنهوي"

local jomml = {
    {'ق', 'ر', 'ش', 'ت', 'ث', 'خ', 'ذ', 'ض', 'ظ'},
    {'ي', 'ك', 'ل', 'م', 'ن', 'س', 'ع', 'ف', 'ص'},
    {'ا', 'ب', 'ج', 'د', 'ه', 'و', 'ز', 'ح', 'ط'},
    ['thousand'] = 'غ'
}

local jommlw = {
    {'ق', 'ر', 'س', 'ت', 'ث', 'خ', 'ذ', 'ظ', 'غ'},
    {'ي', 'ك', 'ل', 'م', 'ن', 'ص', 'ع', 'ف', 'ض'},
    {'ا', 'ب', 'ج', 'د', 'ه', 'و', 'ز', 'ح', 'ط'},
    ['thousand'] = 'ش'
}

local function intdiv(number, divider)
    local reminder = number % divider
    return ((number - reminder) / divider), reminder
end

function p._number2jomml(thenumber, magrib)
	local j= magrib and jommlw or jomml

	function basenumber2jomml(anumber)
	    local result = ''
	    for positionkey, basenumber in ipairs({100,10,1}) do
	        local positiondigit
	        positiondigit, anumber = intdiv(anumber, basenumber)
	        if (positiondigit > 0) then
	            result = result .. (j[positionkey][positiondigit] or '')
	        end
	    end
	    return result
	end

    local result = ''
	local t,i = intdiv(thenumber,1000)
    if t>1 then
	   result = basenumber2jomml(t) .. j.thousand
    elseif t==1 then
	   result = j.thousand
	end
    return result .. basenumber2jomml(i)
end

function p._jomml2number(strnumber, magrib)
    local j=magrib and jw or je
    local r_number=0
    for i =1,mw.ustring.len( strnumber ) do
        local add = j[mw.ustring.sub( strnumber, i, i )] or 0
        if add == 1000 and r_number >0 then
        	r_number = r_number * add
    	else
        	r_number = r_number + add
    	end
    end
    return  r_number
end

function p._literary2number(strnumber, magrib)
    local j=magrib and jw or je
    local r_number=0
    for i =1,mw.ustring.len( strnumber ) do
        r_number=r_number + (j[mw.ustring.sub( strnumber, i, i )] or 0)
    end
    return  r_number
end

function p._number2abjd(thenumber, abth)
	ab = abth and abt or abjd
	local r,i = intdiv(thenumber-1, 28)
	i=i+1
	return mw.ustring.rep(mw.ustring.sub(ab, i,i),r+1)
end	

function p._abjd2number(strnumber, abth)
	ab = abth and abt or abjd
	local r,i = mw.ustring.len( strnumber )-1, mw.ustring.find(ab, mw.ustring.sub( strnumber, 1, 1 ),1,true)
	if i == nil then
		return nil
	end
	return i + (28 * r)
end

function p._number2eastern(thenumber)
	local str_number = tostring(thenumber)
	local ret_str = ''	
	for i=1,#str_number do
		ret_str = ret_str .. mw.ustring.char(0x0660 + tonumber(string.sub(str_number,i,i)))
	end
	return ret_str
end

function p._eastern2number(strnumber)
	return mw.language.getContentLanguage():parseFormattedNumber(strnumber)
end

function p._tonumber(strnumber, type)
	local ret
	if strnumber == nil then
		return nil
	end
	if type then
		local inArray = require('Module:TableTools').inArray
		if inArray({'مشرقي', 'مشرقية'}, type) then
			return p._eastern2number(strnumber)
		elseif type == 'جمل' then
			return p._jomml2number(strnumber)
		elseif type == 'جمل مغربي' then
			return p._jomml2number(strnumber, true)
		elseif inArray({'ابجدي', 'أبجدي'}, type)  then
			return p._abjd2number(strnumber)
		elseif inArray({'هجائي', 'ألفبائي', 'الفبائي'}, type)  then
			return p._abjd2number(strnumber, true)
		end
		return nil
	else
		ret = tonumber(strnumber) or  p._eastern2number(strnumber)
		if ret == nil then
			local fbyte = mw.ustring.byte(strnumber,1)
			if fbyte == 216 or fbyte == 217 then
				if mw.ustring.sub(strnumber,1,1) == mw.ustring.sub(strnumber,2,2) then
					ret = p._abjd2number(strnumber)
				else
					ret = p._jomml2number(strnumber)
				end
			else
				ret = require('Module:Roman').toArabic(strnumber)
			end
		end
		return ret
	end
end

function p._numConv(number, type)
	if type then
		local inArray = require('Module:TableTools').inArray
		if inArray({'مشرقي', 'مشرقية'}, type) then
			return p._number2eastern(number)
		elseif type == 'جمل' then
			return p._number2jomml(number)
		elseif type == 'جمل مغربي' then
			return p._number2jomml(number, true)
		elseif inArray({'ابجدي', 'أبجدي'}, type)  then
			return p._number2abjd(number)
		elseif inArray({'هجائي', 'ألفبائي', 'الفبائي'}, type)  then
			return p._number2abjd(number, true)
		end
	end
	return number
end

local function makeWrapper(funcName,firstInt,secondBool)
	return function (frame)
		local args = require('Module:Arguments with aliases').getArgs(frame)
		if firstInt then
			args[1] = p._tonumber(args[1])
		end
		if args[2] then
			if secondBool then
				args[2] = require('Module:Yesno')(args[2],false)
			end
			return p[funcName](args[1], args[2])
		else
			return p[funcName](args[1])
		end
	end
end

p['number2jomml'] = makeWrapper('_number2jomml',true,true)
p['jomml2number'] = makeWrapper('_jomml2number',false,true)
p['literary2number'] = makeWrapper('_literary2number',false,true)
p['number2abjd'] = makeWrapper('_number2abjd',true,true)
p['abjd2number'] = makeWrapper('_abjd2number',false,true)
p['number2eastern'] = makeWrapper('_number2eastern',true,false)
p['eastern2number'] = makeWrapper('_eastern2number',false,false)
p['tonumber'] = makeWrapper('_tonumber',false,false)
p['numConv'] = makeWrapper('_numConv',true,false)

return p