The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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

local p = {}

local SANDBOX = false
local SANDBOX_SUFFIX = SANDBOX and '/sandbox' or ''

local concat = table.concat
local insert = table.insert
local getArgs = require('Module:Arguments').getArgs -- Import module function to work with passed arguments
local parserModule = require("Module:Road data/parser" .. SANDBOX_SUFFIX)
local parser = parserModule.parser

-- Shields
local rdt

local function size(args)
	local state = args.state or args.province or args.prefecture or ''
	args.state = state
	local country
	if args.country and args.country ~= '' then
		country = string.upper(args.country)
	else
		local countryModule = mw.loadData("Module:Road data/countrymask")
		country = countryModule[state] or 'UNK'
	end
	args.country = country

	local type = args.type
	if rdt then
		return 'x17'
	elseif country == 'CAN' then 
		if state == 'MB' and type == 'Winnipeg' then
			return 'x20'
		elseif state == 'NS' then
			if type == 'Route' then
				return '25'
			elseif type == 'Trunk' then
				return 'x20'
			end
		end
		return '20'
	elseif country == 'FRA' or country == 'TUR' then
		return 'x20'
	elseif country == 'MEX' then
		return '20'
	elseif country == 'USA' and state == 'GU' or state == 'FL' and type == 'Toll' or state == 'DC' and type == 'DC' then
		return '20'
		end
	return 'x20'
end
 
local function shield(args, frame)
	if args.noshield then return '' end
	local firstSize, secondSize = size(args)
	local shield, second = parser(args, 'shield')
	if not shield or shield == '' then
		return ''
	elseif type(shield) == 'table' then
		shield, second = shield[1], shield[2]
	end
	local function render(shield, size)
		if frame:callParserFunction('#ifexist', 'Media:' .. shield, '1') ~= '' then
			return string.format("[[File:%s|%spx|link=|alt=]]", shield, size)
		else
			args.shielderr = true
			local page = mw.title.getCurrentTitle().prefixedText -- Get transcluding page's title
			return mw.ustring.format("[[Category:Jct template errors|1 %s]]", page)
		end
	end
	local rendered = render(shield, firstSize)
	if second and type(second) == 'string' then
		local size = secondSize or firstSize
		rendered = rendered .. render(second, size)
	end
	return rendered
end

-- Links/abbreviations
local function link(args)
	local nolink = args.nolink
	local abbr = parser(args, 'abbr')
	if nolink then
		return abbr
	else
		local link = parser(args, 'link')
		if not link or link == '' then
			return abbr
		else
			return mw.ustring.format("<span class=\"nowrap\">[[%s|%s]]</span>", link, abbr)
		end
	end
end

local function completeLink(args, num)
	local actualLink = link(args)
	if not actualLink then
		local page = mw.title.getCurrentTitle().prefixedText -- Get transcluding page's title
		actualLink = string.format("<span class=\"error\">Invalid type: %s</span>[[Category:Jct template errors|2 %s]]", args.type, page)
	end
	local isTo = args.to
	local prefix
	if num == 1 then
		if isTo then
			prefix = "To "
		else
			prefix = ''
		end
	else
		if isTo then
			prefix = " to "
		else
			prefix = " / "
		end
	end
	local suffix = {}
	local dir = args.dir
	if dir then
		insert(suffix, ' ' .. string.lower(dir))
	end
	local name = args.name
	if name then
		insert(suffix, mw.ustring.format(' (%s)', name))
	end
	return prefix .. actualLink .. concat(suffix)
end

local function namedLink(args, num)
	local actualLink = link(args)
	local name = args.name or ''
	local isTo = args.to
	local prefix
	if num == 1 then
		if isTo then
			prefix = "To "
		else
			prefix = ''
		end
	else
		if isTo then
			prefix = " to "
		else
			prefix = " / "
		end
	end
	local suffix = {}
	local dir = args.dir
	if name ~= '' then
		if dir then
			insert(suffix, mw.ustring.format(' (%s %s)', actualLink, dir))
		else
			insert(suffix, mw.ustring.format(' (%s)', actualLink))
		end
	else
		insert(suffix, actualLink)
		if dir then insert(suffix, ' ' .. string.lower(dir)) end
	end
	return prefix .. name .. concat(suffix)
end

