模組:Vital articles

local p = {}
local lib_PJBS = require("Module:PJBSClass/main")
local vital_subpages = mw.loadData("Module:Vital_articles/subpages")

local VA_Data = {
	{
		base_page = "Wikipedia:中文領域基礎條目",
		display = "条目「'''%s'''」已被列為%s類'''[[Wikipedia:中文領域基礎條目|中文領域基礎條目]]'''之一。請參見[[Wikipedia:中文領域基礎條目|中文領域基礎條目]]以了解詳情。",
		category = "Category:中文基礎條目"
	},
	{
		base_page = "Wikipedia:基礎條目",
		display = "'''%s'''属于维基百科%s主題的'''[[Wikipedia:基礎條目|基礎條目]]'''。",
		default = true,
		category = "Category:基礎條目"
	},
}

local function _getItem(obj, _key)
	local key = mw.text.trim(mw.ustring.lower(_key))
	for _, item in pairs(obj) do
		if item.name == key then
			return item
		end
		if type(item.alias) == type({"array"}) then
			for __, alias_name in pairs(item.alias) do
				if alias_name == key then
					return item
				end
			end
		end
	end
	return nil
end

function p.additional_VA(input_data)
	local data = p.getVitalData(input_data)
	local body = ''
	if type(data) ~= type(nil) then --是基礎條目
		local article_info_of_base_page = data.article_info_of_base_page
		if type(article_info_of_base_page) ~= type(nil) then --多種類別的基礎條目
			--對每種類別的基礎條目做...
			for va_base_page, va_data in pairs(article_info_of_base_page) do
				local va_meta = nil
				for _, find_meta in pairs(VA_Data) do
					if find_meta.base_page == va_base_page then
						va_meta = find_meta
						break
					end
				end
				local va_link = "[[%s|%s]]"
				local page_name = p.getPagename(input_data)
				if type(va_meta) ~= type(nil) then
					body=body..'<br/>'..va_meta.display:format(
						page_name,
						va_link:format(p.getLink(va_data), p.getTopic(va_data))
					)
					if type(va_meta.category) ~= type(nil) then
						body=body..va_link:format(va_meta.category, page_name)
					end
				end
			end
		end
	end
	return body
end

function p.hasTopic(input_data)
	local topic = input_data
	local is_lua = true
	if type((input_data or {}).args) ~= type(nil) then --input_data is a frame
		topic = input_data.args[1] or input_data.args['1'] or ''
		is_lua = false
	end
	local function _value(__value, _is_lua) if _is_lua then return __value else return __value and "1" or "" end end
	if mw.text.trim(topic or '') == '' then return _value(false, is_lua) end
	for _, level_data in pairs(vital_subpages) do
		local topic_item = _getItem(level_data, topic)
		if topic_item then
			if topic_item.name == "#default" then return _value(false, is_lua) end
			return _value(true, is_lua)
		end
	end
	return _value(false, is_lua)
end

function p.getSubpage(input_data, _level, _subpage)
	local topic = input_data
	local level = _level
	local subpage = _subpage
	if type((input_data or {}).args) ~= type(nil) then --input_data is a frame
		topic = input_data.args.topic
		level = input_data.args.level
		subpage = input_data.args.subpage
	end
	level = tonumber(level)
	local result = "Wikipedia:基礎條目"
	if vital_subpages[level] then
		local level_data = vital_subpages[level]
		local default_item = _getItem(level_data, "#default")
		if default_item then
			result = result .. (default_item.page or '')
		end
		local topic_item = _getItem(level_data, topic)
		if topic_item then
			result = result .. (topic_item.page or '')
			local subpage_item = _getItem(topic_item.subpages or {}, subpage)
			if subpage_item then
				result = result .. (subpage_item.page or '')
			end
		end
	end
	return result
end

function p.getDataPageName(_input_data)
	local input_data = tostring(_input_data)
	--相依 : 進制模板
	local convertBase, convertBaseT = require("Module:BaseConvert").convert, mw.title.new("Template:進制"):getContent()
	local subject_page = lib_PJBS.subjectPageTitle(input_data)
	subject_page = (type(subject_page.prefixedText) == type(nil)) and mw.title.new(subject_page) or subject_page
	if type(subject_page) == type(nil) then return {exists=false} end
	local first_char = mw.ustring.upper(mw.ustring.sub(subject_page.prefixedText, 1, 1)) -- get first letter of article name
	local codepoint = mw.ustring.codepoint(first_char, 1, 1)
	local base36 = convertBase({n = codepoint, base = 36})
	local page = tostring(base36:sub(-1,-1))
	return 'Wikipedia:基礎條目/資料/' .. page .. '.json'
end

