local getArgs = require('Module:Arguments').getArgs
local quality = {}
local cfg = {
	['link'] = 'link',
	['text'] = 'texto do link',
	['category'] = 'sobre',
	['image'] = 'imagem',
	['size'] = 'tamanho',
	['description'] = 'texto',
	['talk'] = 'discussão',
	['page'] = 'página',
	['quality'] = 'qualidade',
	['format'] = 'predefinição',
	['date'] = 'rev',
	['reason'] = 'motivo',
	['default-image'] = 'Exemplo.svg',
	['nominate-to-GA'] = 'indique para EAD quando o artigo satisfizer os critérios de artigo bom',
	['image-importance'] = 'Escala-laranja-$1de4.svg',
	['image-importance-unknown'] = 'Escala-laranja-PA.svg',
	['image-quality'] = 'Escala-azul-$1de6.svg',
	['pagetype-0'] = 'artigo',
	['pagetype-100'] = 'portal',
	['pagetype-102'] = 'anexo',
	['pagetype-other'] = 'conteúdo', -- "página" teria problemas de concordância
	['importance-text'] = 'Para o \'\'\'[[$1|$2]]\'\'\' este $3 possui \'\'\'[[Predefinição:Escala de importância|importância]] $4\'\'\'. ' ..
		'Se você se interessa pelo assunto, visite o projeto para conhecer as tarefas e discussões em curso.',
	['importance-unknown'] = 'ainda não avaliada',
	['project-talk-page'] = 'Wikipédia Discussão:Projetos/$1',
	['no-reason'] = 'motivo não informado',
	['category-quality'] = '!Artigos de qualidade $1 sobre $2',
	['category-quality-5'] = '!Artigos bons sobre $2',
	['category-quality-6'] = '!Artigos destacados sobre $2',
	['category-quality-unknown'] = '!Artigos de qualidade desconhecida sobre $1',
	['category-quality-review-old-subject'] = '!Artigos sobre $1 por reavaliar',
	['category-quality-review-old'] = '!Artigos por reavaliar',
	['category-quality-review-new'] = '!Artigos com avaliação revisada',
	['category-quality-review-conflict'] = '!Artigos com avaliações conflitantes-$1',
	['category-quality-review-unknown-date'] = '!Artigos avaliados em uma data desconhecida',
	['category-quality-by-module'] = '!Artigos com qualidade estimada automaticamente',
	['category-importance'] = '!Artigos de importância $1 sobre $2',
	['category-importance-unknown'] = '!Artigos de importância desconhecida sobre $1',
	['quality-aliases'] = {
		['AB'] = 5,
		['AD'] = 6
	},
	['quality-min'] = 1,
	['quality-max'] = 6,
	['quality-format'] = 'Qualidade $1 ($2)',
	['project-contact'] = 'Se não tiver suas questões respondidas nesta página de discussão procure o(s) wikiprojeto(s) acima.',
	['page-evaluated'] = 'Este $1 foi avaliado $2',
	['page-evaluated-by-module'] = 'Este $1 foi avaliado [[Wikipédia:Avaliação automática|automaticamente]] $2',
	['page-elected'] = 'Este $1 foi eleito $2',
	['quality-value'] = 'com <b title="$2">[[Wikipédia:Qualidade|qualidade]] $1</b>',
	['quality-value-5'] = 'um <b>$3 bom</b>',
	['quality-value-6'] = 'um <b>$3 destacado</b>',
	['quality-text'] = '$1.',
	['quality-text-and-projects'] = '$1 e faz parte do âmbito de $2: $3.',
	['quality-text-with-date'] = '$1 em $2.',
	['quality-text-with-date-and-projects'] = '$1 em $2 e faz parte do âmbito de $3: $4.',
	['projects-singular'] = 'um WikiProjeto',
	['projects-plural'] = '$1 WikiProjetos'
}

local function msg(m, ...)
	return mw.message.newRawMessage(m):params{...}:plain()
end

