Documentation for this module may be created at Module:RFC/doc

-- Implements {{Sum RFC}}, {{Ref RFC}}, and {{IETF RFC}}
require( 'strict' )
local getArgs = require('Module:Arguments').getArgs
local err = require('Module:Error')._error
local yesno = require('Module:Yesno')
local p = {}

local sectionMatch = function (n, t) return	'<section begin=rfc' .. n .. t .. '%s*/>(.-)<section end=rfc' .. n .. t .. '%s*/>' end
local isblank = function (v) return (v or '') == '' end

local function summary(args, dbContent, frame)
	--implements {{Ref RFC/summary}}, which is only used by {{Sum RFC}}
	if not frame then frame = mw.getCurrentFrame() end
	local refContent = ""
	local rfc = isblank(tonumber(args[1])) and 0 or tonumber(args[1])
	if not dbContent then
		dbContent = mw.title.new('Template:Ref RFC/db/' .. math.floor(rfc/100)).content
	end
	
	if yesno(args.ref or false, false) then
		refContent = p._ref({[1] = rfc, notes = yesno(args.refnotes or true, true) and 'yes' or 'no'}, dbContent, frame)
	end
	
	if yesno(args.plain or false, false) then
		return p._IETF({[1] = rfc, plainlink = 'yes'}) .. refContent
	end
	
	local output = {}
	table.insert(output, p._IETF({[1] = rfc, link = 'no'}))
	if yesno(args.title or true, true) then
		local titleContent = mw.ustring.match(dbContent, sectionMatch(rfc, 'title'))

		if rfc < 10000 then table.insert(output, '&numsp;') end
		if rfc < 1000 then table.insert(output, '&numsp;') end
		if rfc < 100 then table.insert(output, '&numsp;') end
		if rfc < 10 then table.insert(output, '&numsp;') end
		table.insert(output, string.format(
			'&ndash;&numsp;"%s"%s ',
			frame:extensionTag('cite', frame:preprocess(titleContent) .. ','),
			refContent
		))
		if args.status ~= 'no' then
			local statusContent = mw.ustring.match(dbContent, sectionMatch(rfc, 'status'))
			table.insert(output, "''" .. frame:preprocess(statusContent) .. ".''")
		end
		table.insert(output, ' ')
		if yesno(args.notes or false, false) then
			local notesContent = mw.ustring.match(dbContent, sectionMatch(rfc, 'notes'))
			table.insert(output, frame:preprocess(notesContent))
		end
	elseif yesno(args.ref or false, false) then
		table.insert(output, refContent)
	end
	return table.concat(output)
end

local function secpage(section, page, pp)
	--implements {{Ref RFC/secpage}}, which is only used by {{Ref RFC/getref}}
	local output = {}
	if not isblank(section) then
		table.insert(output, 'sec. ' .. section)
		if not isblank(page) or not isblank(pp) then
			table.insert(output, ',&nbsp;')
		end
	end
	
	if not isblank(page) then
		table.insert(output, 'p. ' .. page)
	elseif not isblank(pp) then
		table.insert(output, 'pp. ' .. pp)
	end
	
	if not isblank(page) or not isblank(pp) or not isblank(section) then
		table.insert(output, '.')
	end
	
	return table.concat(output)
end

local function getref(rfc, section, page, pp, notes, quote, status, dbContent, frame)
	-- implements {{Ref RFC/getref}}, which is only used by {{REf RFC}}
	if not frame then frame = mw.getCurrentFrame() end
	local output = {}
	local refContent = mw.ustring.match(dbContent, sectionMatch(rfc, 'ref'))
	table.insert(output, refContent .. ' ')
	if yesno(status or true, true) then
		local statusContent = mw.ustring.match(dbContent, sectionMatch(rfc, 'status'))
		table.insert(output, "''" .. statusContent .. ".''")
	end
	table.insert(output, ' ' .. secpage(section, page, pp) .. ' ')
	if yesno(notes or true, true) then
		local notesContent = mw.ustring.match(dbContent, sectionMatch(rfc, 'notes'))
		table.insert(output, notesContent)
	end
	table.insert(output, ' ')
	if not isblank(quote) then
		table.insert(output, frame:extensionTag('q', quote))
	end
	return table.concat(output)
end

