local p = {}

local dir_text = {
    ['a'] = 'anticlockwise',
    ['c'] = 'clockwise',
    ['e'] = 'eastbound',
    ['n'] = 'northbound',
    ['s'] = 'southbound',
    ['w'] = 'westbound',
}

local noquad = {
    ['123'] = '4',
    ['124'] = '3',
    ['134'] = '2',
    ['234'] = '1',
}

local valid_dirs = { 'ns', 'sn', 'ew', 'we', 'ca', 'ac' };
local valid_quads = {
	'1', '2', '3', '4',
	'12', '13', '14', '23', '24', '34',
	'123', '124', '134', '234'
};

local function contains(list, x)
	for _, v in pairs(list) do
		if v == x then return true end
	end
	return false
end

local function get_quad_info(dir, quad)
    if quad == '1' then
        return dir_text[dir:sub(2,2)], 'exit'
    elseif quad == '2' then
        return dir_text[dir:sub(1,1)], 'entrance'
    elseif quad == '3' then
        return dir_text[dir:sub(1,1)], 'exit'
    elseif quad == '4' then
        return dir_text[dir:sub(2,2)], 'entrance'
    else
        error('Invalid argument quad=' .. quad)
    end
end

local function get_alt_text(dir, quads, noonly)
	noonly = noonly or false
	
    if quads == nil then
        return 'complete interchange'
    elseif #quads == 1 then
        quad_dir, quad_type = get_quad_info(dir, quads:sub(1,1))
        local alt_text = quad_dir .. ' ' .. quad_type
        if not noonly then
        	alt_text = alt_text .. ' only'
        end
        return alt_text
    elseif #quads == 2 then
        quad_dir1, quad_type1 = get_quad_info(dir, quads:sub(1,1))
        quad_dir2, quad_type2 = get_quad_info(dir, quads:sub(2,2))
        local alt_text = ''
        if quad_type1 == quad_type2 then
            alt_text = quad_dir1 .. ' and ' .. quad_dir2 .. ' ' .. quad_type1 .. 's'
        elseif quad_dir1 == quad_dir2 then
            alt_text = quad_dir1 .. ' entrance and exit'
        else
            alt_text = quad_dir1 .. ' ' .. quad_type1 .. ' and ' .. quad_dir2 .. ' ' .. quad_type2
        end
        if not noonly then
        	alt_text = alt_text .. ' only'
        end
        return alt_text
    elseif #quads == 3 then
        noquad_dir, noquad_type = get_quad_info(dir, noquad[quads])
        return 'no ' .. noquad_dir .. ' ' .. noquad_type
    else
        error('Invalid length for argument quads=' .. quads)
    end
end

local function get_bullet_fn(quads)
	if quads == nil then
		return 'File:Intsym-LHT-Full.svg'
	end
	return 'File:Intsym-LHT-' .. quads .. '.svg'
end

function p._intsym(args)
	local dir = nil
	if args['dir'] ~= nil then
		dir = args['dir']
		if not contains(valid_dirs, dir) then
			error('Invalid input: dir=' .. dir)
		end
	end
	
	local quads = nil
	if args['quads'] ~= nil then
		quads = tostring(args['quads'])
		if not contains(valid_quads, quads) then
			error('Invalid input: quads=' .. quads)
		end
	end

	local text = args['text']
	local noonly = args['noonly']
	local bullet_link = '[[' .. get_bullet_fn(quads) .. '|24px|link=|' .. get_alt_text(dir, quads, noonly) .. ']]'
	
	if text == nil then
		return bullet_link
	else
		local root = mw.html.create()
		local tbl = root:tag('table')
			:css('border-collapse', 'collapse')
			:css('border-spacing', '0px')
		local row = tbl:tag('tr')
		local symbol_cell = row:tag('td')
			:css('border-collapse', 'collapse')
			:css('padding', '0px')
			:css('padding-right', '5px')
			:css('vertical-align', 'middle')
			:wikitext(bullet_link)
		local text_cell = row:tag('td')
			:css('border-collapse', 'collapse')
			:css('padding', '0px')
			:wikitext(text)
		return tostring(root)
	end
end

function p._intsym_legend(args)
	local dir = nil
	if args['dir'] ~= nil then
		dir = args['dir']
		if not contains(valid_dirs, dir) then
			error('Invalid input: dir=' .. dir)
		end
	end
	
	local alt_text1 = get_alt_text(dir, '1', true)
	local alt_text2 = get_alt_text(dir, '2', true)
	local alt_text3 = get_alt_text(dir, '3', true)
	local alt_text4 = get_alt_text(dir, '4', true)
	
	local quad1 = '[[' .. get_bullet_fn('1') .. '|24px|link=|' .. alt_text1 .. ']] ' .. alt_text1
	local quad2 = '[[' .. get_bullet_fn('2') .. '|24px|link=|' .. alt_text2 .. ']] ' .. alt_text2
	local quad3 = '[[' .. get_bullet_fn('3') .. '|24px|link=|' .. alt_text3 .. ']] ' .. alt_text3
	local quad4 = '[[' .. get_bullet_fn('4') .. '|24px|link=|' .. alt_text4 .. ']] ' .. alt_text4
	
	return quad1 .. '   ' .. quad2 .. '   ' .. quad3 .. '   ' .. quad4
end

function p.intsym(frame)
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame)
	return p._intsym(args)
end

function p.intsym_legend(frame)
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame)
	return p._intsym_legend(args)
end

return p