وحدة:ضبط استنادي/documentation

require('strict')
local p = {}
local title = mw.title.getCurrentTitle()
local namespace = title.namespace
local testcases = (string.sub(title.subpageText,1,9) == 'testcases')
local makelink = require('وحدة:ضبط استنادي').makelink
local config = mw.loadData('وحدة:ضبط استنادي/config')

local function needsAttention(sortkey)
	return '[[' .. config.i18n.category .. ':' .. config.i18n.attentioncat .. '|' .. sortkey .. title.text .. ']]'
end

local function addCat(cat,sortkey)
	if cat and cat ~= '' and (namespace == 0 or namespace == 14 or testcases) then
		local redlinkcat = ''
		if testcases == false and mw.title.new(cat, 14).exists == false then
			redlinkcat = needsAttention('N')
		end
		if sortkey then
			cat = '[[' .. config.i18n.category .. ':'..cat..'|' .. sortkey .. title.text .. ']]'
		else
			cat = '[[' .. config.i18n.category .. ':'..cat..']]'
		end
		cat = cat .. redlinkcat
		return cat
	else
		return ''
	end
end

local loadConfig = function(arg)
	local configfile = 'وحدة:ضبط استنادي/config' -- default configuation module
	if arg and arg~='' then
		configfile = 'وحدة:ضبط استنادي/config/' .. arg
	end
	if mw.title.new(configfile).exists then
		return mw.loadData(configfile)
	else
		return false
	end
end
-- Creates a human-readable standalone wikitable version of conf, and tracking categories with page counts, for use in the documentation
function p.docConfTable(frame)
	config = loadConfig(frame.args.config)
	if not config then return error('Invalid configuration file',0)	end
	local getlink = require("Module:Wikidata table")._getLink
	local function checkcat(category,label,idf)
		local ret='[[:' .. config.i18n.category .. ':'..category..'|'..label..']]'
        if mw.title.new(category, 14).exists == false then
			ret = ret..' <span class="plainlinks" style="font-size:85%;">&#91;['..tostring(mw.uri.fullUrl('Category:'..category,'action=edit&preload=Template:ضبط استنادي/مسبق&preloadparams[]=' .. idf))..' إنشاء]&#93;</span>'
        end
        return ret
	end
	local doc = ''
	local a, P, f = 0, 0, 0 --cumulative sums
	local count = frame.args.count or false
	local columns = 3 + (count and 1 or 0)
	local lang = mw.getContentLanguage()
	local row = function(conf)
		local category = conf.category or conf[1]
		local articleCat = mw.message.newRawMessage(config.i18n.aricleswithidcat, {category}):plain()
		local articleCount = mw.site.stats.pagesInCategory(articleCat,'pages')
		local errorCat = conf.errorcat or (mw.message.newRawMessage(config.i18n.aricleswithfaultyidcat, {(conf.category or conf[1])}):plain() )
		local errorCount =  mw.site.stats.pagesInCategory(errorCat,'pages')
		P = P + 1 --property count
		a = a + articleCount
		f = f + errorCount
		local example = mw.wikibase.getBestStatements('P'..conf.property,'P1855') or ''
		if example then
			example = example[1].qualifiers['P'..conf.property][1].datavalue.value
			example = frame:expandTemplate{title = "Hlist", args = {'\n' .. makelink(conf,{id=example},1)}} .. '\n'
		end
		local getname = function(nameprop)
			local name = mw.wikibase.getBestStatements('P'..conf.property,nameprop)
			if name and name[1] and name[1].mainsnak.datavalue.value.id then
				return frame:expandTemplate{title='رابط ويكي بيانات بديل',args={name[1].mainsnak.datavalue.value.id}}
			end
		end
		local name = getname('P1629') or getname('P10726') or ''
		local out = ''
		if conf.remark then
			out = out .. '<tr><td rowspan=2>'
		else
			out = out .. '<tr><td>'
		end
		out = out .. name .. '</td>' ..
			'<td style="text-align: center">' .. config.sections[conf.section].name .. '</td>' ..
			'<td data-sort-value=' .. conf.property .. '>' .. frame:expandTemplate{title='خاصية',args={id='f',conf.property}} .. '</td>' ..
			'<td>' .. example .. '</td>'
		if count then
			out = out .. '<td style="text-align: right;">'..checkcat(articleCat,lang:formatNum(articleCount),category)..' ('..checkcat(errorCat,errorCount, 'faulty ' .. category)..')</td>'
		end
		out = out .. '</tr>'
		if conf.remark then
			out = out .. "<tr class='expand-child'><td colspan=" .. columns .. ">'''ملاحظات:''' " .. frame:preprocess{text = conf.remark} .. "</td></tr>"
		end
		return out
	end
	local doc = '<table class="wikitable sortable">'..
	'<tr><th>المعرف</th>'..
	'<th>الصنف</th>'..
	'<th data-sort-type=number>خاصية ويكي بيانات</th>'..
	'<th>النص الظاهر</th>'
	if count then
	 	doc = doc .. '<th>[[:Category:مقالات فيها معلومات ضبط استنادي|المقالات]] ([[:Category:مقالات بها معرفات ضبط استنادي خاطئة|خاطئة]])</th>'
	end
	doc = doc .. '</tr>'
	for _, conf in pairs(config.config) do
		doc = doc .. row(conf)
	end
	if count then
		doc = doc .. '<tr><th style="text-align: right;" colspan=' .. columns-1 .. '>الإجمالي</th>' ..
			'<th style="text-align: right;">' .. P .. '</th>' ..
			'<th style="text-align: right;">' .. lang:formatNum(a) .. ' ([[:Category:' .. config.i18n.allfaultycat .. '|' .. f .. ']])</th></tr>'
	end
	doc = doc .. '</table>'
	return doc