local function banners(routes)
	local format = string.format
	local firstRun = {}
	local hasBanner = false
	for k,v in ipairs(routes) do
		local banner
		if v.shield == '' or v.shielderr then
			banner = false
		else
			banner = parser(v, 'banner') or ''
			if banner and banner ~= '' then
				hasBanner = true
			end
		end
		insert(firstRun, banner)
	end
	if not hasBanner then return '' end
	local secondRun = {}
	for k,v in ipairs(routes) do
		local bannerFile = firstRun[k]
		if not bannerFile then
			
		elseif bannerFile == '' then
			local widthCode = parser(v, 'width') or 'square'
			if type(widthCode) == 'number' then
				insert(secondRun, "[[File:No image wide.svg|" .. tostring(widthCode) .. "px|bottom|link=|alt=]]")
			elseif widthCode == 'square' then
				insert(secondRun, "[[File:No image wide.svg|20px|bottom|link=|alt=]]")
			elseif widthCode == 'expand' then
				local route = v.route
				local width = (#route >= 3) and '25' or '20'
				insert(secondRun, format("[[File:No image wide.svg|%spx|bottom|link=|alt=]]", width))
			elseif widthCode == 'US1926' then
				insert(secondRun, "[[File:No image wide.svg|20px|bottom|link=|alt=]]")
			elseif widthCode == 'wide' then
				insert(secondRun, "[[File:No image wide.svg|25px|bottom|link=|alt=]]")
			end
		else
			local widthCode = parser(v, 'width') or 'square'
			if widthCode == 'square' then
				insert(secondRun, format("[[File:%s|20px|bottom|link=|alt=]]", bannerFile))
			elseif widthCode == 'expand' then
				if (v.state == 'CA') then
					local route = v.route
					if #route >= 3 then
						insert(secondRun, format("[[File:No image.svg|1px|bottom|link=|alt=]][[File:%s|20px|bottom|link=|alt=]][[File:No image.svg|2px|bottom|link=|alt=]]", bannerFile))
					else
						insert(secondRun, format("[[File:%s|20px|bottom|link=|alt=]]", bannerFile))
					end
				else local route = v.route
				if #route >= 3 then
					insert(secondRun, format("[[File:No image.svg|2px|bottom|link=|alt=]][[File:%s|20px|bottom|link=|alt=]][[File:No image.svg|3px|bottom|link=|alt=]]", bannerFile))
				else
					insert(secondRun, format("[[File:%s|20px|bottom|link=|alt=]]", bannerFile))
				end
			end
			elseif widthCode == 'wide' then
				insert(secondRun, format("[[File:No image.svg|2px|bottom|link=|alt=]][[File:%s|20px|bottom|link=|alt=]][[File:No image.svg|3px|bottom|link=|alt=]]", bannerFile))
			elseif widthCode == 'MOSupp' then
				local route = v.route
				if #route >= 2 then
					insert(secondRun, format("[[File:No image.svg|2px|bottom|link=|alt=]][[File:%s|20px|bottom|link=|alt=]][[File:No image.svg|3px|bottom|link=|alt=]]", bannerFile))
				else
					insert(secondRun, format("[[File:%s|20px|bottom|link=|alt=]]", bannerFile))
				end
			elseif widthCode == 'US1926' then
				insert(secondRun, format("[[File:%s|20px|bottom|link=|alt=]][[File:No image.svg|1px|bottom|link=|alt=]]", bannerFile))
			end
		end
	end
	return concat(secondRun) .. '<br>'
end

local function extra(args)
	local extraTypes = mw.loadData('Module:Road data/extra')
	local extraIcon = extraTypes[string.lower(args.extra or '')]
	if not extraIcon then return '' end
	local size = require("Module:Road data/size").size({style = ''})
	local countryIcon = extraIcon[args.country] or extraIcon.default
	if type(countryIcon) == 'table' then
		local localIcon = countryIcon[args.state] or countryIcon.default
		return string.format("[[File:%s|%s|alt=|link=]]", localIcon, size)
	else
		return string.format("[[File:%s|%s|alt=|link=]]", countryIcon, size)
	end
end

local function parseArgs(args)
	local state = args.state or args.province or args.prefecture
	local country
	if args.country then
		country = string.upper(args.country)
		args.country = country
	else
		local countryModule = mw.loadData("Module:Road data/countrymask")
		country = countryModule[state] or 'UNK'
		args.country = country
	end
	local params = {'denom', 'county', 'township', 'dab', 'nolink', 'noshield', 'to', 'dir', 'name'}
	local routeArgs = {}
	local routeCount = 1
	while true do
		local routeType = args[routeCount * 2 - 1]
		if not routeType then break end
		local route = {type = routeType, route = args[routeCount * 2]}
		for _,v in pairs(params) do
			route[v] = args[v .. routeCount]
		end
		if args.nolink then
			route.nolink = args.nolink
		end
		route.country = country
		route.state = state
		insert(routeArgs, route)
		routeCount = routeCount + 1
	end
	return routeArgs
end

function p._jct(args, frame)
	rdt = args.rdt
	local routes = parseArgs(args)
	local extra = extra(args)
	local shields = {}
	local links = {}
	frame = frame or mw.getCurrentFrame()
	for num,route in ipairs(routes) do
		local routeShield = shield(route, frame)
		insert(shields, routeShield)
		route.shield = routeShield
		if args.jctname then
			insert(links, namedLink(route, num))
		else
			insert(links, completeLink(route, num))
		end
	end
	local bannerText = banners(routes)
	local shieldText = concat(shields)
	local linkText = concat(links)
	local graphics = (not(args.noshield) and (bannerText .. shieldText) or '') .. extra .. ' '
	
	local cities = ''
	if args.city1 or args.location1 then
		local cityModule = require("Module:Jct/city" .. SANDBOX_SUFFIX)
		cities = cityModule.city(args)
	end
	
	local roadStr = ''
	local road = args.road
	if road then
		if args.toroad then
			roadStr = ' to ' .. road
		else
			roadStr = ' / ' .. road
		end
	end
	
	local output = graphics .. linkText .. roadStr .. cities
	return mw.text.trim(output)
end

function p.jct(frame)
	local args = getArgs(frame)
	return p._jct(args, frame)
end

return p