-- Module to build results cross-tables for standings in Chess
-- See documentation for details

require('strict')

local p = {}

-- Other functions
local function get_short_name(s, t, n, ss)
	-- return short name if defined
	if s and s ~= '' then
		return s
	end
	-- deflag if necessary
	if ss and n then
		if ss == 'noflag' or ss == 'nocountry' then
			n = mw.ustring.gsub(n, '%[%[[Ff][Ii][Ll][Ee]:[^%[%]]*%]%]', '')
			n = mw.ustring.gsub(n, '<span class="flagicon">[^<>]*</span>', '')
			if ss == 'nocountry' then
				n = mw.ustring.gsub(n, '<abbr[^<>]*>[^<>]*</abbr>', '')
				n = mw.ustring.gsub(n, '&nbsp;<span[^<>]*>[^<>]*</span>$', '')
			end
		elseif ss == 'flag' then
			n = mw.ustring.gsub(n, '(<span class="flagicon">%s*%[%[[Ff][Ii][Ll][Ee]:[^%[%]]*link=)[^%|%[%]]*(%]%][^<>]*</span>)%s*%[%[([^%[%]%|]*)%|[^%[%]]*%]%]', '%1%3%2')
			n = mw.ustring.gsub(n, '.*(<span class="flagicon">%s*%[%[[Ff][Ii][Ll][Ee]:[^%[%]]*%]%][^<>]*</span>).*', '%1')
			n = mw.ustring.gsub(n, '&nbsp;(</span>)', '%1')
		end
	end
	
	-- replace link text in name with team abbr if possible
	if n and t and n:match('(%[%[[^%[%]]*%]%])') then
		n = mw.ustring.gsub(n, '(%[%[[^%|%]]*%|)[^%|%]]*(%]%])', '%1' .. t .. '%2')
		n = mw.ustring.gsub(n, '(%[%[[^%|%]]*)(%]%])', '%1|' .. t .. '%2')
		return n
	end
	-- nothing worked, so just return the unlinked team abbr
	return t or ''
end

function p.header(tt,Args,p_sub,N_teams,team_list,legs,prefix)
	local ii, team_code_ii, short_name
	prefix = prefix or ''
	legs = tonumber(Args[prefix .. 'legs']) or 1

	-- Set match column width
	local col_width = Args['match_col_width'] or '28'

	-- Determine if default short style is position for short name
	local yesno = require('Module:Yesno')
	local pos_short = yesno(Args['use_pos_short'] or 'no')

	if N_teams>2 then
		-- Set the column span
		col_width = col_width .. ' colspan=' .. legs .. ' style="border-left:2px solid #aaa;"'
	
		-- Get some default values in case it doesn't start at 1
		local top_pos = tonumber(Args['highest_pos']) or 1
	
		for ii=top_pos,N_teams do
			team_code_ii = team_list[ii]
			short_name = get_short_name(Args['short_'..team_code_ii],
				pos_short and ii or team_code_ii, Args['name_'..team_code_ii], Args['short_style'] or '')
			tt = p_sub.colhead(tt,col_width,short_name)
			if legs > 1 then
				tt.count = tt.count + legs - 1
			end
		end
	else
		for ii=1,legs do
			local game_header = Args[prefix..'game'..ii..'_header'] or ii
			tt = p_sub.colhead(tt,col_width,game_header)
		end
	end
	local tb_numplayers = tonumber(Args['tb_numplayers']) or 0
	if prefix == '' and tb_numplayers >= 2 then
		-- Add empty column header
		tt.count = tt.count+1
		table.insert(tt.tab_text,'! scope="row" class="unsortable" style="line-width:3pt;"| \n')
		tt = p.header(tt,Args,p_sub,tb_numplayers,team_list,legs,'tb')
	end
	return tt
end