end

function p.errorTable(frame)
	local config = loadConfig(frame.args.config)
	if not config then return error('Invalid configuration file',0)	end
	local Table = '<table class="wikitable sortable">'..
	  '<tr><th>خاصية ويكي بيانات</th>'..
	  '<th>المعرفات الخاطئة</th>'..
	  '<th>[[:تصنيف:مقالات بها معرفات ضبط استنادي خاطئة|تصنيف التتبع]]</th></tr>'
	local f, P = 0, 0, 0 --cumulative sums
	for _, conf in pairs(config.config) do
		local category = conf.errorcat or mw.message.newRawMessage(config.i18n.aricleswithfaultyidcat, {(conf.category or conf[1])}):plain()
		local count =  mw.site.stats.pagesInCategory(category,'pages')
		if count > 0 then
			P = P + 1
			f = f + count
			Table = Table..'<tr><td>'..frame:expandTemplate{ title = 'خاصية', args = { id = 'f', conf.property } } .. '</td>'..
				'<td style="text-align:center;">'..tostring(count)..'</td>'..
				'<td>[[:تصنيف:'..category..']]</td></tr>'
		end
	end
	Table = Table..'<tr><th>Totals</th>'..
		'<th style="text-align:center;">' .. '[[:تصنيف:' .. config.i18n.allfaultycat .. '|' .. tostring(f) .. ']]</th>'..
		'<th style="text-align:center;">'..tostring(P)..'</th></tr></table>'
	return Table
end

function p.whitelisttable(frame)
	local config = loadConfig(frame.args.config)
	if not config then return error('Invalid configuration file',0)	end
	local Table = '<table class="wikitable sortable">'..
	  '<tr><th>Code</th>'..
	  '<th>Topic</th>'..
	  '<th>Identifiers</th></tr>'
	for code, wlist in pairs(config.whitelists) do
		Table = Table .. '<tr><th>' .. code .. '</th>'..
			'<td>[[' .. mw.wikibase.getSitelink('Q' .. wlist.topic) .. ']]</td>'
		local plist = {}
		for _, property in pairs(wlist.properties) do
			table.insert(plist,frame:expandTemplate{title='خاصية', args={'P' .. property}})
		end
		Table = Table .. '<td>' .. table.concat(plist,', ') .. '</td></tr>'
	end
	Table = Table .. '</table>'
	return Table
end

function p.sectiontable(frame)
	local config = loadConfig(frame.args.config)
	if not config then return error('Invalid configuration file',0)	end
	local Table = '<table class="wikitable sortable">'..
	  '<tr><th>Section</th>'..
	  '<th>Description</th>'..
	  '<th>Identifiers</th></tr>'
	for number,section in ipairs(config.sections) do
		Table = Table .. '<tr><th>' .. number .. '</th>' ..	'<td>' .. section.name .. '</td>'
		local plist = {}
		for _,id in pairs(config.config) do
			if id.section == number then
				table.insert(plist,frame:expandTemplate{title='خاصية', args={'P' .. id.property}})
			end
		end
		Table = Table .. '<td>' .. table.concat(plist,', ') .. '</td></tr>'
	end
	Table = Table .. '</table>'
	return Table