quality[2] = {
	minBytesRef =  {2000, 'menos de 2000 bytes'},
	minBytesNoRefSection = {8000, 'menos de 8000 bytes e não tem seção de referências'},
	noTemplates = {{'mínimo', 'contexto', 'reciclagem', 'reciclar-sobre'}, 'encontrada predefinição:%s'},
	parMaxBytes = {2500, 'parágrafo muito grande (%d bytes): \'%s...\''},
	links = {10, 'menos de 10 ligações internas'},
	minParagraphs = {5, 'menos de 5 parágrafos'}
}

quality[3] = {
	noTemplates = {{'esboço', 'wikificação', 'revisão', 'revisão-sobre'}, 'encontrada predefinição:%s'},
	needRefSection = {true, 'não tem seção de referências'},
	minBytes = {12000, 'menos de 12000 bytes'},
	links = {30, 'menos de 30 ligações internas'},
	sections = {2, 'menos de 2 seções'},
	refs = {5, 'menos de 5 referências'},
	images = {1, 'não tem imagem'},
	allSecRef = {true, 'não encontrada referência na seção \'%s\''}
}

quality[4] = {
	noTemplates = {{'artigo com problemas', 'artigo longo', 'artigo sobre direito com problemas', 'bsre', 'coi', 'caracteres não-padrão',
		'conflito interwiki', 'contextualizar2', 'conteúdo parcial', 'controverso', 'corrigir', 'ctx2', 'curiosidades', 'direitos-autorais',
		'disputa-bpv', 'divisão', 'em tradução', 'expandir', 'expandir2', 'fusão', 'fusão com', 'fusão de', 'fusão vot', 'global',
		'global/brasil', 'global/lusofonia', 'global/portugal', 'hanzi', 'idioma estrangeiro', 'matrad', 'mtag', 'multitag', 'má introdução',
		'má tradução', 'não informado', 'não informado n', 'não-enc', 'não-enciclopédico', 'não-enciclopédico2', 'parcial', 'parcialcontroverso',
		'publicidade', 'rec', 'reciclagem', 'reciclar-sobre', 'ren-pag', 'renomear página', 'revisão', 'revisão de tradução', 'revisão-sobre',
		's-fontes-bpv', 'sem cat', 'sem-fontes-bpv', 'sem-fontes-sobre', 'semimagem-arquitetura', 'semimagem-sobre', 'separar', 'suspeito2',
		'tradução de', 'vda2', 'wikificação'}, 'encontrado predefinição:%s'},
	minBytes = {20000, 'menos de 20000 bytes'},
	links = {50, 'menos de 50 ligações internas'},
	sections = {4, 'menos de 4 seções'},
	refs = {10, 'menos de 10 referências'},
	images = {2, 'só tem uma imagem'}
}

quality[5] = {
	templates = {{'artigo bom', 'lista boa', 'anexo bom'}, 'eleito pela comunidade'}
}

quality[6] = {
	templates = {{'artigo destacado', 'anexo destacado', 'lista destacada', 'portal destacado'}, 'eleito pela comunidade'}
}

local refTemplates = {'referências', 'ref-section', 'refsection', 'rodapé referências', 'reflist', 'referencias', 'notas e referências'}
local refNoTemplates = {'==%s-[Rr]eferências%s-=='}
local imageTemplates = {'imagem dupla'}
local fileNsAliases = {'ficheiro', 'imagem', 'image', 'file', 'arquivo'}
local otherImages = {'{{.-[Ii]magem *=.-%.%a%a%a%a?'}
local exceptions = {'Referências', 'Ver também', 'Notas', 'Notas e referências','Discografia','Galeria de imagens',
	'Referências gerais', 'Leitura adicional', 'Subdivisões', 'Leitura recomendada', 'Ligações externas', 'Bibliografia'}

