-- Module to build Sports games table 
-- See documentation for details

require('strict')

local p = {}

-- Helper functions
local function get_team_label(team_abbr, team_name)
	if team_name == nil then
		team_name = team_abbr
	end
	local team_text = team_name
	if team_text:match('^%[%[[^%|%[%]]*%|([^%|%[%]]*)%]%]') then
		team_text = team_text:match('^%[%[[^%|%[%]]*%|([^%|%[%]]*)%]%]')
	end
	if team_text:match('^%[%[([^%|%[%]]*)%]%]') then
		team_text = team_text:match('^%[%[([^%|%[%]]*)%]%]')
	end
	local team_label = team_name
	if team_text ~= team_abbr then
		team_label = team_label .. '<br>(' .. team_abbr .. ')'
	end
	return team_label
end

local function get_score_background(s, c)
	local s1, s2
	-- Define the colouring
	local wc, lc, tc
	if c == 'level2' then
	wc, lc, tc = '#CCF9FF', '#FCC', '#FFC' -- blue2, red2, yellow2
	elseif c == 'level3' then
	wc, lc, tc = '#DDFCFF', '#FDD', '#FFD' -- blue3, red3, yellow3
	elseif c == 'level4' then
	wc, lc, tc = '#EEFFFF', '#FEE', '#FFE' -- blue4, red4, yellow4
	else
	wc, lc, tc = '#BBF3FF', '#FBB', '#FFB' -- blue1, red1, yellow1
	end

	-- check for override
	if s:match('^%s*<span%s+style%s*=["\'%s]*background[%-colr]*%s*:([^\'";<>]*).-$') then
		local c = mw.ustring.gsub(s,'^%s*<span%s+style%s*=["\'%s]*background[%-colr]*%s*:([^\'";<>]*).-$', '%1')
		return c
	end

	-- delink if necessary
	if s:match('^%s*%[%[[^%[%]]*%|([^%[%]]*)%]%]') then
		s = s:match('^%s*%[%[[^%[%]]*%|([^%[%]]*)%]%]')
	end
	if s:match('^%s*%[[^%[%]%s]*%s([^%[%]]*)%]') then
		s = s:match('^%s*%[[^%[%]%s]*%s([^%[%]]*)%]')
	end
	if s:match('<span[^<>]*>(.-)</span>') then
		s = s:match('<span[^<>]*>(.-)</span>')
	end

	-- get the scores
	s1 = tonumber(mw.ustring.gsub( s or '',
		'^%s*([%d%.]+)%s*–%s*([%d%.]+).*', '%1' ) or '') or ''
	s2 = tonumber(mw.ustring.gsub( s or '',
		'^%s*([%d%.]+)%s*–%s*([%d%.]+).*', '%2' ) or '') or ''

	-- return colouring if possible
	if s1 ~= '' and s2 ~= '' then
		return (s1 > s2) and wc or ((s2 > s1) and lc or tc)
	else
		return 'transparent'
	end
end

local function format_score(s)
	s = mw.ustring.gsub(s or '', '^%s*([%d%.]+)%s*[–−—%-]%s*([%d%.]+)', '%1–%2')
	s = mw.ustring.gsub(s, '^%s*([%d%.]+)%s*&[MmNn][Dd][Aa][Ss][Hh];%s*([%d%.]+)', '%1–%2')
	s = mw.ustring.gsub(s, '^%s*(%[%[[^%[%]]*%|[%d%.]+)%s*%-%s*([%d%.]+)', '%1–%2')
	s = mw.ustring.gsub(s, '^%s*(%[[^%[%]%s]*%s+[%d%.]+)%s*%-%s*([%d%.]+)', '%1–%2')
	s = mw.ustring.gsub(s, '^%s*(%[%[[^%[%]]*%|[%d%.]+)%s*&[MmNn][Dd][Aa][Ss][Hh];%s*([%d%.]+)', '%1–%2')
	s = mw.ustring.gsub(s, '^%s*(%[[^%[%]%s]*%s+[%d%.]+)%s*&[MmNn][Dd][Aa][Ss][Hh];%s*([%d%.]+)', '%1–%2')
	return s
end

local function flip_score(s)
	s = format_score(s)
	s = mw.ustring.gsub(s, '([%d%.]+)–([%d%.]+)', '%2–%1')
	return s
end

local function is_overtime(s)
	if s:match('%d+–%d+[%s%]]*%*') then
		return true
	end
	return false
end	

