-- Substituição para [[Predefinição:Time ago]]
local numberSpell = require('Módulo:NumberSpell')._main
local yesno = require('Módulo:Yesno')

local p = {}

-- Tabela para converter valores de texto inseridos para valores numéricos.
timeText = {
	['segundos'] = 1,
	['minutos'] = 60,
	['horas'] = 3600,
	['dias'] = 86400,
	['semanas'] = 604800,
	['meses'] = 2678400,
	['anos'] = 31557600
}

-- Tabela contendo tabelas de possíveis unidades para usar na saída.
timeUnits = {
	[1] = { 'segundo', 'segundos', "segundo", "segundos" },
	[60] = { 'minuto', 'minutos', "minuto", "minutos" },
	[3600] = { 'hora', 'horas', "hora", "horas" },
	[86400] = { 'dia', 'dias', "dia", "dias" },
	[604800] = { 'semana', 'semanas', "semana", "semanas" },
	[2678400] = { 'mês', 'meses', "mês", "meses" },
	[31557600] = { 'ano', 'anos', "ano", "anos" }
}

function p._main( args )
	-- Inicializa as variáveis
	local lang = mw.language.getContentLanguage()
	local auto_magnitude_num
	local min_magnitude_num
	local result
	local result_unit
	local magnitude = args.magnitude
	local min_magnitude = args.min_magnitude
	local purge = args.purge
	local spell_out = args.spellout
	local spell_out_max = args.spelloutmax
	
	-- Adiciona um link purge se algo (geralmente "sim") for inserido dentro do parâmetro purge
	if purge then
		purge = ' <span class="plainlinks">([' .. mw.title.getCurrentTitle():fullUrl('action=purge') .. ' atualizar])</span>'
	else
		purge = ''
	end

	-- Verifica se o timestamp inserido é válido. Se não for, então, dá uma mensagem de erro.
	local noError, inputTime = pcall( lang.formatDate, lang, 'U', args[1], true )
	if not noError then
		return '<strong class="error">Erro: o primeiro parâmetro não pôde ser analisado como uma data ou hora.</strong>'
	end

	-- Armazena a diferença entre a hora atual e a hora introduzida, bem como o seu valor absoluto.
	local timeDiff = lang:formatDate( 'U', nil, true ) - inputTime
	local absTimeDiff = math.abs( timeDiff )

	if magnitude then
		auto_magnitude_num = 0
		min_magnitude_num = timeText[magnitude]
	else
		-- Calcula a unidade de tempo adequada, se não foi especificada como um argumento.
		local autoMagnitudeData = {
			{ denom = 63115200, amn = 31557600 },
			{ denom = 2764800, amn = 2678400 },
			{ denom = 86400, amn = 86400 },
			{ denom = 7200, amn = 3600 },
			{ denom = 120, amn = 60 }
		}
		for i, t in ipairs( autoMagnitudeData ) do
			if absTimeDiff / t.denom >= 1 then
				auto_magnitude_num = t.amn
				break
			end
		end
		auto_magnitude_num = auto_magnitude_num or 1
		if min_magnitude then
			min_magnitude_num = timeText[min_magnitude]
		else
			min_magnitude_num = -1
		end
	end

	if not min_magnitude_num then
		-- Padrão para segundos se uma magnitude inválida for inserida.
		min_magnitude_num = 1
	end

	local magnitude_num = math.max( min_magnitude_num, auto_magnitude_num )
	local result_num = math.floor ( absTimeDiff / magnitude_num )

	local punctuation_key, prefix
	if timeDiff >= 0 then -- Passado
		if result_num == 1 then
			punctuation_key = 1
		else
			punctuation_key = 2
		end
		if args.ago == '' then
			prefix = ''
		else
			prefix = (args.ago or 'há')
		end
	else -- Futuro
		if args.ago == '' then
			prefix = ''
			if result_num == 1 then
				punctuation_key = 1
			else
				punctuation_key = 2
			end
		else
			prefix = 'daqui a'
			if result_num == 1 then
				punctuation_key = 3
			else
				punctuation_key = 4
			end
		end
	end
	result_unit = timeUnits[ magnitude_num ][ punctuation_key ]

	-- Converte numerais para palavras se for o caso.
	spell_out_max = tonumber( spell_out_max ) -- Poderia causar erros de script, se não um número.
	local result_num_text
	if ( spell_out == 'auto' and 1 <= result_num and result_num <= 9 and result_num <= ( spell_out_max or 9 ) )
		or ( yesno( spell_out ) and 1 <= result_num and result_num <= 100 and result_num <= ( spell_out_max or 100 ) )
	then
		result_num_text = numberSpell( result_num )
	else
		result_num_text = tostring( result_num )
	end

	result = prefix .. ' ' .. result_num_text .. ' ' .. result_unit -- Espaços para prefixo foram adicionados anteriormente.
	return result .. purge
end

function p.main( frame )
	local args = require( 'Módulo:Arguments' ).getArgs( frame, {
		valueFunc = function( k, v )
			if v then
				v = v:match( '^%s*(.-)%s*$' ) -- Apara espaço em branco.
				if k == 'há' or v ~= '' then
					return v
				end
			end
			return nil
		end,
		wrappers = 'Predefinição:Time ago'
	})
	return p._main( args )
end

return p