
local MAJOR_VERSION = "LibRoman-1.0"
local MINOR_VERSION = tonumber(("$Revision: 54069 $"):match("(%d+)")) - 100000

local lib = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)

if (not lib) then return; end

--[[ Create a table with valid roman numbers and their letters ]]--
lib.tRoman = nil;
lib.tRoman = {};
table.insert(lib.tRoman, { value = 1000, letter = "M" });
table.insert(lib.tRoman, { value = 900, letter = "CM" });
table.insert(lib.tRoman, { value = 500, letter = "D" });
table.insert(lib.tRoman, { value = 400, letter = "CD" });
table.insert(lib.tRoman, { value = 100, letter = "C" });
table.insert(lib.tRoman, { value = 90, letter = "XC" });
table.insert(lib.tRoman, { value = 50, letter = "L" });
table.insert(lib.tRoman, { value = 40, letter = "XL" });
table.insert(lib.tRoman, { value = 10, letter = "X" });
table.insert(lib.tRoman, { value = 9, letter = "IX" });
table.insert(lib.tRoman, { value = 5, letter = "V" });
table.insert(lib.tRoman, { value = 4, letter = "IV" });
table.insert(lib.tRoman, { value = 1, letter = "I" });

function lib:R(value)
	--[[ Try converting it to a Number ]]--
	value = tonumber(value);
	
	--[[ Non-numerics can't be converted obviously so return nil ]]--
	if (not value) then return; end
	
	--[[ In general, the number zero did not have its own Roman numeral, but a primitive form (nulla).
	     Only one instance of a Roman numeral for zero is known. About 725, Bede or one of his colleagues used the letter N, the initial of nullae.
	     http://en.wikipedia.org/wiki/Roman_numerals ]]--
	if (value == 0) then return "N", 0; end
	
	local alpha = ""; --[[ Our Return Value ]]--
	local bravo = value; --[[ Original Value ]]--
	local tango = math.abs(value); --[[ What's left to convert (absolute) ]]--
	
	--[[ Go through our table with valid Roman Numbers ]]--
	for index, tNumber in ipairs(lib.tRoman) do
		
		--[[ Keep adding as many letters as we need ]]--
		while (tango >= tNumber.value) do
			alpha = alpha .. tNumber.letter;
			tango = tango - tNumber.value;
		end
		
	end
	
	--[[ Return Converted, Original, Negative ]]--
	return alpha, bravo, (value < 0) or nil;
end
--[[ Some extra handles for the same thing ]]--
function lib:Roman(...) return lib:R(...); end
function lib:ToRoman(...) return lib:R(...); end
function lib:ArabicToRoman(...) return lib:R(...); end

function lib:A(roman)
	local neg = nil;
	roman = string.upper(roman); --[[ Rather then checking for both variants ]]--
	
	--[[ Negative, someone will pass it sometime ]]--
	if (string.sub(roman, 1, 1) == "-") then
		roman = string.sub(roman, 2);
		neg = true;
	end
	
	--[[ Check for invalid chars ]]--
	if (string.find(roman, "[^MDCLXVI]")) then
		if (roman == "N") then
			return 0, Roman;
		else return; end
	end
	
	local alpha = 0; --[[ Our return value ]]--
	local bravo = roman; --[[ Original value ]]--
	local tango = roman; --[[ What's left to convert ]]--
	
	--[[ Go through our table with valid Roman Numbers ]]--
	for index, tNumber in ipairs(lib.tRoman) do
		
		--[[ Length of string to check for Roman Numbers this time ]]--
		local rLength = string.len(tNumber.letter);
		
		--[[ Check begining of string for a match until it fails ]]--
		while (string.sub(tango, 1, rLength) == tNumber.letter) do
			alpha = alpha + tNumber.value;
			tango = string.sub(tango, (rLength + 1));
		end
		
	end
	
	--[[ If there is anything at all left in tango the passed string was not correct ]]--
	if (tango ~= "") then return; end
	
	--[[ Return Converted, Original, Negative ]]--
	return alpha, bravo, neg;
end
--[[ Some extra handles for the same thing ]]--
function lib:Arabic(...) return lib:A(...); end
function lib:ToArabic(...) return lib:A(...); end
function lib:RomanToArabic(...) return lib:A(...); end

--[[ I got so used to calling 1-10 system Decimals so gonna provide overloads for that aswell ]]--
function lib:D(...) return lib:A(...); end
function lib:Decimal(...) return lib:A(...); end
function lib:ToDecimal(...) return lib:A(...); end
function lib:RomanToDecimal(...) return lib:A(...); end