-- Main function
function p.table(frame)
	-- Get the args, stripping out blank values
	local getArgs = require('Module:Arguments').getArgs
	local Args = getArgs(frame, {parentFirst = true})

	-- Exit early if we are using section transclusion for a different section
	local tsection = frame:getParent().args['transcludesection'] or frame:getParent().args['section'] or ''
	local bsection = frame.args['section'] or ''
	if( tsection ~= '' and bsection ~= '' ) then
		if( tsection ~= bsection ) then
			return ''
		end
	end
	
	if Args['team_order'] and Args['team_order'] ~= '' then
		local tlist = mw.text.split(Args['team_order'], '%s*[;,]%s*')
		for k, tname in ipairs(tlist) do
			if tname ~= '' then
				Args['team' .. k] = tname
			end
		end
	end
	
	-- Build team list
	local team_list = {}
	local other_team_table = {}
	local k = 1
	while Args['team' .. k] do
		team_list[k] = Args['team' .. k]
		other_team_table[Args['team' .. k]] = {}
		k = k + 1
	end
	
	-- Store the results
	local total_games = 0
	for k,v in pairs(Args) do
		if v and v ~= '' and k:match('^m%d+_[^_]+_[^_]+$') then
			local g = k:match('^m(%d+)_[^_]+_[^_]+$')
			local t1 = k:match('^m%d+_([^_]+)_[^_]+$')
			local t2 = k:match('^m%d+_[^_]+_([^_]+)$')
			if other_team_table[t1] then
				other_team_table[t1][tonumber(g)] = t2
			end
			total_games = (tonumber(g) > total_games) and tonumber(g) or total_games
		end
	end

	-- Start the div
	local root = mw.html.create('div')
		:css('overflow-x', 'auto')
		:css('white-space', 'nowrap')
		
	-- Start table
	local t = root:tag('table')
		:addClass('wikitable')
		:addClass('plainrowheaders')
		:css('text-align', 'center')
		:css('font-size', Args['font_size'])
	
	-- Table title
	if Args['title'] and Args['title'] ~= '' then
		t:tag('caption'):wikitext(Args['title'])
	end
	
	-- Header rows
	local match_col_width = Args['match_col_width'] and (Args['match_col_width'] .. 'px') or nil
	local row = t:tag('tr')
	row:tag('th')
		:attr('scope', 'col')
		:attr('rowspan', 2)
		:wikitext('Team')
	row:tag('th')
		:attr('scope', 'col')
		:attr('colspan', total_games)
		:wikitext('Game')
	row = t:tag('tr')
	for jj = 1,total_games do
		row:tag('th')
			:attr('scope', 'col')
			:css('width', match_col_width)
			:wikitext(jj)
	end
	
	-- Results rows
	local ot_note = false
	for ii=1,#team_list do
		local team_abbr = team_list[ii]
		local team_label = get_team_label(team_abbr, Args['name_' .. team_abbr])
		row = t:tag('tr')
		row:tag('th')
			:attr('scope', 'row')
			:css('background', 'inherit')
			:css('color', 'inherit')
			:wikitext(team_label)
		for jj=1,total_games do
			local other_team_abbr = other_team_table[team_abbr][jj] or ''
			local result = ''
			if other_team_abbr ~= '' then
				result = Args['m' .. jj .. '_' .. team_abbr .. '_' .. other_team_abbr] or ''
				if result == other_team_abbr or result == 'auto' then
					for kk=1,total_games do
						local other_result = Args['m' .. kk .. '_' .. other_team_abbr .. '_' .. team_abbr]
						if other_result then
							result = flip_score(other_result)
						end
					end
				end
			end
			local ot_flag = is_overtime(result)
			if (ot_flag) then
				ot_note = true
			end
			local bg = get_score_background(result, ot_flag and 'level3' or 'level1')
			if bg == 'transparent' then bg = bg .. ';color:inherit' end
			if result ~= '' then
				result = other_team_abbr .. '<br>' .. format_score(result)
			end
			row:tag('td')
				:css('background', bg)
				:wikitext(result)
		end
	end
	
	-- footer
	local t_footer = {}
	local update = Args['update'] or 'unknown'
	local start_date = Args['start_date'] or 'unknown'
	local source = Args['source']
		or frame:expandTemplate{ title = 'citation needed',
			args = { reason='No source parameter defined', date=os.date('%B %Y') } }
	
	-- Date updating
	if string.lower(update)=='complete' then
		-- Do nothing
	elseif update=='' then
		-- Empty parameter
		table.insert(t_footer,'Updated to match(es) played on unknown. ')
	elseif string.lower(update)=='future' then
		-- Future start date
		table.insert(t_footer,'First match(es) will be played: '..start_date..'. ')
	else
		table.insert(t_footer,'Updated to match(es) played on '..update..'. ')
	end
	table.insert(t_footer,'Source: '..source)
	table.insert(t_footer, '<br />Legend: Blue = win; Red = loss')

	if ot_note then
		table.insert(t_footer, '; Matches with lighter background shading were decided after overtime.')
		table.insert(t_footer, ' (*) Number of asterisks denotes number of overtime periods')
	end
	
	t_footer = mw.html.create('div')
		:css('font-size', '90%')
		:css('margin-bottom', '0.5em')
		:wikitext(table.concat(t_footer))
	
	return tostring(root) .. tostring(t_footer)
end

return p