模組:Adjacent stations/experimental

require('strict')

local p = {}

local lang = 'zh-CN' -- local default language

local i18n = require('Module:Adjacent stations/i18n')
local function getData(system, verify)
	if verify then
		local title = mw.title.new('Module:Adjacent stations/' .. system-- .. '/sandbox'
		)
		if not (title and title.exists) then return nil end
	end
	return require('Module:Adjacent stations/' .. system-- .. '/sandbox'
	)
end

local function getLine(data, lineN)
	if lineN then
		if data['aliases'] then
			lineN = data['aliases'][mw.ustring.lower(lineN)] or lineN
		end
		local default = data['lines']['_default'] or {}
		local line = data['lines'][lineN] or {}
		for k, v in pairs(default) do
			if v then line[k] = line[k] or v end
		end
		line['title'] = line['title'] and mw.ustring.gsub(line['title'], '%%1', lineN)
		return line, lineN
	end
end

local lineN, typeN

local function somethingMissing(name, key, formats)
	local formatKeys = {}
	for k in pairs(formats) do
		table.insert(formatKeys, k)
	end
	return name .. ' 曾是 "' .. key .. '" 但既没有找到它的条目,也没有找到默认值。选择是: ' ..
		table.concat(formatKeys, ', ')
end

local function getStation(station, _Format)
	if type(_Format) == 'table' then
		local lineNformats = _Format
		_Format = lineNformats[lineN] or lineNformats[1]
		if not _Format then
			error(somethingMissing('lineN', lineN, lineNformats))
		elseif type(_Format) == 'table' then
			local typeNformats = _Format
			_Format = typeNformats[typeN] or typeNformats[1]
			if not _Format then
				error(somethingMissing('typeN', typeN, typeNformats))
			end
		end
	end
	if typeN then _Format = mw.ustring.gsub(_Format, '%%3', typeN) end
	if lineN then _Format = mw.ustring.gsub(_Format, '%%2', lineN) end
	return (mw.ustring.match(_Format, '%[%[.+%]%]')) and (mw.ustring.gsub(_Format, '%%1', station)) or
		table.concat { '[[', mw.ustring.gsub(_Format, '%%1', station), '|', station, ']]' }
end

local getArgs = require('Module:Arguments').getArgs

local function makeInvokeFunction(funcName)
	-- makes a function that can be returned from #invoke, using
	-- [[Module:Arguments]]
	return function (frame)
		local args = getArgs(frame, {parentOnly = true})
		return p[funcName](args, frame)
	end
end

function p._terminusTable(args, frame)
	local system = args[1] or args.system
	lineN = args[2] or args.line
	local side = mw.ustring.sub(mw.ustring.lower(args[3] or args.side or ''), 1, 1)
	typeN = args.type
	local prefix = (side == 'r') and 'right' or 'left'

	local data = args.data
	if system or data then
		data = data or getData(system, true) or error(i18n[lang]['error_line'])
		local line = getLine(data, lineN) or error(i18n[lang]['error_unknown'](lineN))
		if typeN and data and data['aliases'] then typeN = data['aliases'][mw.ustring.lower(typeN)] or typeN end
		local Type = line['types'] and line['types'][typeN]

		local circular
		if Type then
			if Type['circular'] then
				-- Type may override the circular status of the line
				circular = Type['circular']
			end
		else
			circular = line['circular']
		end

		return Type and Type[prefix .. ' terminus'] or line[prefix .. ' terminus'], data['station format'] or i18n[lang]['error_format'], circular
	end
end

function p._terminus(args, frame)
	local var, Format, circular = p._terminusTable(args, frame)

	local function subst(var1, var2)
		-- var1 is the terminus or table of termini; var2 is the key for the table of termini
		return type(var1) == 'string' and (circular and var1 or getStation(var1, (Format[var1] or Format[1])))
			or type(var1) == 'table' and #var1 > 0 and (circular and var1[var2] or getStation(var1[var2], (Format[var1[var2]] or Format[1])))
			or ''
	end

	if Format then
		if type(var) == 'string' then
			return subst(var)
		elseif type(var) == 'table' and #var > 0 then
			local t = {subst(var, 1)}

			for i = 2, #var - 1 do
				t[i] = i18n[lang]['comma'](subst(var, i))
			end

			if #var > 1 then t[#var] = i18n[lang]['or'](subst(var, #var)) end
			if var['via'] then
				if i18n[lang]['via-first'] then
					table.insert(t, 1, i18n[lang]['via'](subst(var, 'via')))
				else
					table.insert(t, i18n[lang]['via'](subst(var, 'via')))
				end
			end

			return table.concat(t)
		else
			return ''
		end
	else
		return var or ''
	end
end

p.terminus = makeInvokeFunction('_terminus')

return p