function p._IETF(args, frame)
	-- Implements {{IETF RFC}}
	if not frame then frame = mw.getCurrentFrame() end
	if not isblank(args[1]) then
		local cll = require('Module:Catalog lookup link')._main
		local cllArgs = {
			['link-prefix'] = 'https://www.rfc-editor.org/rfc/rfc',
			['list-leadout'] = args.leadout or ''
		}
		for i = 1, 9 do
			cllArgs[i] = tonumber(args[i])
		end
		if yesno(args.plainlink or false, false) == false and yesno(args.link or true, true) == true then
			cllArgs['article-link'] = 'RFC (identifier)'
		end
		if yesno(args.plainlink or false, false) == false then
			cllArgs['article-name'] = 'RFC'
		end
		return cll(cllArgs, frame)
	else
		local errMsg = 'Parameter error in {{[[Template:IETF RFC|IETF RFC]]}}: Missing [[RFC (identifier)|RFC]].'
		return err({message = errMsg, style = 'font-size:inherit', tag='span'})
	end
end
function p.IETF(frame)
	return p._IETF(getArgs(frame), frame)
end
		
function p._ref(args, dbContent, frame)
	--implements {{Ref RFC}}
	if not frame then frame = mw.getCurrentFrame() end
	local rfc = tonumber(args[1])
	if rfc then
		local db = 'Template:Ref RFC/db/' .. math.floor(rfc/100)
		if (not dbContent) and rfc then
			dbContent = mw.title.new(db).content
		end
		if dbContent then
			local refContent = mw.ustring.match(dbContent, sectionMatch(rfc, 'ref'))
			if refContent then
				local output = {}
				if yesno(args['repeat'] or false, false) then
					output[1] =  frame:extensionTag('ref', '', {name='rfc' .. rfc})
				else
					output[1] = getref(rfc, args.section, args.p, args.pp, args.notes, args.quote, args.status, dbContent, frame)
					if yesno(args.ref or true, true) then
						local refname = ''
						if isblank(args.p) and isblank(args.pp) and isblank(args.section) and isblank(args.quote) then
							refname = 'rfc' .. rfc
						end
						output[1] = frame:extensionTag('ref', output[1], {name = refname})
					else
						output[1] = frame:preprocess(output[1])
					end
				end
				if not isblank(args.rp) then
					table.insert(output, frame:expandTemplate{title = 'rp', args = {page = args.rp}})
				end
				if not isblank(args.rpp) then
					table.insert(output, frame:expandTemplate{title = 'rp', args = {pages = args.rpp}})
				end
				if not isblank(args.rsection) then
					table.insert(output, frame:expandTemplate{title = 'rp', args = {at = '§' ..args.rsection}})
				end
				return table.concat(output)
			else
				local errMsg = 'REFERENCE FOR RFC' .. rfc .. ' IS NOT DEFINED YET.'
				return err({errMsg}) .. ' You are invited to add it [[' .. db .. '|here]].'
			end
		else
			local errMsg = 'REFERENCE FOR RFC' .. rfc .. ' IS NOT DEFINED YET.'
			return err({errMsg}) .. ' You are invited to add it [[Template:Ref RFC/db|here]].'
		end			
	else
		local errMsg = 'Parameter error in {{[[Template:Ref RFC|Ref RFC]]}}: Missing [[RFC (identifier)|RFC]].'
		return err({message = errMsg, style = 'font-size:inherit', tag='span'})
	end
end
function p.ref(frame)
	return p._ref(getArgs(frame), nil, frame)
end

function p._sum(args, frame)
	--implements {{Sum RFC}}
	if not frame then frame = mw.getCurrentFrame() end
	if not isblank(args[1]) then
		local rfc = tonumber(args[1])
		if rfc then
			local db = 'Template:Ref RFC/db/' .. math.floor(rfc/100)
			local dbContent = mw.title.new(db).content
			if dbContent then
				local titleContent = mw.ustring.match(dbContent, sectionMatch(rfc, 'title'))
				if titleContent then
					return summary(args, dbContent, frame)
				else
					local errMsg = 'Reference for RFC' .. rfc .. ' is not defined yet.'
					return err({errMsg}) .. ' You are invited to add it [[' .. db .. '|here]].'
				end
			else
				local errMsg = 'Reference for RFC' .. rfc .. ' is not defined yet.'
				return err({errMsg}) .. ' You are invited to add it [[Template:Ref RFC/db|here]].'
			end
		else
			local errMsg = 'Parameter error in {{[[Template:Sum RFC|Sum RFC]]}}: "' .. args[1] .. '" is not a number.'
			return err({message = errMsg, style = 'font-size:inherit', tag='span'})
		end
	else
		local errMsg = 'Parameter error in {{[[Template:Sum RFC|Sum RFC]]}}: Missing [[RFC (identifier)|RFC]].'
		return err({message = errMsg, style = 'font-size:inherit', tag='span'})
	end
end
function p.sum(frame)
	return p._sum(getArgs(frame), frame)
end

return p