Module:Professional wrestling results table

local p = {}

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {wrappers = 'Template:Professional wrestling results table'})
	local warnings = {}

	-- Preprocessing
	local live = 'broadcast prior to the pay-per-view on '
	local taped = 'taped for a future broadcast of '
	local notes = {
		dark		= {  'D',			'a [[dark match]]'										},
		pre			= {  'P',			'broadcast on the pre-show'								},
		aewd		= { 'AD',	taped ..'<i>[[AEW Dark|Dark]]</i>'								},
		aewde		= { 'DE',	taped ..'<i>[[AEW Dark: Elevation|Dark: Elevation]]</i>'		},
		bti	        = {  'B',	taped ..'<i>[[Before the Impact]]</i>'				         	},
		ffa			= {  'F',	 live ..'<i>[[WWE Free for All|Free for All]]</i>'				},
		fusion		= { 'FT',	taped ..'<i>[[MLW Fusion|Fusion]]</i>'							},
		fusionlive	= {  'F',	 live ..'<i>[[MLW Fusion|Fusion]]</i>'							},
		heat		= {  'H',	 live ..'<i>[[WWE Heat|Sunday Night Heat]]</i>'					},
		mem 		= {'MEM',   taped ..'<i>Main Event Mondays</i>'                             },
		regnxt		= {  'N',	taped ..'<i>[[WWE NXT|NXT]]</i>'								},
		regnxtuk	= { 'UK',	taped ..'<i>[[WWE NXT UK|NXT UK]]</i>'							},
		slam		= {  'S',	 live ..'<i>[[WWF Sunday Night Slam|Sunday Night Slam]]</i>'	},
		wcwme		= { 'ME',	 live ..'<i>[[WCW Main Event|Main Event]]</i>'					},
		wcwsn		= { 'SN',	 live ..'<i>[[WCW Saturday Night|Saturday Night]]</i>'			},
		xplosion	= {  'X',	taped ..'<i>[[Impact! Xplosion|Xplosion]]</i>'					}
	}
	local matches, notes_key, notes_key_filter = {}, {}, {}
	local future_match, times_active, champions_active
	local row_num = 1

	while args['match'.. row_num] do
		-- Validate match status and order
		local row_match = args['match'.. row_num]
		if not (row_match:match(' defeated ') or row_match:match(' ended ') or row_match:match('[ -]won') or row_match:match(' lost')) then
			future_match = true
		elseif future_match then
			table.insert(warnings, '<b>match'.. row_num-1 ..'</b> (future match in wrong order OR not properly marked as complete—"defeated", "ended", "won" or "lost" expected)')
			future_match = false
		end

		-- Validate note
		-- Add note to Key (maintain order, avoid duplicates)
		-- Create sub-note if discrepancy in match status
		local row_note = args['note'.. row_num]
		if row_note then
			if notes[row_note] then
				local suffix = future_match and 'F' or ''
				local row_note_symbol = notes[row_note][1] .. (future_match and notes_key_filter[row_note] and 'F' or '')
				if not notes_key_filter[row_note .. suffix] then
					table.insert(notes_key, {
						row_note_symbol,
						(row_note == 'dark' and 'this' or 'the match') .. (future_match and ' will be ' or ' was ') .. notes[row_note][2]
					})
					notes_key_filter[row_note .. suffix] = true
				end
				row_note = row_note_symbol
			else
				table.insert(warnings, '<b>note'.. row_num ..'</b> (see [[Template:Professional wrestling results table#note list|note list]])')
				row_note = nil
			end
		end

		-- Validate stipulation
		if mw.text.killMarkers(args['stip'.. row_num] or '') == '' then
			table.insert(warnings, '<b>stip'.. row_num ..'</b> (stipulation should not be blank)')
		end

		-- Validate time (M:SS minimum)
		local row_time = args['time'.. row_num]
		if row_time then
			if row_time:match('[0-9]:[0-5][0-9]') then
				times_active = true
			else
				table.insert(warnings, '<b>time'.. row_num ..'</b> (M:SS expected)')
				row_time = nil
			end
		end

		-- Detect champions for Key
		if not champions_active and row_match:match('%(c%)') then
			champions_active = true
		end

		table.insert(matches, {row_note, row_match, args['stip'.. row_num], row_time})
		row_num = row_num+1
	end

	local notes_active = #notes_key > 0 and true or false

	-- Validate extra parameters
	if args['align'] and args['align'] ~= 'center' then
		table.insert(warnings, '<b>align</b> ("center" expected)')
	end

	-- Table start
	local root = mw.html.create('table')
		:addClass('wikitable')
		:css('margin', args['align'] == 'center' and '1em auto !important' or nil) -- Optional center align

	if args['caption'] then
		root
		:tag('caption')
			:wikitext(args['caption'])
	end

	-- Header
	local header = root:tag('tr')

	header
	:tag('th')
		:attr('scope', 'col')
		:tag('abbr')
			:attr('title', 'Number'.. (notes_active and ' and note' or ''))
			:wikitext('No.')
			:done()
		:done()
	:tag('th')
		:attr('scope', 'col')
		:wikitext((future_match and 'Matches*' or 'Results') .. (args['results'] or '')) -- Optional reference
		:done()
	:tag('th')
		:attr('scope', 'col')
		:wikitext('Stipulations')
	if times_active then
		header
		:tag('th')
			:attr('scope', 'col')
			:wikitext('Times'.. (args['times'] or '')) -- Optional reference
	end

	-- Matches
	for num, v in ipairs(matches) do
		local row = root:tag('tr')

		row
		-- Number
		:tag('th')
			:attr('scope', 'row')
			:wikitext(num)
		-- Note
			:tag('sup')
				:css('font-size', '85%')
				:wikitext(v[1])
				:done()
			:done()
		-- Match
		:tag('td')
			:wikitext(v[2])
			:done()
		-- Stipulation
		:tag('td')
			:wikitext(v[3])
		-- Time
		if v[4] then
			row
			:tag('td')
				:css('text-align', 'center')
				:wikitext(v[4])
		elseif times_active then
			-- mirror Template:N/a
			row
			:tag('td')
				:addClass('table-na')
				:css('text-align', 'center')
				:css('background-color', '#ececec')
				:css('color', '#2C2C2C')
				:wikitext('—')
		end
	end

	-- Key
	if champions_active or notes_active or future_match then
		local key = root:tag('tr')
			:tag('th')
				:attr('scope', 'row')
				:attr('colspan', times_active and '4' or '3')
				:css('border-top', 'solid 2px #aaa')
				:css('font-weight', 'normal')
				:css('text-align', 'left')
				:tag('table')
					:css('margin', '0 auto !important')
					:css('padding', '0')
					:css('border-spacing', '0')
					:css('line-height', '1.45em')

		if champions_active then
			key
			:tag('tr')
				:tag('td')
					:css('text-align', 'right')
					:wikitext('(c)')
					:done()
				:tag('td')
					:wikitext('&nbsp;– the champion(s) heading into the match')
		end
		for _, v in ipairs(notes_key) do
			key
			:tag('tr')
				:tag('td')
					:css('text-align', 'right')
					:css('font-size', '85%')
					:css('font-weight', 'bold')
					:wikitext(v[1])
					:done()
				:tag('td')
					:wikitext('&nbsp;– '.. v[2])
		end
		if future_match then
			key
			:tag('tr')
				:tag('td')
					:attr('colspan', '2')
					:css('text-align', 'center')
					:css('font-size', '85%')
					:css('font-weight', 'bold')
					:wikitext('*Card subject to change')
		end
	end

	-- Preview warnings and tracking
	if #warnings > 0 then
		root = require('Module:If preview')._warning({'Invalid parameter value at '.. table.concat(warnings, '; ') ..'.'})
		.. (mw.title.getCurrentTitle().namespace == 0 and '[[Category:Pages using professional wrestling results table with invalid parameter values]]' or '')
		.. tostring(root)
	end

	return root
end

return p