local getClassForText = function(text)
	local bytes = #text
	local hasRefSection = false
	local images = 0
	local tList = {}
	local paragraphs = 0
	local lang = mw.language.getContentLanguage()

	local hasitem = function(tbl, item)
		for i = 1, #tbl do
			if tbl[i] == item then
				return true
			end
		end

		return false
	end

	local count = function(txt, pattern)
		local c = 0

		for i in mw.ustring.gmatch(txt, pattern) do
			c = c + 1
		end

		return c
	end

	-- Verificando as predefinições; Checking the templates
	for t in mw.ustring.gmatch(text, '{{ *([^|}\n]+)[ \n]*[|}]') do
		t = lang:lcfirst( mw.ustring.gsub( t, '_', ' ' ) )

		if hasitem(quality[6].templates[1], t) then
			return {6, quality[6].templates[2]}    -- Q6: Artigo destacado; Featured article
		elseif hasitem(quality[5].templates[1], t) then
			return {5, quality[5].templates[2]}    -- Q5: Artigo bom; Good article
		elseif not hasRefSection and hasitem(refTemplates, t) then
			hasRefSection = true
		elseif hasitem(imageTemplates, t) then
			--FIXME: Imagem dupla deve contar como uma única imagem?
			images = images + 1
		elseif hasitem(quality[2].noTemplates[1], t) then
			noTemplate = {1, mw.ustring.format(quality[2].noTemplates[2], t)}  -- Q1: Predefinição proibida para Q2; Template prohibited for Q2
		elseif hasitem(quality[3].noTemplates[1], t) then
			noTemplate = {2, mw.ustring.format(quality[3].noTemplates[2], t)}  -- Q2: Predefinição proibida para Q3; Template prohibited for Q3
		elseif hasitem(quality[4].noTemplates[1], t) then
			noTemplate = {3, mw.ustring.format(quality[4].noTemplates[2], t)}  -- Q3: Predefinição proibida para Q4; Template prohibited for Q4
		end
		if not hasitem(tList, t) then
			table.insert(tList, t)
		end
	end

	if bytes < quality[2].minBytesRef[1] then
		return {1, quality[2].minBytesRef[2]}         -- Q1: Página é muito pequena; Page is too small
	end

	-- Verificando referências fora de predefinição; Checking referências outside templates
	if not hasRefSection then
		local n = 0

		for i = 1, #refNoTemplates do
			text, n = mw.ustring.gsub(text, refNoTemplates[i], '')

			if n > 0 then
				hasRefSection = true
			end
		end
	end

	if not hasRefSection and bytes < quality[2].minBytesNoRefSection[1] then
		return {1, quality[2].minBytesNoRefSection[2]}       -- Q1: Artigo pequeno sem referências; Small article without references
	end

	-- Removendo e contando notas de rodapé; Removing and counting citations
	-- FIXME: "refs" deveria ser 1 (não 2) quando text='A<ref>B</ref>C<ref>B</ref>D'
	local textNoRef, refs1, refs2, refs
	textNoRef, refs1 = mw.ustring.gsub(text, '<[Rr][Ee][Ff]>.-</[Rr][Ee][Ff]>', '')
	textNoRef, refs2 = mw.ustring.gsub(textNoRef, '<[Rr][Ee][Ff] [^>]-[^/]>.-</[Rr][Ee][Ff]>', '')
	-- FIXME: Guardar a quantidade de nomes (únicos) de refs reutilizados?
	textNoRef = mw.ustring.gsub(textNoRef, '<[Rr][Ee][Ff].-/>', '')
	refs = refs1 + refs2
	-- Paragrafos; Paragraphs
	local paragraph = '\n([^*{\n|[]' .. mw.ustring.rep('[^\n]', 99) .. '+)\n'
	for p in mw.ustring.gmatch( textNoRef, paragraph ) do
		if #p > quality[2].parMaxBytes[1] then
			return {1, mw.ustring.format(quality[2].parMaxBytes[2], #p, mw.ustring.sub(mw.text.nowiki(p),1, 25))}  -- Q1: parágrafo muito grande; Too big paragraph
		else
			paragraphs = paragraphs + (mw.ustring.find(p, '%. ') and 1 or 0.5)
		end
	end

	local wikilinks = count(textNoRef, '%[%[[^:\n][^:\n]-%]%]')
	textNoRef = nil

	if wikilinks < quality[2].links[1] then
		return {1, quality[2].links[2]}           -- Q1: Poucas ligações internas; Few internal links
	end

	if paragraphs < quality[2].minParagraphs[1] then
		return {1, quality[2].minParagraphs[2]}   -- Q1: Poucos parágrafos; Few paragraphs
	end

	if noTemplate and noTemplate[1] == 1 then
		return noTemplate
	end

	-- Check if some requirement for Q3 is not satisfied
	if quality[3].needRefSection[1] and not hasRefSection then
		return {2, quality[3].needRefSection[2]}     -- Q2: Não tem seção de referências; There is no references section
	end

	if bytes < quality[3].minBytes[1] then
		return {2, quality[3].minBytes[2]}            -- Q2: Muito pequeno para Q3; Too small for Q3
	end

	if wikilinks < quality[3].links[1] then
		return {2, quality[3].links[2]}           -- Q2: Poucas ligações internas; Few internal links
	end

	local sections = count(text, '\n==[^=}{\n][^=}{\n]-==')
	sections = sections + count(text, '\n===[^=}{\n][^=}{\n]-===') / 5

	if sections < quality[3].sections[1] then
		return {2, quality[3].sections[2]}        -- Q2: Poucas seções; Few sections
	end

	if refs < quality[3].refs[1] then
		return {2, quality[3].refs[2]}            -- Q2: Poucas referências; Few references
	end

	for l in mw.ustring.gmatch(text, '%[%[ *(%a+) *:[^%]\n]-%]%]') do
		if hasitem(fileNsAliases, lang:lc(l)) then
			images = images + 1
		end
	end

	for i = 1, #otherImages do
		images = images + count(text, otherImages[i])
	end

	if images < quality[3].images[1] then
		return {2, quality[3].images[2]}          -- Q2: Sem imagens; No images
	end

	-- Só retorna Q2 depois de todos testes para Q1
	if noTemplate and noTemplate[1] == 2 then
		return noTemplate
	end

	-- Check if some requirement for Q4 is not satisfied
	if bytes < quality[4].minBytes[1] then
		return {3, quality[4].minBytes[2]}            -- Q3: Muito pequeno para Q4; Too small for Q4
	end

	if wikilinks < quality[4].links[1] then
		return {3, quality[4].links[2]}           -- Q3: Poucas ligações internas; Few internal links
	end

	if sections < quality[4].sections[1] then
		return {3, quality[4].sections[2]}        -- Q3: Poucas seções; Few sections
	end
	--FIXME: "refs" tem um valor impreciso, como exemplificado acima
	if refs < quality[4].refs[1] then
		return {3, quality[4].refs[2]}            -- Q3: Poucas referências; Few references
	end

	if images < quality[4].images[1] then
		return {3, quality[4].images[2]}          -- Q3: Poucas imagens; Few images
	end

	-- Só retorna Q3 depois de todos testes para Q1 e Q2
	if noTemplate and noTemplate[1] == 3 then
		return noTemplate
	end

	local a, b, s = mw.ustring.find(text, '\n==+ *([^={}\n]-) *==+')
	local a2, b2, s2 = 0, 0, ''

	while quality[3].allSecRef[1] and b do
		local r = mw.ustring.find(text, '<[Rr][Ee][Ff]', b)
		local p = mw.ustring.find(text, '\n[^*\n]' .. mw.ustring.rep('[^\n]', 99) .. '+', b)
		a2, b2, s2 = mw.ustring.find(text, '\n==+ *([^={}\n]-) *==+', b)

		if ( ( a2 and p and r and p < a2 and r > a2 ) or (p and not r) ) and not hasitem(exceptions, s) then
			return {3, mw.ustring.format(quality[3].allSecRef[2], s)}  -- Q3: Existem seções sem referências; There are sections with no citations
		end

		a, b, s = a2, b2, s2

	end

	-- Nada encontrado; Nothing found
	return {4, msg(cfg['nominate-to-GA'])}
end

local getClassForPage = function ( page )
	local pageTitle = mw.title.new( page )

	if pageTitle.isRedirect then
		-- Redefine the title to the target page after extracting it from wikicode
		local text = mw.ustring.match( pageTitle:getContent(), '^[^\n]-%[%[([^\n]-)%|', 10 )
		if not text then
			text = mw.ustring.match( pageTitle:getContent(), '^[^\n]-%[%[([^\n]-)%]%]', 10 )
		end
		pageTitle = mw.title.new( mw.uri.decode( text ) )
	end

	return getClassForText( pageTitle:getContent() or '' )
end

local _getBannerRow = function ( args )
	local importance = tonumber( args['importance'] )
	if importance and ( importance < 1 or 4 < importance ) then
		importance = nil
	end
	local quality = args['quality']
	local image = args['image'] or cfg['default-image']
	local size = args['size'] or '75x50px'
	local imgImportance
	if importance then
		imgImportance = msg(cfg['image-importance'], importance )
	else
		imgImportance = msg(cfg['image-importance-unknown'] )
	end
	local row = mw.html.create( 'tr' )
		:tag( 'td' )
			:addClass( 'tmbox-image' )
			:css( 'border-top', '1px solid #c0c090' )
			:css( 'border-bottom', '1px solid #c0c090' )
			:css( 'padding', '2px 0px 2px 0.9em' )
			:css( 'text-align', 'center' )
			:wikitext( '[[File:' .. image .. '|' .. size .. ']]' )
			:done()
		:tag( 'td' )
			:css( 'border-top', '1px solid #c0c090' )
			:css( 'border-bottom', '1px solid #c0c090' )
			:css( 'text-align', 'center' )
			:wikitext( '[[File:' .. imgImportance .. ']]' )
			:done()
	local textCell = row:tag( 'td' )
		:addClass( 'tmbox-text' )
		:css( 'border-top', '1px solid #c0c090' )
		:css( 'border-bottom', '1px solid #c0c090' )
		:css( 'padding', '1em 2px 1em 0.9em' )
		:css( 'width', '100%' )
	if args['description'] then
		textCell
			:tag( 'p' )
			:wikitext( args['description'] )
	end
	page = args['page'] or mw.title.getCurrentTitle().subjectPageTitle.prefixedText
	local nsNum = mw.title.new( page ).namespace
	local lang = mw.language.getContentLanguage()
	local link = args['link']
	if not( link and mw.title.new( link ) and mw.title.new( link ).exists ) then
		-- link does not contain a valid title to an existing page
		local title = lang:ucfirst( args['title'] )
		local proj = 'Wikipédia:Projetos/' .. title
		if mw.title.new( proj ) and mw.title.new( proj ).exists then
			link = proj
		else
			local portal = 'Portal:' .. title
			if mw.title.new( portal ) and mw.title.new( portal ).exists then
				link = portal
			else
				-- No valid title was found! Create a red link for a future project
				link = proj
			end
		end
	end
	local text = args['text'] or link
	local pageType = msg( cfg['pagetype-' .. nsNum] or cfg['pagetype-other'] )
	local about = args['category'] or args['title']
	local importanceText = importance or msg( cfg['importance-unknown'] )
	local projPage = msg( cfg['project-talk-page'], args['talk'] or lang:ucfirst( about or '' ) )
	textCell:wikitext( msg(cfg['importance-text'], link, text, pageType, importanceText, projPage ) )
	local cats = {}
	if mw.site.contentNamespaces[nsNum] and about then
		if quality then
			table.insert( cats, msg(cfg['category-quality-' .. quality] or cfg['category-quality'], quality, about) )
		else
			table.insert( cats, msg(cfg['category-quality-unknown'], about) )
		end
	end
	if importance then
		table.insert( cats, msg(cfg['category-importance'], importance, about) )
	else
		table.insert( cats, msg(cfg['category-importance-unknown'], about) )
	end
	if quality < 5 then
		if args['date'] == '' then
			-- FIXME: Precisamos de subcategorização por tema para a falta de datas?
			-- table.insert( cats, msg( cfg['category-quality-review-unknown-date-subject'] ) )
		else
			if lang:formatDate( 'Ymd', '-1 year' ) < args['date'] then
				-- FIXME: Precisamos de subcategorização por tema para avaliações revisadas?
				-- table.insert( cats, msg( cfg['category-quality-review-new-subject'], about ) )
			else
				table.insert( cats, msg(cfg['category-quality-review-old-subject'], about) )
			end
		end
	end
	return tostring( row ) .. ( #cats ~= 0 and ( '[[Category:' .. table.concat(cats, ']]\n[[Category:') .. ']]' ) or '' )
end

-- [[Predefinição:Marca de projeto]]
local _getBanners = function ( args )
	page = args[cfg['page']] or mw.title.getCurrentTitle().subjectPageTitle.prefixedText
	local qualityByUser = args[1] or args[cfg['quality']]
	local qualityByModule = getClassForPage( page )
	local reason = args[cfg['reason']] or msg(cfg['no-reason'])
	local lang = mw.language.getContentLanguage()

	-- Convert to numbers
	qualityByUser = tonumber( cfg['quality-aliases'][ qualityByUser ] or qualityByUser )
	if qualityByUser then
		if cfg['quality-min'] <= qualityByUser and qualityByUser <= cfg['quality-max'] then
			-- Users should use only the levels from 1 to 4
			qualityByUser = qualityByUser < 5 and { qualityByUser, reason } or nil
		else
			-- FIXME: Avisar o usuário? Categorizar?
			qualityByUser = nil
		end
	end

	local quality = qualityByUser or qualityByModule
	local proj = {}
	local importanceForProj = {}
	local pos = 2

	while args[pos] do
		table.insert( proj, args[pos] )
		table.insert( importanceForProj, args[pos+1] or '?' )
		pos = pos + 2
	end

	local dateOfLastestReview = args[cfg['date']]
	if not dateOfLastestReview or not tonumber(dateOfLastestReview) or mw.ustring.len( dateOfLastestReview ) ~= 8 then
		dateOfLastestReview = ''
	end
	local root = mw.html.create('')
	local bannerTable = root:tag( 'table' )
		:addClass( 'plainlinks tmbox tmbox-content' )
		:css( 'margin', '4px auto' )
		:css( 'border-collapse', 'collapse' )
		:css( 'border', '1px solid #c0c090' )
		:css( 'width', '80%' )

	if #proj > 2 then
		bannerTable:addClass( 'collapsible collapsed' )
	end

	local firstRow = bannerTable:tag( 'tr' )

	firstRow:tag( 'td' )
		:attr( 'colspan', 2 )
		:addClass( 'tmbox-text' )
		:css( 'border', 'none' )
		:css( 'padding', '0.25em 0.9em' )
		:css( 'text-align', 'right' )
		:css( 'background', 'transparent' )
		:wikitext( '[[File:' .. msg(cfg['image-quality'], quality[1]) .. ']]' )

	local qualityCell = firstRow:tag( #proj > 0 and 'th' or 'td' )

	qualityCell:addClass( 'tmbox-text' )
		:css( 'border', 'none' )
		:css( 'padding', '0.25em 0.9em' )
		:css( 'text-align', 'left' )
		:css( 'font-weight', 'normal' )

	local nsNum = mw.title.new( page ).namespace
	local pageType = msg( cfg['pagetype-' .. nsNum] or cfg['pagetype-other'] )
	local pageEvaluation
	local pageQuality = msg(cfg['quality-value-' .. quality[1]] or cfg['quality-value'], quality[1], quality[2], pageType )
	if quality[1] >= 5 then
		pageEvaluation = msg(cfg['page-elected'], pageType, pageQuality )
	else
		if qualityByUser then
			pageEvaluation = msg(cfg['page-evaluated'], pageType, pageQuality )
		else
			pageEvaluation = msg(cfg['page-evaluated-by-module'], pageType, pageQuality )
		end
	end
	if dateOfLastestReview ~= '' and qualityByUser then
		if #proj > 0 then
			local projects
			if #proj == 1 then
				projects = msg(cfg['projects-singular'])
			else
				projects = msg(cfg['projects-plural'], #proj)
			end
			qualityCell:wikitext( msg(
				cfg['quality-text-with-date-and-projects'],
				pageEvaluation,
				lang:formatDate( 'd "de" F "de" Y', dateOfLastestReview ),
				projects,
				mw.text.listToText( proj )
			) )
		else
			qualityCell:wikitext( msg(cfg['quality-text-with-date'], pageEvaluation ) )
		end
	else
		if #proj > 0 then
			local projects
			if #proj == 1 then
				projects = msg(cfg['projects-singular'])
			else
				projects = msg(cfg['projects-plural'], #proj)
			end
			qualityCell:wikitext( msg(
				cfg['quality-text-and-projects'],
				pageEvaluation,
				projects,
				mw.text.listToText( proj )
			) )
		else
			qualityCell:wikitext( msg(cfg['quality-text'], pageEvaluation ) )
		end		
	end
	local banners = mw.loadData( 'Módulo:Avaliação/Marcas' )
	for i = 1, #proj do
		--local projBanner = 'Marca de projeto/' .. lang:ucfirst( proj[i] )
		local title = lang:lcfirst( proj[i] )
		local banner = banners[ title ]
		if not banner then
			title = lang:ucfirst( proj[i] )
			banner = banners[ title ]
		end
		if type( banner ) == 'string' then
			-- Redirect
			title = banner
			banner = banners[ title ]
		end
		local params = {
			['page'] = page,
			['quality'] = quality[1],
			['date'] = dateOfLastestReview,
			['title'] = title,
			['importance'] = importanceForProj[i]
		}
		if banner then
			params['link'] = banner[cfg['link']]
			params['text'] = banner[cfg['text']]
			params['category'] = banner[cfg['category']]
			params['image'] = banner[cfg['image']]
			params['size'] = banner[cfg['size']]
			params['description'] = banner[cfg['description']]
			params['talk'] = banner[cfg['talk']]
		-- else
			-- FIXME: Informar o usuário que o projeto é desconhecido? Categorizar?
		end
		bannerTable:wikitext( _getBannerRow( params ) )
	end

	if #proj > 0 then
		bannerTable:tag( 'tr' )
			:tag( 'td' )
				:attr( 'colspan', 3 )
				:css( 'text-align', 'center' )
				:css( 'font-size', '90%' )
				:wikitext( msg( cfg['project-contact'] ) )
	end

	local cats = {}
	-- Categorizar somente se a página for um artigo (ou anexo)
	if mw.site.contentNamespaces[nsNum] then
		if qualityByUser then
			if dateOfLastestReview == '' then
				--FIXME: Um usuário estimou a qualidade mas não informou a data. Mostrar Erro?
				table.insert( cats, msg( cfg['category-quality-review-unknown-date'] ) )
			else
				if lang:formatDate( 'Ymd', '-1 year' ) < dateOfLastestReview then
					table.insert( cats, msg( cfg['category-quality-review-new'] ) )
				else
					table.insert( cats, msg(cfg['category-quality-review-old']) )
				end
				if qualityByUser[1] ~= qualityByModule[1] then
					table.insert( cats, msg( cfg['category-quality-review-conflict'], qualityByModule[1] ) )
				end
			end
		else
			table.insert( cats, msg( cfg['category-quality-by-module'] ) )
		end
	-- else
		-- FIXME: A predefinição foi usada em um domínio inadequado. Categorizar? Mostrar Erro?
	end

	return tostring( root ) .. ( #cats ~= 0 and ( '[[Category:' .. table.concat(cats, ']]\n[[Category:') .. ']]' ) or '' )
end

return {
	_getClassForText = getClassForText,
	_getClassForPage = getClassForPage,
	projeto = function( frame )
		local args = getArgs( frame )
		return _getBannerRow( args )
	end,
	marcas = function( frame )
		local args = getArgs( frame )
		return _getBanners( args )
	end,
	qualidade = function( frame )
		local args = getArgs( frame )
		local page = args[cfg['page']] or args[1]
		local template = args[cfg['format']] or args[2] or msg( cfg['quality-format'] )

		if page == nil then
			page = mw.title.getCurrentTitle().subjectPageTitle.prefixedText
		end

		local quality = getClassForPage( page )
		local text = mw.ustring.gsub(mw.ustring.gsub(template,'$1', tostring(quality[1])),'$2', quality[2])
		return text
	end
}