模組:RailOpenDater

local p = {
	DEFAULT_DATE_ELAPSED_TEXT = '[[Category:需要去除时间判断模板的页面]]',
	DEFAULT_LINE_DATE_ABSENT_TEXT = '规划中',
}

local function convBool(val, default)
	if val == nil then
		return default
	elseif type(val) == 'boolean' then
		return val
	elseif mw.text.trim(val) == '' then
		return default
	end
	return (mw.text.trim(val) == '1')
end

local function _loadSystemData(system, raises)
	local system_data = nil
	local state
	if raises == nil then
		raises = true
	end
	if system ~= nil then
		state, system_data = pcall(mw.loadData, "Module:Adjacent stations/" .. system)
		if not state then
			if raises then
				error(string.format('铁道系统“%s”的数据模块不存在', system))
			else
				system_data = nil
			end
		end
	end
	return system_data
end

function p._internalLineDateMessage(line_code, type_, reprs, options, system)
	local system_data = _loadSystemData(system)
	local frame = mw.getCurrentFrame()
	local lowest_level = 0 -- 0: everything is ok, 1: year, 2: month, 3: day
	local cur_time = frame:callParserFunction{ name = '#time', args = { 'U' } }
	local types_data, type_data, alias
	local open_date, year, month, day, new_year, new_month
	local ret_str = ''
	
	for i, repr in ipairs(reprs) do
		repr = mw.text.trim(repr)
		if lowest_level < 1 and (repr == 'year') then
			lowest_level = 1
		elseif lowest_level < 2 and (repr == 'month' or repr == 'ym') then
			lowest_level = 2
		elseif  lowest_level < 3 and (repr == 'day' or repr == 'date' or repr == 'ymd') then
			lowest_level = 3
		end
	end
	
	if options == nil then options = {} end
	options.auto_hide = convBool(options.auto_hide, false)
	options.auto_defer = convBool(options.auto_defer, true)
	if options.cur_time ~= nil then -- for testing purpose
		cur_time = frame:callParserFunction{ name = '#time', args = { 'U', options.cur_time } }
	end
	
	if system_data.aliases then
		line_code = system_data.aliases[mw.ustring.lower(line_code)] or line_code
	end
	
	open_date = system_data.lines[line_code]["open date"]
	if type_ ~= nil then
		types_data = system_data.lines[line_code]["types"]
		if types_data ~= nil then
			type_data = types_data[type_]
			if type_data ~= nil then
				open_date = type_data["open date"]
			end
		end
	end

	year = tonumber(frame:callParserFunction{ name = '#time', args = { 'Y', open_date } })
	month = tonumber(frame:callParserFunction{ name = '#time', args = { 'm', open_date } })
	day = tonumber(frame:callParserFunction{ name = '#time', args = { 'd', open_date } })
	if options.auto_defer then
		if lowest_level == 1 then
			open_date = string.format('%04d-01-01', year + 1)
		elseif lowest_level == 2 then
			new_year, new_month = year, month
			if month == 12 then
				new_year = new_year + 1
				new_month = 1
			else
				new_month = new_month + 1
			end
			open_date = string.format('%04d-%02d-01', new_year, new_month)
		end
	end
	open_date = frame:callParserFunction{ name = '#time', args = { 'U', open_date } }
	
	if options.auto_hide and cur_time >= open_date then
		return p.DEFAULT_DATE_ELAPSED_TEXT
	end
	for i, repr in ipairs(reprs) do
		if repr == 'year' then
			ret_str = ret_str .. year .. '年'
		elseif repr == 'month' then
			ret_str = ret_str .. month .. '月'
		elseif repr == 'day' then
			ret_str = ret_str .. day .. '日'
		elseif repr == 'ym' then
			ret_str = ret_str .. string.format('%s年%s月', year, month)
		elseif repr == 'date' or repr == 'ymd' then
			ret_str = ret_str .. string.format('%s年%s月%s日', year, month, day)
		else
			ret_str = ret_str .. repr
		end
	end
	return ret_str
end

function p.lineDateMessage(frame)
	local a = frame.args
	local name, type_, system = a.name, a['type'], a.system
	local reprs, options = {}, {}
	local preserved = { name = true, ['type'] = true, system = true }
	for k, v in pairs(a) do
		if preserved[k] == nil then
			if type(k) == 'number' then
				reprs[k] = v
			else
				options[k] = v
			end
		end
	end 
	return p._internalLineDateMessage(name, type_, reprs, options, system)
end

function p.testCase()
	local frame = mw.getCurrentFrame()
	
	-- lineDateMessage test
	if p.lineDateMessage{args = {'在', 'year', '的', 'month', '的', 'day', ',月份', 'ym', ',日期', 'date', '开通', name='1', ['type']='二期', cur_time = '2016-1-1', auto_hide=true, system='宁波轨道交通'}} ~= '在2016年的3月的19日,月份2016年3月,日期2016年3月19日开通' then
		error('lineDateMessage test failed.' .. p.lineDateMessage{args = {'在', 'year', '的', 'month', '的', 'day', ',月份', 'ym', ',日期', 'date', '开通', name='1', ['type']='2', cur_time = '2016-1-1', auto_hide=true, system='宁波轨道交通'}} )
	end
	if p.lineDateMessage{args = {'year', name='1', ['type']='二期', cur_time = '2016-5-19', auto_hide=true, system='宁波轨道交通'}} ~= '2016年' then
		error('lineDateMessage test failed.')
	end
	if p.lineDateMessage{args = {'year', name='1', ['type']='二期', cur_time = '2017-3-19', auto_hide=true, system='宁波轨道交通'}} ~= p.DEFAULT_DATE_ELAPSED_TEXT then
		error('lineDateMessage test failed.')
	end
	if p.lineDateMessage{args = {'ym', name='1', ['type']='二期', cur_time = '2016-3-30', auto_hide=true, system='宁波轨道交通'}} ~= '2016年3月' then
		error('lineDateMessage test failed.')
	end
	if p.lineDateMessage{args = {'ym', name='1', ['type']='二期', cur_time = '2016-4-19', auto_hide=true, system='宁波轨道交通'}} ~= p.DEFAULT_DATE_ELAPSED_TEXT then
		error('lineDateMessage test failed.')
	end
	if p.lineDateMessage{args = {'ymd', name='1', ['type']='二期', cur_time = '2016-3-18', auto_hide=true, system='宁波轨道交通'}} ~= '2016年3月19日' then
		error('lineDateMessage test failed.')
	end
	if p.lineDateMessage{args = {'ymd', name='1', ['type']='二期', cur_time = '2016-3-19', auto_hide=true, system='宁波轨道交通'}} ~= p.DEFAULT_DATE_ELAPSED_TEXT then
		error('lineDateMessage test failed.')
	end
	if p.lineDateMessage{args = {'ymd', name='1', cur_time = '2012-3-4', auto_hide=true, system='宁波轨道交通'}} ~= '2014年5月30日' then
		error('lineDateMessage test failed.' .. p.lineDateMessage{args = {'ymd', name='1', cur_time = '2023-3-4', auto_hide=true, system='宁波轨道交通'}})
	end
end

return p