function p.row(tt,Args,N_teams,team_list,ii,ii_show,legs,prefix)
	-- Note ii is the row number being shown
	local jj, fw, bg, result, bg_col, team_code_jj
	prefix = prefix or ''
	legs = tonumber(Args[prefix .. 'legs']) or 1
	local team_code_ii = team_list[ii]

	-- Determine if backgrounds will be colored
	local yesno = require('Module:Yesno')
	local colorbg = yesno(Args['colorbg'] or 'yes')

	-- Get some default values in case it doesn't start at 1
	local top_pos = tonumber(Args['highest_pos']) or 1

	local bgcolrow_str = Args[prefix .. 'bgcolrow_' .. team_code_ii] or ''
	if bgcolrow_str ~= '' then
		for pp=1,(top_pos-1) do
			bgcolrow_str = mw.ustring.gsub(bgcolrow_str, '^([^,]*),?', '') or ''	-- Trim bgcol data prior to top_pos
		end
	end
	for jj=top_pos,N_teams do
		local bl = 'border-left:2px solid #aaa;'
		if ii == jj and N_teams>2 then
			-- Solid cell
			fw = 'font-weight:' .. (ii==ii_show and 'bold' or 'normal') .. ';'
			bg = ''

			-- Background color for solid cell
			local solid_cell = Args['solid_cell'] or ''
			if solid_cell ~= 'gray' and solid_cell ~= 'grey' and solid_cell ~= 'lightgray' and solid_cell ~= 'lightgrey' and solid_cell ~= 'silver' then
				solid_cell = mw.ustring.match(solid_cell,'^#%x%x%x+') or ''
			end
			if solid_cell ~= '' then
				table.insert(tt,'| colspan ="'..legs..'" style="'..fw..bl..'background:'..solid_cell..';" |\n')
			else
				table.insert(tt,'| colspan ="'..legs..'" style="'..fw..bl..bg..'" | &mdash;\n')
			end
		elseif ii ~= jj then
			-- Content cells
			team_code_jj = team_list[jj]
			if bgcolrow_str ~= '' then
				Args[prefix .. 'bgcol_' .. team_code_ii..'_'..team_code_jj] = mw.ustring.match(bgcolrow_str, '^([^,]*),?')
			end
			local bgcol_str = Args[prefix .. 'bgcol_'..team_code_ii..'_'..team_code_jj] or ''
			for l=1,legs do
				-- Get match data
				local m = (legs == 1) and 'match_' or 'match' .. l .. '_'
				m = prefix .. m
				result = Args[m..team_code_ii..'_'..team_code_jj] or '&nbsp;&nbsp;'

				-- Set bolding and background
				fw = 'font-weight:' .. ((ii==ii_show or jj == ii_show) and 'bold' or 'normal') .. ';'
				if l > 1 or N_teams<=2 then
					bl = ''
				end
				bg = ''

				-- Background coloring
				if colorbg then
					local bg_col = mw.ustring.match(bgcol_str, '^([^%+]*)%+?') or ''
					bgcol_str = mw.ustring.gsub(bgcol_str, '^([^%+]*)%+?', '') or ''	-- Remove bg_col from bgcol_str
					bg_col = mw.ustring.gsub(bg_col,'^%s*','')							-- Trim starting whitespace
					bg_col = mw.ustring.gsub(bg_col,'%s*$','')							-- Trim ending whitespace
					if bg_col == '' then
						bg_col = (l % 2 == 0 and 'B') or 'W'
					else
						bg_col = mw.ustring.upper(bg_col)
					end
					if bg_col == 'B' then
						bg = 'background-color:black; color:white';
					elseif bg_col == 'W' then
						bg = 'background-color:white; color:black';
					end
				end
				table.insert(tt,'| style="white-space:nowrap;'..fw..bl..bg..'" |'..result..'\n')
			end
		end
		bgcolrow_str = mw.ustring.gsub(bgcolrow_str, '^([^,]*),?', '') or ''
	end

	local tb_numplayers = tonumber(Args['tb_numplayers']) or 0
	if prefix == '' and tb_numplayers >= 2 then
		-- Add empty cell
		table.insert(tt,'| \n')
		if ii <= tb_numplayers then
			tt = p.row(tt,Args,tb_numplayers,team_list,ii,ii_show,legs,'tb')
		else
			local numtbgames = (tb_numplayers == 2) and legs or (tb_numplayers * legs)
			for gg=1,numtbgames do
				table.insert(tt,'| \n')
			end
		end
	end
	
	return tt
end

return p