function p.getDataPage(input_data)
	local data_page = mw.title.new(p.getDataPageName(input_data))
	return data_page
end

function p.getPagename(input_data)
	local page_name = input_data
	if type(input_data) == type({}) then
		if type(input_data.args) == type({}) then
			page_name = input_data.args[1] or input_data.args['1'] or ''
		else
			if type(input_data.trimmed_link) ~= type(nil) then
				return input_data
			end
		end
	end
	return p.matchVital(page_name)
end

function p.getVitalData(input_data)
	local page_name = input_data
	if type(input_data) == type({}) then
		if type(input_data.args) == type({}) then
			page_name = input_data.args[1] or input_data.args['1'] or ''
		else
			if type(input_data.trimmed_link) ~= type(nil) then
				return input_data
			end
		end
	end
	local target_page = p.matchVital(page_name)
	local data_page = p.getDataPage(target_page)
	if data_page.exists then
		local index = tonumber(target_page) or target_page --convert to number if page is numerical, otherwise loadJsonData does not work
		local data = mw.loadJsonData(data_page.prefixedText)[index]
		return data
	end
	return nil
end

function p.isVital(input_data)
	local page_name = input_data
	local is_lua = true
	if type((type(input_data) == type({}) and input_data or {}).args) == type({}) then
		page_name = input_data.args[1] or input_data.args['1'] or ''
		is_lua = false
	end
	local target_page = p.matchVital(page_name)
	if is_lua then
		return not not target_page
	else
		return target_page and "yes" or ""
	end
end

function p.matchVital(page_name)
	local function _get_item(_page_name)
		local data_page = p.getDataPage(_page_name)
		if data_page.exists then
			local index = tonumber(_page_name) or _page_name --convert to number if page is numerical, otherwise loadJsonData does not work
			local data = mw.loadJsonData(data_page.prefixedText)[index]
			return data
		end
	end
	local data = _get_item(page_name)
	if type(data) ~= type(nil) then return page_name end
	
	local redircct_page = mw.title.new(page_name) redircct_page = redircct_page.redirectTarget or redircct_page
	local redircct_name = redircct_page.prefixedText or ""
	data = _get_item(redircct_name)
	if type(data) ~= type(nil) then return redircct_name end
	
	local lib_zhcvt = require('Module:ZhConversion') --繁簡轉換
	for _, check_title in ipairs({
		lib_zhcvt.to_hant(page_name), lib_zhcvt.to_hans(page_name),
		lib_zhcvt.to_hant(redircct_name), lib_zhcvt.to_hans(redircct_name),
	}) do
		data = _get_item(check_title)
		if type(data) ~= type(nil) then return check_title end
		
		redircct_page = mw.title.new(check_title) redircct_page = redircct_page.redirectTarget or redircct_page
		redircct_name = redircct_page.prefixedText or ""
		data = _get_item(redircct_name)
		if type(data) ~= type(nil) then return redircct_name end
	end
	
	return nil
end

local function _resolve_section(data)
	if type(data.topic) == type(nil) then
		if type(data.section) ~= type(nil) then
			local result = mw.ustring.gsub(data.section, "[(%(].*[%))]", "")
			return result
		end
	else return data.topic
	end
	return ""
end

local function _resolve_meta(data)
	if (data or {}).topic == "meta" then
		local trimmed_link = data.trimmed_link or ''
		local _, meta_index = mw.ustring.find(trimmed_link, "meta[\\/]")
		if meta_index then
			local topic_tail = mw.ustring.find(trimmed_link, "[\\/#]", meta_index + 1)
			return mw.ustring.sub(trimmed_link, meta_index + 1, (topic_tail or 0) - 1)
		end
	end
	return _resolve_section(data)
end

function p.getTopic(input_data)
	local data = p.getVitalData(input_data)
	if type(data) ~= type(nil) then
		if data.base_page == "Wikipedia:中文領域基礎條目" then
			local cba_topic = mw.ustring.match(data.trimmed_link, "[\\/]([^\\/#]+)#") or mw.ustring.match(data.trimmed_link, "[\\/]([^\\/#]+)$")
			if mw.text.trim(cba_topic or '') ~= '' then
				return cba_topic
			end
		end
		return _resolve_meta(data) or ""
	end
	return ""
end

function p.getSublistText(input_data)
	local data = p.getVitalData(input_data)
	if type(data) ~= type(nil) then
		local topic = _resolve_meta(data) or ""
		local sublist = data.sublist or ""
		if topic ~= "" and sublist ~= "" then
			 local lib_zhcvt = require('Module:ZhConversion') --繁簡轉換
			 topic = lib_zhcvt.to_hant(topic)
			 sublist = lib_zhcvt.to_hant(sublist)
			 local success, matched = pcall(mw.ustring.match, topic, ({mw.ustring.gsub(sublist, "科?學", "")})[1])
			 matched = success and matched
			 if sublist ~= "其他" and sublist ~= "其它" and sublist ~= topic and not matched then
			 	return sublist
			 end
		end
	end
	return ""