end

function p.autoDetect(frame)
	local config = loadConfig(frame.args.config)
	if not config then return error('Invalid configuration file',0)	end
	local function whichTOC(frame) -- standardize TOC behavior via {{'فهرس تصنيف آلي'}}
		return frame:expandTemplate{ title = 'فهرس تصنيف آلي', args = { align = 'center' } }
	end
	--local rmCats = require('Module:Suppress categories').main
	local function wpa(frame,id,faulty)
		for _,conf in pairs(config.config) do
			if conf.category == id or conf[1] == id then
				local getname = function(nameprop)
					local name = mw.wikibase.getBestStatements('P'..conf.property,nameprop)
					if name and name[1] and name[1].mainsnak.datavalue.value.id then
						return frame:expandTemplate{title='Wikidata fallback link',args={name[1].mainsnak.datavalue.value.id}}
					end
				end
				local name = getname('P1629') or getname('P10726') or ''
				local outString = frame:expandTemplate{ title = 'شرح تصنيف', args = {'مقالات مع معرفات '..name..' الرجاء عدم إضافة [[ويكيبيديا:تصنيف|تصنيفات فرعية]].\nالصفحات في هذا التصنيف تضاف فقط من [[وحدة:ضبط استنادي]].'}}
					.. frame:expandTemplate{ title = 'تصنيف أكثر', args = {'ويكيبيديا:ضبط استنادي', ':d:Property:P'..conf.property} }
					.. frame:expandTemplate{ title = 'تصنيف فارغ' }
					.. frame:expandTemplate{ title = 'تصنيف صيانة', args = { hidden = 'yes', tracking = 'yes' } }
					.. frame:expandTemplate{ title = 'تصنيف ملوث' }
					.. whichTOC( frame )
				if faulty then
					outString = outString .. addCat('مقالات بها معرفات ضبط استنادي خاطئة',id) .. addCat(mw.message.newRawMessage( config.i18n.aricleswithidcat, {id}):plain())
				else
					outString = outString .. addCat('مقالات فيها معلومات ضبط استنادي',id)
				end
				return outString
			end
		end
	end
	if namespace == 14 then --cat space
		local wpfaultyID = mw.ustring.match(title.text, mw.message.newRawMessage( config.i18n.aricleswithfaultyidcat, {'(.+)'}):plain())
		local wpID = mw.ustring.match(title.text, mw.message.newRawMessage( config.i18n.aricleswithidcat, {'(.+)'}):plain())
		if wpfaultyID then
			return wpa(frame,wpfaultyID,true)-- must be before wpID check, in case they both match
		elseif wpID then
			return wpa(frame,wpID,false)
		else
			return needsAttention('U')
		end
	end
end

function p.idproposal(frame)
	local config = loadConfig(frame.args.config)
	if not config then return error('Invalid configuration file',0)	end
	local property = frame.args.property or ''
	local out = '<ul><li>Wikidata property: ' .. frame:expandTemplate{title='خاصية', args={'P' .. property}} .. '</li>'
	out = out .. '<li>Section: '
	local section = frame.args.section or ''
	if section~='' then
		out = out .. config.sections[section].name .. ' (' .. section .. ')'
	else
		out = out .. 'Not specified'
	end
	out = out .. '</li><li>Link: '
	local link = frame.args.link or ''
	if link=='' then
		link = mw.wikibase.getBestStatements('P'..property,'P1630') or ''
		link = link[1].mainsnak.datavalue.value
	end	
	if link~='' then
		out = out .. '<code>' .. link .. '</code>'
	else
		out = out .. 'Not specified'
	end
	out = out .. '</li><li>Label: '
	local label = frame.args.label or ''
	if label~='' then
		out = out .. label
	else
		out = out .. 'Not specified'
	end
	out = out .. '</li><li>Example: '
	local example = mw.wikibase.getBestStatements('P'..property,'P1855') or ''
	if example then
		example = example[1].qualifiers['P'..property][1].datavalue.value
		example = frame:expandTemplate{title = "Hlist", args = {'\n' .. makelink({[1]='',link=link,label=label},{id=example},1)}} .. '\n'
		out = out .. example
	else
		out = out .. 'Not available'
	end
	out = out .. '</li></ul>'
	return out
end

return p