end

function p.getLevel(input_data)
	local data = p.getVitalData(input_data)
	if type(data) ~= type(nil) then
		return data.level or -1
	end
	return -1
end

function p.getSublist(input_data)
	local data = p.getVitalData(input_data)
	if type(data) ~= type(nil) then
		return data.sublist or ''
	end
	return ''
end

function p.getSection(input_data)
	local data = p.getVitalData(input_data)
	if type(data) ~= type(nil) then
		return data.section or ''
	end
	return ''
end

function p.getBasePage(input_data)
	local data = p.getVitalData(input_data)
	if type(data) ~= type(nil) then
		return (data.base_page or 'Wikipedia:%s基礎條目'):format(data.va_type or "")
	end
	return 'Wikipedia:基礎條目'
end

function p.getLink(input_data)
	local data = p.getVitalData(input_data)
	if type(data) ~= type(nil) then
		local level = tostring(data.level)
		local level_name = ({'一','二','三','四','五','六','七','八','九','十',[0]='零'})[data.level]
		if level and level_name then
			local link = (data.base_page or 'Wikipedia:%s基礎條目'):format(data.va_type or "")
			if mw.text.trim(data.trimmed_link or '') ~= '' then
				link = link .. data.trimmed_link
			else
				if level~='3' then
					if level=='4' then
						link = link .. '/擴展'
					else
						link = link .. '/第' .. level_name ..'級'
					end
				end
				if (level=='4' or level=='5') and data.topic then
					link = link .. '/' .. data.topic
				end
				if data.sublist then
					link = link .. '/' .. data.sublist
				end
				if data.section then
					link = link .. '#' .. data.section
				end
			end

			if not mw.title.new(link).exists then -- add tracking category if link does not exist
				--addCategory('Wikipedia vital articles needing attention', 'L')
			end
			return link
		end
	end
	return ''
end

function p._dataCount(input_data)
	local page_id = input_data
	if type((input_data or {}).args) ~= type(nil) then --input_data is a frame
		page_id = input_data.args[1] or input_data.args['1'] or ''
	end
	local dataPage = mw.title.new('Wikipedia:基礎條目/資料/' .. (page_id or '') .. '.json')
	local success, data = pcall(mw.loadJsonData, (dataPage or {}).prefixedText)
	local count = 0
	if success and type(data) == type({"table"}) then
		for _, item in pairs(data) do
			if type(item) == type({"table"}) then count = count + 1 end
		end
	end
	return count
end

function p.checkJSON(input_data)
	local subject_page = lib_PJBS.subjectPageTitle(input_data)
	local error_count = 0
	local body = ""
	if type(subject_page.prefixedText) == type(nil) then
		subject_page = mw.title.new(subject_page)
	end
	if (subject_page.contentModel or ''):lower() == "json" then
		local data = mw.loadJsonData( subject_page.prefixedText )
		for article, _ in pairs(data) do
			local datapage = p.getDataPage(article)
			if datapage.prefixedText ~= subject_page.prefixedText then
				error_count = error_count + 1
				body = body .. '!' .. subject_page.prefixedText .. '\n||' .. 
					article .. '\n||' .. datapage.prefixedText ..'\n|-\n'
			end
		end
	end
	if error_count == 0 then
		body = body .. '!' .. subject_page.prefixedText .. '\n|colspan=2 align=center|無錯誤\n|-\n'
	end
	return body
end

function p.testAllArticleInJSON(input_data)
	local subject_page = lib_PJBS.subjectPageTitle(input_data)
	local error_count = 0
	local body = ""
	if type(subject_page.prefixedText) == type(nil) then
		subject_page = mw.title.new(subject_page)
	end
	local body = ''
	if (subject_page.contentModel or ''):lower() == "json" then
		local data = mw.loadJsonData( subject_page.prefixedText )
		for article, article_data in pairs(data) do
			local topic = _resolve_meta(article_data)
			body = body .. (body~=''and'\n'or'') ..'#[[:' .. article .. '|' .. article .. "]]属于维基百科"
				..((mw.text.trim(topic or '') == '') and '' or ("'''"..topic.."'''")) ..p.getSublistText(article)..'主題类'
				..'的[['..p.getLink(article).."|'''基础条目'''"
				..(({'第一级', '第二级', '', '扩展', '第五級'})[tonumber(article_data.level)] or '')
				..']]。请[[WP:勇于更新页面|勇于更新页面]]。'
		end
	end
	return body
end
return p