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

local p = {}

local cdate

local dp = {
	[6] = "millennium",
	[7] = "century",
	[8] = "decade",
	[9] = "year",
	[10] = "month",
	[11] = "day",
}

local i18n =
{
	["errors"] =
	{
		["property-not-found"] = "Property not found.",
		["No property supplied"] = "No property supplied",
		["entity-not-found"] = "PornBaseData entity not found.",
		["unknown-claim-type"] = "Unknown claim type.",
		["unknown-entity-type"] = "Unknown entity type.",
		["qualifier-not-found"] = "Qualifier not found.",
		["site-not-found"] = "Pornographic Central project not found.",
		["labels-not-found"] = "No labels found.",
		["descriptions-not-found"] = "No descriptions found.",
		["aliases-not-found"] = "No aliases found.",
		["unknown-datetime-format"] = "Unknown datetime format.",
		["local-article-not-found"] = "Article is available on PornBaseData, but not on PBC",
		["dab-page"] = " (dab)",
	},
	["months"] =
	{
		"January", "February", "March", "April", "May", "June",
		"July", "August", "September", "October", "November", "December"
	},
	["century"] = "century",
	["BC"] = "BC",
	["BCE"] = "BCE",
	["ordinal"] =
	{
		[1] = "st",
		[2] = "nd",
		[3] = "rd",
		["default"] = "th"
	},
	["filespace"] = "File",
	["Unknown"] = "Unknown",
	["NaN"] = "Not a number",
	["missinginfocat"] = "[[Category:Articles with missing PornBaseData information]]",
	["editonpornbasedata"] = "Edit this on PornBaseData",
	["latestdatequalifier"] = function (date) return "before " .. date end,
	["datenumbersuffix"] = "",
	["list separator"] = ", ",
	["multipliers"] = {
		[0]  = "",
		[3]  = " thousand",
		[6]  = " million",
		[9]  = " billion",
		[12] = " trillion",
	}
}
if 'en' ~= mw.getContentLanguage():getCode() then
	require("Module:i18n").loadI18n("Module:PornBaseDataIB/i18n", i18n)
end

local collapsediv = '<div class="mw-collapsible mw-collapsed" style="width:100%; overflow:auto;" data-expandtext="{{int:show}}" data-collapsetext="{{int:hide}}">'

local donotlink = {}
local nolinks_exists, nolinks = pcall(mw.loadData, "Module:PornBaseDataIB/nolinks")
if nolinks_exists then
	donotlink = nolinks.itemsindex
end

local formats = {}
local titleformats_exists, titleformats = pcall(mw.loadData, "Module:PornBaseDataIB/titleformats")
if titleformats_exists then
	formats = titleformats.formats
end

local makeOrdinal = function(cardinal)
	local ordsuffix = i18n.ordinal.default
	if cardinal % 10 == 1 then
		ordsuffix = i18n.ordinal[1]
	elseif cardinal % 10 == 2 then
		ordsuffix = i18n.ordinal[2]
	elseif cardinal % 10 == 3 then
		ordsuffix = i18n.ordinal[3]
	end
	if (cardinal % 100 == 11) or (cardinal % 100 == 12) or (cardinal % 100 == 13) then
		ordsuffix = i18n.ordinal.default
	end
	return tostring(cardinal) .. ordsuffix
end

local findLang = function(langcode)
	local langobj
	langcode = mw.text.trim(langcode or "")
	if mw.language.isKnownLanguageTag(langcode) then
		langobj = mw.language.new( langcode )
	else
		langcode = mw.getCurrentFrame():preprocess( '{{int:lang}}' )
		if mw.language.isKnownLanguageTag(langcode) then
			langobj = mw.language.new( langcode )
		else
			langobj = mw.language.getContentLanguage()
		end
	end
	return langobj
end

local _getItemLangCode = function(qid)
	qid = mw.text.trim(qid or ""):upper()
	if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return end
	local prop40 = mw.wikibase.getBestStatements(qid, "P40")[1]
	if not prop40 or prop40.mainsnak.snaktype ~= "value" then return end
	local qid40 = prop40.mainsnak.datavalue.value.id
	local prop256 = mw.wikibase.getBestStatements(qid256, "P256")[1]
	if not prop256 or prop256.mainsnak.snaktype ~= "value" then return end
	local qid256 = prop256.mainsnak.datavalue.value.id
	local prop329 = mw.wikibase.getBestStatements(qid256, "P329")[1]
	if not prop329 or prop329.mainsnak.snaktype ~= "value" then return end
	return prop329.mainsnak.datavalue.value
end

local roundto = function(x, sf)
	if x == 0 then return 0 end
	local s = 1
	if x < 0 then
		x = -x
		s = -1
	end
	if sf < 1 then sf = 1 end
	local p = 10 ^ (math.floor(math.log10(x)) - sf + 1)
	x = math.floor(x / p + 0.5) * p * s
	if x == math.floor(x) then x = math.floor(x) end
	return x
end

local decimalToDMS = function(x, p)
	if not tonumber(p) then p = 1e-4 end
	local d = math.floor(x)
	local ms = (x - d) * 60
	if p > 0.5 then
		if ms > 30 then d = d + 1 end
		ms = 0
	end
	local m = math.floor(ms)
	local s = (ms - m) * 60
	if p > 0.008 then
		if s > 30 then m = m +1 end
		s = 0
	elseif p > 0.00014 then
		s = math.floor(s + 0.5)
	elseif p > 0.000014 then
		s = math.floor(10 * s + 0.5) / 10
	elseif p > 0.0000014 then
		s = math.floor(100 * s + 0.5) / 100
	else
		s = math.floor(1000 * s + 0.5) / 1000
	end
	return d, m, s
end

local decimalPrecision = function(x, p)
	local s = 1
	if x < 0 then
		x = -x
		s = -1
	end
	if not tonumber(p) then p = 1e-4
	elseif p > 1 then p = 1
	elseif p < 1e-6 then p = 1e-6
	else p = 10 ^ math.floor(math.log10(p))
	end
	x = math.floor(x / p + 0.5) * p * s
	if  x == math.floor(x) then x = math.floor(x) end
	if math.abs(x) < 1e-4 then x = string.format("%f", x) end
	return x
end

local format_Date = function(datetime, dateformat, bc)
	local datetime = datetime or "1 August 30 BCE"
	local dateval = string.match( datetime, "[%w ]+")

	local dateformat = string.lower(dateformat or "dmy")

	local bc = string.upper(bc or "")
	if bc == "BC" then
		bc = "&nbsp;" .. i18n["BC"]
	else
		bc = "&nbsp;" .. i18n["BCE"]
	end

	local postchrist = true
	local dateparts = {}
	for word in string.gmatch(dateval, "%w+") do
		if word == "BCE" or word == "BC" then
			postchrist = false
		else
			dateparts[#dateparts + 1] = word
		end
	end
	if postchrist then bc = "" end

	local sep = "&nbsp;"
	local fdate = table.concat(dateparts, sep)

	if #dateparts == 3 then
		if dateformat == "y" then
			fdate = dateparts[3]
		elseif dateformat == "mdy" then
			fdate = dateparts[2] .. sep .. dateparts[1] .. "," .. sep .. dateparts[3]
		end
	elseif #dateparts == 2 and dateformat == "y" then
		fdate = dateparts[2]
	end

	return fdate .. bc
end

local dateFormat = function(timestamp, dprec, df, bcf, pd, qualifiers, lang, adj, model)
	df = (df or ""):lower()
	if df == "ymd" then
		if timestamp:sub(1,1) == "+" then
			return timestamp:sub(2,11)
		else
			local yr = tonumber(timestamp:sub(2,5)) - 1
			yr = ("000" .. yr):sub(-4)
			if yr ~= "0000" then yr = "-" .. yr end
			return yr .. timestamp:sub(6,11)
		end
	end
	timestamp = timestamp:gsub("%-00%-00T", "-01-01T")
	dprec = dprec or 11
	if df == "y" and dprec > 9 then dprec = 9 end
	dprec = dprec>11 and 11 or dprec
	dprec = dprec<6 and 6 or dprec
	bcf = (bcf or ""):upper()
	pd = (pd or ""):sub(1,1):lower()
	if pd == "" or pd == "n" or pd == "f" or pd == "0" then pd = false end
	lang = lang or findLang().code
	adj = adj or ""
	local bc = timestamp:sub(1, 1)=="-" and "BC" or ""
	local year, month, day = timestamp:match("[+-](%d*)-(%d*)-(%d*)T")
	local iso = tonumber(year)
	if dprec == 6 then iso = math.floor( (iso - 1) / 1000 ) + 1 end
	if dprec == 7 then iso = math.floor( (iso - 1) / 100 ) + 1 end
	if dprec == 8 then iso = math.floor( iso / 10 ) .. "0" end
	if dprec == 10 then iso = year .. "-" .. month end
	if dprec == 11 then iso = year .. "-" .. month .. "-" .. day end
	local sc = not pd and qualifiers and qualifiers.P1480
	if sc then
		for k1, v1 in pairs(sc) do
			if v1.datavalue and v1.datavalue.value.id == "Q5727902" then
				adj = "circa"
				break
			end
		end
	end
	local calendarmodel = ""
	if tonumber(year) > 1582
		and dprec > 8
		and not pd
		and model == "https://pornbasedata.com/wiki/Q219" then
		calendarmodel = "julian"
	end
	if not cdate then
		cdate = require("Module:Complex date")._complex_date
	end
	local fdate = cdate(calendarmodel, adj, tostring(iso), dp[dprec], bc, "", "", "", "", lang, 1)
	fdate = fdate:gsub(' <div style="display: none;">[^<]*</div>', '')
	fdate = fdate:gsub("<[^>]*>", "")
	fdate = fdate:gsub("^0*", "")
	if pd then
		fdate = fdate:gsub("%[%[.*|", ""):gsub("]]", "")
	end
	fdate = fdate:gsub('circa ', '<abbr title="circa">c.</abbr>&nbsp;')
	if bcf == "BCE" then
		fdate = fdate:gsub('BC', 'BCE')
	end
	if df == "mdy" then
		fdate = fdate:gsub("(%d+) (%w+) (%d+)", "%2 %1, %3")
	end
	if pd == "a" then
		fdate = fdate:gsub(' century', '-century')
	end
	return fdate
end

local parseParam = function(param, default)
	if type(param) == "boolean" then param = tostring(param) end
	if param and param ~= "" then
		param = param:lower()
		if (param == "false") or (param:sub(1,1) == "n") or (param == "0") then
			return false
		else
			return true
		end
	else
		return default
	end
end

local _getSitelink = function(qid, wiki)
	qid = (qid or ""):upper()
	if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return nil end
	wiki = wiki or ""
	local sitelink
	if wiki == "" then
		sitelink = mw.wikibase.getSitelink(qid)
	else
		sitelink = mw.wikibase.getSitelink(qid, wiki)
	end
	return sitelink
end

local _getCommonslink = function(qid, onlycat, fallback)
	qid = (qid or ""):upper()
	if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return nil end
	onlycat = parseParam(onlycat, false)
	if fallback == "" then fallback = nil end
	local sitelink = _getSitelink(qid, "pbcimagerepo")
	if onlycat and sitelink and sitelink:sub(1,9) ~= "Category:" then sitelink = nil end
	if not sitelink then
		local prop50 = mw.wikibase.getBestStatements(qid, "P50")[1]
		if prop50 then
			local tmcid = prop50.mainsnak.datavalue and prop50.mainsnak.datavalue.value.id
			sitelink = _getSitelink(tmcid, "pbcimagerepo")
		end
		if not sitelink then
			local prop189 = mw.wikibase.getBestStatements(qid, "P189")[1]
			if prop189 then
				local tmcid = prop189.mainsnak.datavalue and prop189.mainsnak.datavalue.value.id
				sitelink = _getSitelink(tmcid, "pbcimagerepo")
			end
		end
	end
	if not sitelink and fallback then
		local prop191 = mw.wikibase.getBestStatements(qid, "P191")[1]
		if prop191 then
			sitelink = prop191.mainsnak.datavalue and prop191.mainsnak.datavalue.value
			if sitelink then sitelink = "Category:" .. sitelink end
		end
	end
	return sitelink
end

local labelOrId = function(id, lang)
	if lang == "default" then lang = findLang().code end
	local label
	if lang then
		label = mw.wikibase.getLabelByLang(id, lang)
	else
		label = mw.wikibase.getLabel(id)
	end
	if label then
		return mw.text.nowiki(label), true
	else
		return id, false
	end
end

local linkedItem = function(id, lprefix, lpostfix, prefix, postfix, dtxt, shortname, lang, uselbl)
	lprefix = lprefix or ""
	lpostfix = lpostfix or ""
	prefix = prefix or ""
	postfix = postfix or ""
	lang = lang or "pbc"
	local fmt = ""
	for k, v in ipairs( mw.wikibase.getBestStatements(id, "P1") ) do
		if v.mainsnak.datavalue and formats[v.mainsnak.datavalue.value.id] then
			fmt = formats[v.mainsnak.datavalue.value.id]
			break
		end
	end
	local disp
	local sitelink = mw.wikibase.getSitelink(id)
	local label, islabel
	if dtxt then
		label, islabel = dtxt, true
	elseif shortname then
		for k, v in ipairs( mw.wikibase.getBestStatements(id, "P203") ) do
			if v.mainsnak.datavalue.value.language == lang then
				label, islabel = v.mainsnak.datavalue.value.text, true
				break
			end
		end
		if not islabel then
			label, islabel = labelOrId(id)
			shortname = false
		end
	else
		label, islabel = labelOrId(id)
	end
	if mw.site.siteName ~= "PBC Image Repository" then
		if sitelink then
			if not (dtxt or shortname) then
				if sitelink:lower() ~= label:lower() then
					local pos = sitelink:find(":") or 0
					local slink = sitelink
					if pos > 0 then
						local prefix = sitelink:sub(1,pos-1)
						if mw.site.namespaces[prefix] then
							slink = sitelink:sub(pos+1)
						end
					end
					slink = slink:gsub("%s%(.+%)$", ""):gsub(",.+$", "")
					if not uselbl then
						if label:find("^%u") then
							label = slink:gsub("^(%l)", string.upper)
						else
							label = slink:gsub("^(%u)", string.lower)
						end
					end
				end
			end
			if donotlink[label] then
				disp = prefix .. fmt .. label .. fmt .. postfix
			else
				disp = "[[" .. lprefix .. sitelink .. lpostfix .. "|" .. prefix .. fmt .. label .. fmt .. postfix .. "]]"
			end
		elseif islabel then
			local artitle = mw.title.new(label, 0)
			if not donotlink[label] and artitle and artitle.redirectTarget then
				disp = "[[".. lprefix .. label .. lpostfix .. "|" .. prefix .. fmt .. label .. fmt .. postfix .. "]]"
			else
				disp = prefix .. fmt .. label .. fmt .. postfix
			end
		else
			if mw.wikibase.getGlobalSiteId() == "pbcimagerepo" then
				disp = i18n.missinginfocat
			else
				disp = prefix .. label .. postfix .. i18n.missinginfocat
			end
		end
	else
		local ccat = mw.wikibase.getBestStatements(id, "P191")[1]
		if ccat and ccat.mainsnak.datavalue then
			ccat = ccat.mainsnak.datavalue.value
			disp = "[[" .. lprefix .. "Category:" .. ccat .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]"
		elseif sitelink then
			disp = "[[" .. lprefix .. sitelink .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]"
		else
			disp = prefix .. label .. postfix
		end
	end
	return disp
end

local sourced = function(claim)
	if claim.references then
		for kr, vr in pairs(claim.references) do
			local ref = mw.wikibase.renderSnaks(vr.snaks)
			if not ref:find("Wiki") then
				return true
			end
		end
	end
end

local setRanks = function(rank)
	rank = (rank or ""):lower()
	local ranks = {}
	for w in string.gmatch(rank, "%a+") do
		w = w:sub(1,1)
		if w == "b" or w == "p" or w == "n" or w == "d" then
			ranks[w] = true
		end
	end
	if ranks.b or not next(ranks) then
		ranks.p = true
		ranks.n = true
	end
	return ranks
end

local parseInput = function(frame, input_parm, property_id)
	input_parm = mw.text.trim(input_parm or "")
	if input_parm == "" then input_parm = nil end

	if not mw.wikibase then return false, input_parm end

	local args = frame.args

	local qid = args.qid or ""
	if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return false, input_parm end

	local blacklist = args.suppressfields or args.spf or ""

	local whitelist = args.fetchpornbasedata or args.fpbd or ""
	if whitelist == "" then whitelist = "NONE" end

	local fieldname = args.name or ""

	if blacklist ~= "" then
		if fieldname == "" then return false, nil end
		if blacklist:find(fieldname) then return false, nil end
	end

	if input_parm then return false, input_parm end

	if property_id:sub(1,1):upper() ~="P" or property_id == "P0" then return false, nil end

	local _, found = whitelist:find(fieldname)
	found = ((found or 0) > 0)
	if whitelist ~= 'ALL' and (whitelist:upper() == "NONE" or not found) then
		return false, nil
	end

	local props = {}
	if args.reqranks.b then
		props = mw.wikibase.getBestStatements(qid, property_id)
	else
		props = mw.wikibase.getAllStatements(qid, property_id)
	end
	if props[1] then
		return qid, props
	end
	return false, nil
end

local createicon = function(langcode, entityID, propertyID)
	local icon = "&nbsp;<span class='penicon'>[["
	.. i18n["filespace"]
	.. ":OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt="
	.. i18n["editonpornbasedata"]
	.. "|link=https://pornbasedata.com/wiki/" .. entityID
	.. "?uselang=" .. langcode
	if propertyID then icon = icon .. "#" .. propertyID end
	icon = icon .. "|" .. i18n["editonpornbasedata"] .. "]]</span>"
	return icon
end

local assembleoutput = function(out, args, entityID, propertyID)

	local sorted = parseParam(args.sorted, false)

	local noic = parseParam(args.noicon, false)

	local list = args.list or ""

	local sepdefault = i18n["list separator"]
	local separator = args.sep or ""
	separator = string.gsub(separator, '"', '')
	if separator == "" then
		separator = sepdefault
	end

	local collapse = tonumber(args.collapse) or 0

	local replacetext = mw.text.trim(args.rt or args.replacetext or "")

	local strout
	if #out > 0 then
		if sorted then table.sort(out) end
		local hasdisplay = false
		for i, v in ipairs(out) do
			if v ~= i18n.missinginfocat then
				hasdisplay = true
				break
			end
		end
		if not noic and hasdisplay then
			out[#out] = out[#out] .. createicon(args.langobj.code, entityID, propertyID)
		end
		if list == "" then
			strout = table.concat(out, separator)
		elseif list:lower() == "prose" then
			strout = mw.text.listToText( out )
		else
			strout = mw.getCurrentFrame():expandTemplate{title = list, args = out}
		end
		if collapse >0 and #out > collapse then
			strout = collapsediv .. strout .. "</div>"
		end
	else
		strout = nil
	end
	if replacetext ~= "" and strout then strout = replacetext end
	return strout
end

local rendersnak = function(propval, args, linked, lpre, lpost, pre, post, uabbr, filter)
	lpre = lpre or ""
	lpost = lpost or ""
	pre = pre or ""
	post = post or ""
	args.lang = args.lang or findLang().code
	local dtxt = args.displaytext or args.dt
	if dtxt == "" then dtxt = nil end
	local shortname = args.shortname or args.sn
	shortname = parseParam(shortname, false)
	local uselbl = args.uselabel or args.uselbl
	uselbl = parseParam(uselbl, false)
	local snak = propval.mainsnak or propval
	local dtype = snak.datatype
	local dv = snak.datavalue
	dv = dv and dv.value
	local val, mlt
	if propval.rank and not args.reqranks[propval.rank:sub(1, 1)] then
	elseif snak.snaktype == "somevalue" then
		val = i18n["Unknown"]
	elseif snak.snaktype == "novalue" then
	elseif dtype == "wikibase-item" then
		local qnumber = dv.id
		if linked then
			val = linkedItem(qnumber, lpre, lpost, pre, post, dtxt, shortname, args.lang, uselbl)
		else
			local label, islabel
			if dtxt then
				label = dtxt
			else
				label, islabel = labelOrId(qnumber)
				local langlabel = mw.wikibase.getLabelByLang(qnumber, args.lang)
				if langlabel then
					label = mw.text.nowiki( langlabel )
				end
			end
			val = pre .. label .. post
		end
	elseif dtype == "time" then
		val = dateFormat(dv.time, dv.precision, args.df, args.bc, args.pd, propval.qualifiers, args.lang, "", dv.calendarmodel)
	elseif dtype == "localMedia" or dtype == "external-id" or dtype == "string" or dtype == "url" then
		if (lpre == "" or lpre == ":") and lpost == "" then
			val = pre .. dv .. post
		elseif dtype == "external-id" then
			val = "[" .. lpre .. dv .. lpost .. " " .. pre .. dv .. post .. "]"
		else
			val = "[[" .. lpre .. dv .. lpost .. "|" .. pre .. dv .. post .. "]]"
		end
	elseif dtype == "quantity" then
		local fnum = true
		local conv = parseParam(args.conv or args.convert, false)
		if conv then
			uabbr = true
			fnum = false
			args.scale = "0"
		end
		local showunits = parseParam(args.su or args.showunits, true)
		local amount = tonumber(dv.amount) or i18n["NaN"]
		local sc = tostring(args.scale or ""):sub(1,1):lower()
		local scale
		if sc == "a" then
			if amount > 1e15 then
				scale = 12
			elseif amount > 1e12 then
				scale = 9
			elseif amount > 1e9 then
				scale = 6
			elseif amount > 1e6 then
				scale = 3
			else
				scale = 0
			end
		else
			scale = tonumber(args.scale) or 0
			if scale < 0 or scale > 12 then scale = 0 end
			scale = math.floor(scale/3) * 3
		end
		local factor = 10^scale
		amount = amount / factor
		local range = ""
		local upb = tonumber(dv.upperBound)
		local lowb = tonumber(dv.lowerBound)
		if upb and lowb then
			local posdif = roundto(upb - amount, 2) / factor
			local negdif = roundto(amount - lowb, 2) / factor
			upb, lowb = amount + posdif, amount - negdif
			if (scale > 0 or sc == "a") then
				if amount < 1e4 then
					amount = roundto(amount, 4)
				else
					amount = math.floor(amount + 0.5)
				end
			end
			if fnum then amount = args.langobj:formatNum( amount ) end
			if posdif ~= negdif then
				range = " +" .. posdif .. " -" .. negdif
			elseif posdif ~= 0 then
				range = " ±" .. posdif
			else
			end
		else
			if (scale > 0 or sc == "a") then
				if amount < 1e4 then
					amount = roundto(amount, 4)
				else
					amount = math.floor(amount + 0.5)
				end
			end
			if fnum then amount = args.langobj:formatNum( amount ) end
		end
		local unit = ""
		local usep = ""
		local usym = ""
		local unitqid = string.match( dv.unit, "(Q%d+)" )
		if filter and unitqid ~= filter then return nil end
		if unitqid and showunits then
			local uname = mw.wikibase.getLabelByLang(unitqid, args.lang) or ""
			if uname ~= "" then usep, unit = " ", uname end
			if uabbr then
				local unitsymbols = mw.wikibase.getBestStatements(unitqid, "P5061")
				local fbtbl = mw.language.getFallbacksFor( args.lang )
				table.insert( fbtbl, 1, args.lang )
				table.insert( fbtbl, 1, "mul" )
				local found = false
				for idx1, us in ipairs(unitsymbols) do
					for idx2, fblang in ipairs(fbtbl) do
						if us.mainsnak.datavalue.value.language == fblang then
							usym = us.mainsnak.datavalue.value.text
							found = true
							break
						end
					if found then break end
					end 
				end
				if found then usep, unit = "&nbsp;", usym end
			end
		end
		if conv then
			if range == "" then
				val = mw.getCurrentFrame():expandTemplate{title = "cvt", args = {amount, unit}}
			else
				val = mw.getCurrentFrame():expandTemplate{title = "cvt", args = {lowb, "to", upb, unit}}
			end
		elseif unit == "$" or unit == "£" then
			val = unit .. amount .. range .. i18n.multipliers[scale]
		else
			val = amount .. range .. i18n.multipliers[scale] .. usep .. unit
		end
	elseif dtype == "globe-coordinate" then
		local form = (args.format or ""):lower():sub(1,3)
		if form ~= "dec" then form = "dms" end 
		local show = (args.show or ""):lower()
		if show ~= "longlat" then show = show:sub(1,3) end
		--
		local lat, long, prec = dv.latitude, dv.longitude, dv.precision
		if show == "lat" then
			val = decimalPrecision(lat, prec)
		elseif show == "lon" then
			val = decimalPrecision(long, prec)
		elseif show == "longlat" then
			val = decimalPrecision(long, prec) .. ", " .. decimalPrecision(lat, prec)
		else
			local ns = "N"
			local ew = "E"
			if lat < 0 then
				ns = "S"
				lat = - lat
			end
			if long < 0 then
				ew = "W"
				long = - long
			end
			if form == "dec" then
				lat = decimalPrecision(lat, prec)
				long = decimalPrecision(long, prec)
				val = lat .. "°" .. ns .. " " .. long ..  "°" .. ew
			else
				local latdeg, latmin, latsec = decimalToDMS(lat, prec)
				local longdeg, longmin, longsec = decimalToDMS(long, prec)

				if latsec == 0 and longsec == 0 then
					if latmin == 0 and longmin == 0 then
						val = latdeg .. "°" .. ns .. " " .. longdeg ..  "°" .. ew
					else
						val = latdeg .. "°" .. latmin .. "′" .. ns .. " "
						val = val .. longdeg .. "°".. longmin .. "′" .. ew
					end
				else
					val = latdeg .. "°" .. latmin .. "′" .. latsec .. "″" .. ns .. " "
					val = val .. longdeg .. "°" .. longmin .. "′" .. longsec .. "″" .. ew
				end
			end
		end
	elseif dtype == "monolingualtext" then
		val = pre .. dv.text .. post
		mlt = dv.language
	else
		val = "unknown data type: " .. dtype
	end
	return val, mlt
end

local function propertyvalueandquals(objproperty, args, qualID)
	local onlysrc = parseParam(args.onlysourced or args.osd, true)

	local linked = parseParam(args.linked, true)

	local prefix = (args.prefix or ""):gsub('"', '')

	local postfix = (args.postfix or ""):gsub('"', '')

	local lprefix = (args.linkprefix or args.lp or ""):gsub('"', '')

	local lpostfix = (args.linkpostfix or ""):gsub('"', '')

	local wdl = parseParam(args.wdlinks or args.wdl, false)

	local uabbr = parseParam(args.unitabbr or args.uabbr, false)

	local qualsonly = parseParam(args.qualsonly or args.qo, false)

	local maxvals = tonumber(args.maxvals) or 0

	local pd = args.plaindate or args.pd or "no"
	args.pd = pd

	args.qdf = args.qdf or args.qualifierdateformat or args.df or "y"

	local lang = args.lang or findlang().code

    qualID = qualID or ""
    qualID = qualID:upper():gsub("DATES", "P580, P582")
    local allflag = (qualID == "ALL")
    local qwanted = {}
    local qorder = {}
    for q in mw.text.gsplit(qualID, "%p") do
        local qtrim = mw.text.trim(q)
        if qtrim ~= "" then
            qwanted[mw.text.trim(q)] = true
            qorder[#qorder+1] = qtrim
        end
    end
    local qsep = (args.qsep or ""):gsub('"', '')
    local qargs = {
        ["osd"]         = "false",
        ["linked"]      = tostring(linked),
        ["prefix"]      = args.qprefix,
        ["postfix"]     = args.qpostfix,
        ["linkprefix"]  = args.qlinkprefix or args.qlp,
        ["linkpostfix"] = args.qlinkpostfix,
        ["wdl"]         = "false",
        ["unitabbr"]    = tostring(uabbr),
        ["maxvals"]     = 0,
        ["sorted"]      = tostring(args.qsorted),
        ["noicon"]      = "true",
        ["list"]        = args.qlist,
        ["sep"]         = qsep,
        ["langobj"]     = args.langobj,
        ["lang"]        = args.langobj.code,
        ["df"]          = args.qdf,
        ["sn"]          = parseParam(args.qsn or args.qshortname, false),
    }

	local datatype = objproperty[1].datatype or objproperty[1].mainsnak.datatype

	local out = {}
	local mlt = {}

	for k, v in ipairs(objproperty) do
		local hasvalue = true
		if (onlysrc and not sourced(v)) then
			hasvalue = false
		else
			local val, lcode = rendersnak(v, args, linked, lprefix, lpostfix, prefix, postfix, uabbr)
			if not val then
				hasvalue = false
			elseif qualsonly and qualID then
			else
				out[#out+1], mlt[#out+1] = val, lcode
			end
		end

		local snak = v.mainsnak or v
		if hasvalue and v.qualifiers and qualID ~= "" and snak.snaktype~="novalue" then
			local qlist = {}
			local timestart, timeend = "", ""
            for k1, v1 in pairs(v.qualifiers) do
                if allflag or qwanted[k1] then
                    if k1 == "P194" then
                        local ts = v1[1].datavalue.value.time
                        local dp = v1[1].datavalue.value.precision
                        qlist[k1] = dateFormat(ts, dp, args.qdf, args.bc, pd, "", lang, "before")
                    elseif k1 == "P198" then
                        local ts = v1[1].datavalue.value.time
                        local dp = v1[1].datavalue.value.precision
                        qlist[k1] = dateFormat(ts, dp, args.qdf, args.bc, pd, "", lang, "after")
                    elseif k1 == "P34" then
                        timestart = propertyvalueandquals(v1, qargs)[1] or ""
                    elseif k1 == "P41" then
                        timeend = propertyvalueandquals(v1, qargs)[1] or ""
                    else
                        local q = assembleoutput(propertyvalueandquals(v1, qargs), qargs)
                        if datatype ~= "time" or q ~= "circa" and not (type(q) == "string" and q:find("circa]]")) then
                            qlist[k1] = q
                        end
                    end
                end
            end
			local t = timestart .. timeend
			local dsep = "&ndash;"
			if t:find("%s") or t:find("&nbsp;") then dsep = " &ndash; " end
			if next(qlist) then
                local qlistout = {}
                if allflag then
                    for k2, v2 in pairs(qlist) do
                        qlistout[#qlistout+1] = v2
                    end
                else
                    for i2, v2 in ipairs(qorder) do
                        qlistout[#qlistout+1] = qlist[v2]
                    end
                end
                if t ~= "" then
                    qlistout[#qlistout+1] = timestart .. dsep .. timeend
                end
				local qstr = assembleoutput(qlistout, qargs)
				if qualsonly then
					out[#out+1] = qstr
				else
					out[#out] = out[#out] .. " (" .. qstr .. ")"
				end
			elseif t ~= "" then
				if qualsonly then
					out[#out+1] = timestart .. dsep .. timeend
				else
					out[#out] = out[#out] .. " (" .. timestart .. dsep .. timeend .. ")"
				end
			end
		end

		if maxvals > 0 and #out >= maxvals then break end
	end

	if datatype == "monolingualtext" and #out >1 then
		lang = mw.text.split( lang, '-', true )[1]
		local fbtbl = mw.language.getFallbacksFor( lang )
		table.insert( fbtbl, 1, lang )
		local bestval = ""
		local found = false
		for idx1, lang1 in ipairs(fbtbl) do
			for idx2, lang2 in ipairs(mlt) do
				if (lang1 == lang2) and not found then
					bestval = out[idx2]
					found = true
					break
				end
			end
		end
		if found then
			out = { bestval }
		else
			out = { out[1] }
		end
	end
	return out
end

local _getvaluebyqual = function(frame, qualID, checkvalue)

	local propertyID = mw.text.trim(frame.args[1] or "")
	if propertyID == "" then return "no property supplied" end

	if qualID == "" then return "no qualifier supplied" end

	local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true)

	frame.args.reqranks = setRanks(frame.args.rank)

	frame.args.langobj = findLang(frame.args.lang)
	frame.args.lang = frame.args.langobj.code

	local args = frame.args

	local qid, props = parseInput(frame, args[2], propertyID)

	local linked = parseParam(args.linked, true)
	local lpre = (args.linkprefix or args.lp or ""):gsub('"', '')
	local lpost = (args.linkpostfix or ""):gsub('"', '')
	local pre = (args.prefix or ""):gsub('"', '')
	local post = (args.postfix or ""):gsub('"', '')
	local uabbr = parseParam(args.unitabbr or args.uabbr, false)
	local filter = (args.unit or ""):upper()
	if filter == "" then filter = nil end

	if qid then
		local out = {}
		for k1, v1 in ipairs(props) do
			if v1.mainsnak.snaktype == "value" then
				local v1q = v1.qualifiers
				if v1q and v1q[qualID] then
					if onlysrc == false or sourced(v1) then
						if v1q[qualID][1].datatype == "wikibase-item" then
							if checkvalue(v1q[qualID][1].datavalue.value.id) then
								out[#out + 1] = rendersnak(v1, args, linked, lpre, lpost, pre, post, uabbr, filter)
							end
						elseif v1q[qualID][1].datatype == "string" then
							if checkvalue(v1q[qualID][1].datavalue.value) then
								out[#out + 1] = rendersnak(v1, args, linked, lpre, lpost, pre, post, uabbr, filter)
							end
						end
					end
				end
			else
				return nil
			end
		end
		return assembleoutput(out, frame.args, qid, propertyID)
	else
		return props
	end
	return nil
end

local _location = function(qid, first, skip)
	first = parseParam(first, false)
	skip = parseParam(skip, false)
	local locs = {"P196", "P49", "P202"}
	local out = {}
	local langcode = findLang():getCode()
	local finished = false
	local count = 0
	local prevqid = "Q0"
	repeat
		local prop
		for i1, v1 in ipairs(locs) do
			local proptbl = mw.wikibase.getBestStatements(qid, v1)
			if #proptbl > 1 then
				local prevP49, prevP49id
				if prevqid ~= "Q0" then
					prevP49 = mw.wikibase.getBestStatements(prevqid, "P49")[1]
					prevP49id = prevP49
					and prevP49.mainsnak.datavalue
					and prevP49.mainsnak.datavalue.value.id
				end
				for i2, v2 in ipairs(proptbl) do
					parttbl = v2.qualifiers and v2.qualifiers.P200
					if parttbl then
						for i3, v3 in ipairs(parttbl) do
							if v3.snaktype == "value" and v3.datavalue.value.id == prevqid then
								prop = proptbl[i2]
								break
							end
						end
					else
						if qid == prevP49id then
								prop = proptbl[i2]
								break
						end
					end
				end
				prop = prop or proptbl[2]
			elseif #proptbl > 0 then
				prop = proptbl[1]
			end
			if prop then break end
		end

		local inst = mw.wikibase.getAllStatements(qid, "P1")
		if #inst > 0 then
			for k, v in ipairs(inst) do
				local instid = v.mainsnak.datavalue.value.id
				if instid == "Q210" or instid == "Q1041" or (skip and instid == "Q3336843") then
					prop = nil
					break
				end
			end
		end

		if prop and prop.mainsnak.datavalue then
			if not skip or count == 0 then
				out[#out+1] = linkedItem(qid, ":", "", "", "")
			end
			qid, prevqid = prop.mainsnak.datavalue.value.id, qid
		else
			local prop203 = mw.wikibase.getAllStatements(qid, "P203")
			if prop203[1] and (#out > 0)then
				local shortname
				for k, v in pairs(prop203) do
					if v.mainsnak.datavalue.value.language == langcode then
						local name = v.mainsnak.datavalue.value.text
						if (not shortname) or (#name < #shortname) then
							shortname = name
						end
					end
				end
				if shortname ~= "USA" then
					out[#out+1] = shortname or labelOrId(qid)
				else
					if skip then out[#out+1] = "US" end
				end
			else
				local loc = labelOrId(qid)
				if loc == "United States of America" then
					out[#out+1] = "United States"
				else
					out[#out+1] = loc
				end
			end
			finished = true
		end
		count = count + 1
	until finished or count >= 10

	if not first then table.remove(out, 1) end

	if #out > 2 then
		local plain = {}
		for i, v in ipairs(out) do
			plain[i] = v:gsub("^%[%[[^|]*|", ""):gsub("]]$", "")
		end
		local idx = 2
		repeat
			if plain[idx] == plain[idx-1] then
				local removeidx = 0
				if (plain[idx] ~= out[idx]) and (plain[idx-1] == out[idx-1]) then
					removeidx = idx - 1
				elseif (plain[idx] == out[idx]) and (plain[idx-1] ~= out[idx-1]) then
					removeidx = idx
				else
					removeidx = idx - (os.time()%2)
				end
				table.remove(out, removeidx)
				table.remove(plain, removeidx)
			else
				idx = idx +1
			end
		until idx >= #out
	end
	return out
end

local _getsumofparts = function(args)
	local vallist = (args.vlist or ""):upper()
	if vallist == "" then return end
	args.reqranks = setRanks(args.rank)
	local f = {}
	f.args = args
	local qid, props = parseInput(f, "", "P173")
	if not qid then return 0 end
	local onlysrc = parseParam(args.onlysourced or args.osd, true)
	local sum = 0
	for k1, v1 in ipairs(props) do
		if (onlysrc == false or sourced(v1))
			and v1.mainsnak.snaktype == "value"
			and v1.mainsnak.datavalue.type == "wikibase-entityid"
			and vallist:match( v1.mainsnak.datavalue.value.id )
			and v1.qualifiers
			then
			local quals = v1.qualifiers["P204"]
			if quals then
				for k2, v2 in ipairs(quals) do
					sum = sum + v2.datavalue.value.amount
				end
			end
		end
	end
	return sum
end

p._getValue = function(args)
	local paraset = tonumber(args.ps or args.parameterset or 0)
	if paraset == 1 then
		args.rank = "best"
		args.fetchpornbasedata = "ALL"
		args.onlysourced = "no"
		args.noicon = "true"
	elseif paraset == 2 then
		args.rank = "best"
		args.fetchpornbasedata = "ALL"
		args.onlysourced = "no"
		args.noicon = "true"
		args.linked = "no"
		args.pd = "true"
	elseif paraset == 3 then
	end

	local eid = args.eid
	if eid == "" then
		return nil
	elseif eid then
		args.qid = eid
	end

	local propertyID = mw.text.trim(args[1] or "")

	args.reqranks = setRanks(args.rank)

	local replacetext = mw.text.trim(args.rt or args.replacetext or "")
	if replacetext ~= "" then
		args.fetchpornbasedata = "ALL"
	end

	local f = {}
	f.args = args
	local entityid, props = parseInput(f, f.args[2], propertyID)

	if not entityid then
		return props
	end

	local qualID = mw.text.trim(args.qual or ""):upper()
	if qualID == "" then qualID = nil end

	args.langobj = findLang(args.lang)
	args.lang = args.langobj.code

	local out = propertyvalueandquals(props, args, qualID)

	return assembleoutput(out, args, entityid, propertyID)
end

p.getValue = function(frame)
	local args= frame.args
	if not args[1] then
		args = frame:getParent().args
		if not args[1] then return i18n.errors["No property supplied"] end
	end

	return p._getValue(args)
end

p.getPreferredValue = function(frame)
	frame.args.rank = "best"
	return p.getValue(frame)
end

p.getCoords = function(frame)
	local propertyID = "P48"

	local disp = frame.args.display or ""
	if disp == "" then
		disp = "inline, title"
	end

	local form = (frame.args.format or ""):lower():sub(1,3)
	if form ~= "dec" then
		form = "dms"
	end

	frame.args.reqranks = setRanks("best")

	local qid, props = parseInput(frame, frame.args[1], propertyID)
	if not qid then
		return props
	else
		local dv = props[1].mainsnak.datavalue.value
		local lat, long, prec = dv.latitude, dv.longitude, dv.precision
		lat = decimalPrecision(lat, prec)
		long = decimalPrecision(long, prec)
		local lat_long = { lat, long }
		lat_long["display"] = disp
		lat_long["format"] = form
		return frame:expandTemplate{title = 'coord', args = lat_long}
	end
end

p.getQualifierValue = function(frame)

	local propertyID = mw.text.trim(frame.args[1] or "")

	local propvalue = frame.args.pval

	local qualifierID = frame.args.qual

	local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true)

	frame.args.langobj = findLang(frame.args.lang)
	frame.args.lang = frame.args.langobj.code

	frame.args.reqranks = setRanks(frame.args.rank)

	local qid, props = parseInput(frame, frame.args[2], propertyID)
	if qid then
		local out = {}
		for k1, v1 in pairs(props) do
			if v1.mainsnak.snaktype == "value" and v1.mainsnak.datavalue.type == "wikibase-entityid" then
				if v1.mainsnak.datavalue.value.id == propvalue and v1.qualifiers then
					if onlysrc == false or sourced(v1) then
						local quals = v1.qualifiers[qualifierID]
						if quals then
							local qargs = frame.args
							qargs.onlysourced = "no"
							local vals = propertyvalueandquals(quals, qargs, qid)
							for k, v in ipairs(vals) do
								out[#out + 1] = v
							end
						end
					end
				end
			end
		end
		return assembleoutput(out, frame.args, qid, propertyID)
	else
		return props
	end
	return nil
end

p.getSumOfParts = function(frame)
	local sum = _getsumofparts(frame.args)
	if sum == 0 then return end
	return sum
end

p.getValueByQual = function(frame)
	local qualID = frame.args.qualID
	local qval = frame.args.qvalue or ""
	if qval == "" then return "no qualifier value supplied" end
	local function checkQID(id)
		return id == qval
	end
	return _getvaluebyqual(frame, qualID, checkQID)
end

p.getValueByLang = function(frame)
	local langcode = findLang(frame.args.lang).code
	local function checkLanguage(id)
		local qlcode = mw.wikibase.getBestStatements(id, "P329")
		if (#qlcode > 0) and (qlcode[1].mainsnak.datavalue.value == langcode) then
			return true
		end
	end
	return _getvaluebyqual(frame, "P44", checkLanguage)
end

p.getValueByRefSource = function(frame)
	local propertyID = mw.text.trim(frame.args[1] or ""):upper()
	if propertyID == "" then return "no property supplied" end

	local qval = (frame.args.match or ""):upper()
	if qval == "" then qval = "Q21540096" end

	local unit = (frame.args.unit or ""):upper()
	if unit == "" then unit = "Q1058" end

	local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true)

	frame.args.reqranks = setRanks(frame.args.rank)

	frame.args.langobj = findLang(frame.args.lang)
	frame.args.lang = frame.args.langobj.code

	local linked = parseParam(frame.args.linked, true)

	local uabbr = parseParam(frame.args.uabbr or frame.args.unitabbr, false)

	local qid, props = parseInput(frame, frame.args[2], propertyID)

	if qid then
		local out = {}
		local mlt= {}
		for k1, v1 in ipairs(props) do
			if onlysrc == false or sourced(v1) then
				if v1.references then
					for k2, v2 in ipairs(v1.references) do
						if v2.snaks.P15 then
							for k3, v3 in ipairs(v2.snaks.P15) do
								if v3.datavalue.value.id == qval then
									out[#out+1], mlt[#out+1] = rendersnak(v1, frame.args, linked, "", "", "", "", uabbr, unit)
									if not mlt[#out] then
										break
									end
								end
							end
						end
					end
				end
			end
		end
		if #mlt > 0 then
			local langcode = frame.args.lang
			langcode = mw.text.split( langcode, '-', true )[1]
			local fbtbl = mw.language.getFallbacksFor( langcode )
			table.insert( fbtbl, 1, langcode )
			local bestval = ""
			local found = false
			for idx1, lang1 in ipairs(fbtbl) do
				for idx2, lang2 in ipairs(mlt) do
					if (lang1 == lang2) and not found then
						bestval = out[idx2]
						found = true
						break
					end
				end
			end
			if found then
				out = { bestval }
			else
				out = { out[1] }
			end
		end
		return assembleoutput(out, frame.args, qid, propertyID)
	else
		return props
	end
end

p.getPropertyIDs = function(frame)
	local args = frame.args
	args.reqranks = setRanks(args.rank)
	args.langobj = findLang(args.lang)
	args.lang = args.langobj.code
	args.noicon = tostring(parseParam(args.noicon or "", true))
	local f = {}
	f.args = args
	local pid = mw.text.trim(args[1] or ""):upper()

	local qid, props = parseInput(f, args[2], pid)
	if not qid then return props end
	if not props[1] then return nil end
	local onlysrc = parseParam(args.onlysourced or args.osd, true)
	local maxvals = tonumber(args.maxvals) or 0

	out = {}
	for i, v in ipairs(props) do
		local snak = v.mainsnak
		if ( snak.datatype == "wikibase-item" )
			and ( v.rank and args.reqranks[v.rank:sub(1, 1)] )
			and ( snak.snaktype == "value" )
			and ( sourced(v) or not onlysrc )
			then
			out[#out+1] = snak.datavalue.value.id
		end
		if maxvals > 0 and #out >= maxvals then break end
	end

	return assembleoutput(out, args, qid, pid)
end

p.getQualifierIDs = function(frame)
	local args = frame.args
	args.reqranks = setRanks(args.rank)
	args.langobj = findLang(args.lang)
	args.lang = args.langobj.code
	args.noicon = tostring(parseParam(args.noicon or "", true))
	local f = {}
	f.args = args
	local pid = mw.text.trim(args[1] or ""):upper()

	local qid, props = parseInput(f, args[2], pid)
	if not qid then return props end
	if not props[1] then return nil end
	local onlysrc = parseParam(args.onlysourced or args.osd, true)
	local maxvals = tonumber(args.maxvals) or 0
	local qlist = args.qlist or ""
	if qlist == "" then qlist = "ALL" end
	qlist = qlist:gsub("[%p%s]+", " ") .. " "

	out = {}
	for i, v in ipairs(props) do
		local snak = v.mainsnak
		if ( v.rank and args.reqranks[v.rank:sub(1, 1)] )
			and ( snak.snaktype == "value" )
			and ( sourced(v) or not onlysrc )
			then
			if v.qualifiers then
				for k1, v1 in pairs(v.qualifiers) do
					if qlist == "ALL " or qlist:match(k1 .. " ") then
						for i2, v2 in ipairs(v1) do
							if v2.datatype == "wikibase-item" and v2.snaktype == "value" then
								out[#out+1] = v2.datavalue.value.id
							end
						end
					end
				end
			end
		end
		if maxvals > 0 and #out >= maxvals then break end
	end

	return assembleoutput(out, args, qid, pid)
end

p._getPropOfProp = function(args)
	local paraset = tonumber(args.ps or args.parameterset or 0)
	if paraset == 1 then
		args.rank = "best"
		args.fetchpornbasedata = "ALL"
		args.onlysourced = "no"
		args.noicon = "true"
	elseif paraset == 2 then
		args.rank = "best"
		args.fetchpornbasedata = "ALL"
		args.onlysourced = "no"
		args.noicon = "true"
		args.linked = "no"
		args.pd = "true"
	elseif paraset == 3 then
	end

	args.reqranks = setRanks(args.rank)
	args.langobj = findLang(args.lang)
	args.lang = args.langobj.code
	local pid1 = args.prop1 or args.pid1 or ""
	local pid2 = args.prop2 or args.pid2 or ""
	local localval = mw.text.trim(args[1] or "")
	if pid1 == "" or pid2 == "" then return nil end

	local f = {}
	f.args = args
	local qid1, statements1 = parseInput(f, localval, pid1)
	if not qid1 then return localval end

	local onlysrc = parseParam(args.onlysourced or args.osd, true)
	local maxvals = tonumber(args.maxvals) or 0
	local qualID = mw.text.trim(args.qual or ""):upper()
	if qualID == "" then qualID = nil end
	local out = {}
	for k, v in ipairs(statements1) do
		if not onlysrc or sourced(v) then
			local snak = v.mainsnak
			if snak.datatype == "wikibase-item" and snak.snaktype == "value" then
				local qid2 = snak.datavalue.value.id
				local statements2 = {}
				if args.reqranks.b then
					statements2 = mw.wikibase.getBestStatements(qid2, pid2)
				else
					statements2 = mw.wikibase.getAllStatements(qid2, pid2)
				end
				if statements2[1] then
					local out2 = propertyvalueandquals(statements2, args, qualID)
					out[#out+1] = assembleoutput(out2, args, qid2, pid2)
				end
			end
		end
		if maxvals > 0 and #out >= maxvals then break end
	end
	return assembleoutput(out, args, qid1, pid1)
end

p.getPropOfProp = function(frame)
	local args= frame.args
	if not args.prop1 and not args.pid1 then
		args = frame:getParent().args
		if not args.prop1 and not args.pid1 then return i18n.errors["No property supplied"] end
	end

	return p._getPropOfProp(args)
end

p.getAwardCat = function(frame)
	frame.args.reqranks = setRanks(frame.args.rank)
	frame.args.langobj = findLang(frame.args.lang)
	frame.args.lang = frame.args.langobj.code
	local args = frame.args
	args.sep = " "
	local pid1 = args.prop1 or "P206"
	local pid2 = args.prop2 or "P207"
	if pid1 == "" or pid2 == "" then return nil end
	local localval = mw.text.trim(args[1] or "")
	local qid1, statements1 = parseInput(frame, localval, pid1)
	if not qid1 then return localval end
	local lp = (args.linkprefix or args.lp or ""):gsub('"', '')
	local sk = (args.sortkey or args.sk or ""):gsub('["-.]', '')
	local famname = ""
	if sk == "" then
		local p186 = mw.wikibase.getBestStatements(qid1, "P186")[1]
		local p186id = p186 and p186.mainsnak.snaktype == "value" and p186.mainsnak.datavalue.value.id or ""
		famname = mw.wikibase.getSitelink(p186id) or ""
		local pos = famname:find(":") or 0
		famname = famname:sub(pos+1):gsub("%s%(.+%)$", "")
		if famname == "" then
			local lbl = mw.wikibase.getLabel(p186id)
			famname = lbl and mw.text.nowiki(lbl) or ""
		end
	end
	local onlysrc = parseParam(args.onlysourced or args.osd, true)
	local maxvals = tonumber(args.maxvals) or 0
	local qualID = mw.text.trim(args.qual or ""):upper()
	if qualID == "" then qualID = nil end
	local out = {}
	for k, v in ipairs(statements1) do
		if not onlysrc or sourced(v) then
			local snak = v.mainsnak
			if snak.datatype == "wikibase-item" and snak.snaktype == "value" then
				local qid2 = snak.datavalue.value.id
				local statements2 = {}
				if args.reqranks.b then
					statements2 = mw.wikibase.getBestStatements(qid2, pid2)
				else
					statements2 = mw.wikibase.getAllStatements(qid2, pid2)
				end
				if statements2[1] and statements2[1].mainsnak.snaktype == "value" then
					local qid3 = statements2[1].mainsnak.datavalue.value.id
					local sitelink = mw.wikibase.getSitelink(qid3)
					if not sitelink then
						local lbl = mw.wikibase.getLabelByLang(qid3, "pbc")
						if lbl then
							if lbl:sub(1,9) == "Category:" then
								sitelink = mw.text.nowiki(lbl)
							else
								sitelink = "Category:" .. mw.text.nowiki(lbl)
							end
						end
					end
					if sitelink then
						if sk ~= "" then
							out[#out+1] = "[[" .. lp .. sitelink .. "|" .. sk .. "]]"
						elseif famname ~= "" then
							out[#out+1] = "[[" .. lp .. sitelink .. "|" .. famname .. "]]"
						else
							out[#out+1] = "[[" .. lp .. sitelink .. "]]"
						end
					end
				end
			end
		end
		if maxvals > 0 and #out >= maxvals then break end
	end
	return assembleoutput(out, args, qid1, pid1)
end

p.getIntersectCat = function(frame)
	frame.args.reqranks = setRanks(frame.args.rank)
	frame.args.langobj = findLang(frame.args.lang)
	frame.args.lang = frame.args.langobj.code
	local args = frame.args
	args.sep = " "
	args.linked = "no"
	local pid1 = args.prop1 or "P124"
	local pid2 = args.prop2 or "P133"
	if pid1 == "" or pid2 == "" then return nil end
	local qid, statements1 = parseInput(frame, "", pid1)
	if not qid then return nil end
	local qid, statements2 = parseInput(frame, "", pid2)
	if not qid then return nil end
	local subs_exists, subs = pcall(mw.loadData, "Module:PornBaseDataIB/subs")
	local join = args.join or ""
	local onlysrc = parseParam(args.onlysourced or args.osd, true)
	local maxvals = tonumber(args.maxvals) or 0
	local lp = (args.linkprefix or args.lp or ""):gsub('"', '')
	local sk = (args.sortkey or args.sk or ""):gsub('["-.]', '')
	local famname = ""
	if sk == "" then
		local p186 = mw.wikibase.getBestStatements(qid, "P186")[1]
		local p186id = p186 and p186.mainsnak.snaktype == "value" and p186.mainsnak.datavalue.value.id or ""
		famname = mw.wikibase.getSitelink(p186id) or ""
		local pos = famname:find(":") or 0
		famname = famname:sub(pos+1):gsub("%s%(.+%)$", "")
		if famname == "" then
			local lbl = mw.wikibase.getLabel(p186id)
			famname = lbl and mw.text.nowiki(lbl) or ""
		end
	end
	local cat1 = {}
	for k, v in ipairs(statements1) do
		if not onlysrc or sourced(v) then
			local pvalID = (v.mainsnak.snaktype == "value") and v.mainsnak.datavalue.value.id
			if pvalID then
				local p50 = mw.wikibase.getBestStatements(pvalID, "P50")[1]
				if p50 and p50.mainsnak.snaktype == "value" then
					local tmcID = p50.mainsnak.datavalue.value.id
					local cat = mw.wikibase.getSitelink(tmcID)
					if not cat then
						local lbl = mw.wikibase.getLabelByLang(tmcID, "pbc")
						if lbl then
							if lbl:sub(1,9) == "Category:" then
								cat = mw.text.nowiki(lbl)
							else
								cat = "Category:" .. mw.text.nowiki(lbl)
							end
						end
					end
					cat1[#cat1+1] = cat
				end
			end
		end
		if maxvals > 0 and #cat1 >= maxvals then break end
	end
	local cat2 = {}
	for k, v in ipairs(statements2) do
		if not onlysrc or sourced(v) then
			local cat = rendersnak(v, args)
			if subs[cat] then cat = subs[cat] end
			cat2[#cat2+1] = cat
		end
		if maxvals > 0 and #cat2 >= maxvals then break end
	end
	out = {}
	for k1, v1 in ipairs(cat1) do
		for k2, v2 in ipairs(cat2) do
			if sk ~= "" then
				out[#out+1] = "[[" .. lp .. v1 .. " " .. join .. " " .. v2 .. "|" .. sk .. "]]"
			elseif famname ~= "" then
				out[#out+1] = "[[" .. lp .. v1 .. " " .. join .. " " .. v2 .. "|" .. famname .. "]]"
			else
				out[#out+1] = "[[" .. lp .. v1 .. " " .. join .. " " .. v2 .. "]]"
			end
		end
	end
	args.noicon = "true"
	return assembleoutput(out, args, qid, pid1)
end

p.qualsToTable = function(frame)
	local args = frame.args

	local quals = args.quals or ""
	if quals == "" then return "" end

	args.reqranks = setRanks(args.rank)

	local propertyID = mw.text.trim(args[1] or "")
	local f = {}
	f.args = args
	local entityid, props = parseInput(f, "", propertyID)
	if not entityid then return "" end

	args.langobj = findLang(args.lang)
	args.lang = args.langobj.code

	local pval = args.pval or ""

	local qplist = mw.text.split(quals, "%p")
	for i, v in ipairs(qplist) do
		qplist[i] = mw.text.trim(v):upper()
	end

	local col1 = args.firstcol or ""
	if col1 ~= "" then
		col1 = col1 .. "</td><td>"
	end

	local emptycell = args.emptycell or "&nbsp;"

	local qvals = {}
	for i, v in ipairs(props) do
		local skip = false
		if pval ~= "" then
			local pid = v.mainsnak.datavalue and v.mainsnak.datavalue.value.id
			if pid ~= pval then skip = true end
		end
		if not skip then
			local qval = {}
			local vqualifiers = v.qualifiers or {}
			for i1, v1 in ipairs(qplist) do
				local qv, qtype
				if vqualifiers[v1] then
					qtype = vqualifiers[v1][1].datatype
					if qtype == "time" then
						if vqualifiers[v1][1].snaktype == "value" then
							qv = mw.wikibase.renderSnak(vqualifiers[v1][1])
							qv = frame:expandTemplate{title="dts", args={qv}}
						else
							qv = "?"
						end
					elseif qtype == "url" then
						if vqualifiers[v1][1].snaktype == "value" then
							qv = mw.wikibase.renderSnak(vqualifiers[v1][1])
							local display = mw.ustring.match( mw.uri.decode(qv, "WIKI"), "([%w ]+)$" )
							if display then
								qv = "[" .. qv .. " " .. display .. "]"
							end
						end
					else
						qv = mw.wikibase.formatValue(vqualifiers[v1][1])
					end
				end
				qval[i1] = qv or emptycell
			end
			qvals[#qvals+1] = qval
		end
	end

	local out = {}
	for i, v in ipairs(qvals) do
		out[i] = "<tr><td>" .. col1 .. table.concat(qvals[i], "</td><td>") .. "</td></tr>"
	end
	return table.concat(out, "\n")
end

p.getGlobe = function(frame)
	local qid = frame.args.qid or frame.args[1] or ""
	if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	local coords = mw.wikibase.getBestStatements(qid, "P48")[1]
	local globeid
	if coords and coords.mainsnak.snaktype == "value" then
		globeid = coords.mainsnak.datavalue.value.globe:match("(Q%d+)")
	end
	return globeid
end

p.getCommonsLink = function(frame)
	local oc = frame.args.onlycat or frame.args.onlycategories
	local fb = parseParam(frame.args.fallback or frame.args.fb, true)
	return _getCommonslink(frame.args.qid, oc, fb)
end

p.getSiteLink = function(frame)
	return _getSitelink(frame.args.qid, frame.args.wiki or mw.text.trim(frame.args[1] or ""))
end

p.getLink = function(frame)
	local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "")
	if itemID == "" then return end
	local sitelink = mw.wikibase.getSitelink(itemID)
	local label = labelOrId(itemID)
	if sitelink then
		return "[[:" .. sitelink .. "|" .. label .. "]]"
	else
		return label
	end
end

p.getLabel = function(frame)
	local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "")
	if itemID == "" then return end
	local lang = frame.args.lang or ""
	if lang == "" then lang = nil end
	local label = labelOrId(itemID, lang)
	return label
end

p.label = function(frame)
	local qid = mw.text.trim(frame.args[1] or frame.args.qid or "")
	if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return end
	local lang = frame.args.lang or ""
	if lang == "" then lang = nil end
	local label, success = labelOrId(qid, lang)
	if success then return label end
end

p.getAT = function(frame)
	local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "")
	if itemID == "" then return end
	return mw.wikibase.getSitelink(itemID)
end

p.getDescription = function(frame)
	local desc = mw.text.trim(frame.args[1] or "")
	local itemID = mw.text.trim(frame.args.qid or "")
	if itemID == "" then itemID = nil end
	if desc:lower() == 'pornbasedata' then
		return mw.wikibase.getDescription(itemID)
	elseif desc:lower() == 'none' then
		return nil
	else
		return desc
	end
end

p.getAliases = function(frame)
	local args = frame.args

	local fieldname = args.name or ""
	if fieldname == "" then fieldname = "alias" end

	local blacklist = args.suppressfields or args.spf or ""
	if blacklist:find(fieldname) then return nil end

	local localval = mw.text.trim(args[1] or "")
	if localval ~= "" then return localval end

	local whitelist = args.fetchpornbasedata or args.fpbd or ""
	if whitelist == "" then whitelist = "NONE" end
	if not (whitelist == 'ALL' or whitelist:find(fieldname)) then return nil end

	local qid = mw.text.trim(args.qid or "")
	if qid == "" then qid = nil end

	local entity = mw.wikibase.getEntity(qid)
	if not entity then return nil end
	local aliases = entity.aliases
	if not aliases then return nil end
	if not qid then qid= mw.wikibase.getEntityIdForCurrentPage() end

	args.langobj = findLang(args.lang)
	local langcode = args.langobj.code
	args.lang = langcode

	local out = {}
	for k1, v1 in pairs(aliases) do
		if v1[1].language == langcode then
			for k1, v2 in ipairs(v1) do
				out[#out+1] = v2.value
			end
			break
		end
	end

	return assembleoutput(out, args, qid)
end

p.pageId = function(frame)
	return mw.wikibase.getEntityIdForCurrentPage()
end

p.formatDate = function(frame)
	return format_Date(frame.args[1], frame.args.df, frame.args.bc)
end

p.getImageLegend = function(frame)
	local id = frame.args.id
	if id and (#id == 0) then
		id = nil
	end

	local lang = frame.args.lang
	if (not lang) or (#lang < 2) then
		lang = mw.language.getContentLanguage().code
	end

	local input_parm = mw.text.trim(frame.args[1] or "")
	if input_parm == "FETCH_WIKIDATA" then
		local ent = mw.wikibase.getEntity(id)
		local imgs
		if ent and ent.claims then
			imgs = ent.claims.P470
		end
		local imglbl
		if imgs then
			for k1, v1 in pairs(imgs) do
				if v1.rank == "preferred" and v1.qualifiers and v1.qualifiers.P523 then
					local imglbls = v1.qualifiers.P523
					for k2, v2 in pairs(imglbls) do
						if v2.datavalue.value.language == lang then
							imglbl = v2.datavalue.value.text
							break
						end
					end
				end
			end
			if (not imglbl) then
				for k1, v1 in pairs(imgs) do
					if v1.rank == "normal" and v1.qualifiers and v1.qualifiers.P523 then
						local imglbls = v1.qualifiers.P523
						for k2, v2 in pairs(imglbls) do
							if v2.datavalue.value.language == lang then
								imglbl = v2.datavalue.value.text
								break
							end
						end
					end
				end
			end
		end
		return imglbl
	else
		return input_parm
	end
end

p.location = function(frame)
	local debug = (frame.args.debug or ""):sub(1, 1):lower()
	if debug == "" then debug = "n" end
	local qid = mw.text.trim(frame.args.qid or frame.args[1] or ""):upper()
	if qid == "" then qid=mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then
		if debug ~= "n" then
			return i18n.errors["entity-not-found"]
		else
			return nil
		end
	end
	local first = mw.text.trim(frame.args.first or "")
	local skip = mw.text.trim(frame.args.skip or "")
	return table.concat( _location(qid, first, skip), ", " )
end

p.checkBlacklist = function(frame)
	local blacklist = frame.args.suppressfields or frame.args.spf or ""
	local fieldname = frame.args.name or ""
	if blacklist ~= "" and fieldname ~= "" then
		if blacklist:find(fieldname) then
			return false
		else
			return true
		end
	else
		return true
	end
end

p.emptyor = function(frame)
	local s = frame.args[1] or ""
	if s == "" then return nil end
	local sx = s:gsub("%s", ""):gsub("<[^>]*>", ""):gsub("%p", "")
	if sx == "" then
		return nil
	else
		return s
	end
end

p.labelorid = function(frame)
	return (labelOrId(frame.args.qid or frame.args[1]))
end

p.getLang = function(frame)
	local style = (frame.args.style or ""):lower()
	local langcode = mw.language.getContentLanguage().code
	if style == "full" then
		return mw.language.fetchLanguageName( langcode )
	end
	return langcode
end

p.getItemLangCode = function(frame)
	return _getItemLangCode(frame.args.qid or frame.args[1])
end

p.findLanguage = function(frame)
	return findLang(frame.args.lang or frame.args[1]).code
end

p.getQid = function(frame)
	local qid = (frame.args.qid or ""):upper()
	if qid ~= "" then return qid end
	qid = mw.wikibase.getEntityIdForCurrentPage()
	if qid then
		local prop521 = mw.wikibase.getBestStatements(qid, "P521")
		if prop521[1] then
			local mctid = prop521[1].mainsnak.datavalue.value.id
			if mctid then return mctid end
		end
	end
	return qid
end

p._followQid = function(args)
	local qid = (args.qid or ""):upper()
	local all = parseParam(args.all, false)
	if qid == "" then
		qid = mw.wikibase.getEntityIdForCurrentPage()
	end
	if not qid then return nil end
	local out = {}
	local props = (args.props or ""):upper()
	if props ~= "" then
		for p in mw.text.gsplit(props, "%p") do
			p = mw.text.trim(p)
			for i, v in ipairs( mw.wikibase.getBestStatements(qid, p) ) do
				local linkedid = v.mainsnak.datavalue and v.mainsnak.datavalue.value.id
				if linkedid then
					if all then
						out[#out+1] = linkedid
					else
						return linkedid
					end
				end
			end
		end
	end
	if #out > 0 then
		return table.concat(out, " ")
	else
		return qid
	end
end

p.followQid = function(frame)
	return p._followQid(frame.args)
end

p.globalSiteID = function(frame)
	return mw.wikibase.getGlobalSiteId()
end

p.siteID = function(frame)
	local txtlang = frame:preprocess( "{{int:lang}}" ) or ""
	if txtlang == "be-tarask" then
		return "be_x_old"
	end
	local pos = txtlang:find("-")
	local ret = ""
	if pos then
		ret = txtlang:sub(1, pos-1)
	else
		ret = txtlang
	end
	return ret
end

p.projID = function(frame)
	local txtlang = frame:preprocess( "{{int:lang}}" ) or ""
	if txtlang == "be-tarask" then
		return "be-x-old"
	end
	local pos = txtlang:find("-")
	local ret = ""
	if pos then
		ret = txtlang:sub(1, pos-1)
	else
		ret = txtlang
	end
	return ret
end

p.formatNumber = function(frame)
	local lang
	local num = tonumber(frame.args[1] or frame.args.num) or 0
	lang = findLang(frame.args.lang)
	return lang:formatNum( num )
end

p.examine = function( frame )
	local args
	if frame.args[1] or frame.args.pid or frame.args.qid then
		args = frame.args
	else
		args = frame:getParent().args
	end
	local par = {}
	local pid = (args.pid or ""):upper()
	local qid = (args.qid or ""):upper()
	par[1] = mw.text.trim( args[1] or "" ):upper()
	par[2] = mw.text.trim( args[2] or "" ):upper()
	table.sort(par)
	if par[2]:sub(1,1) == "P" then par[1], par[2] = par[2], par[1] end
	if pid == "" then pid = par[1] end
	if qid == "" then qid = par[2] end
	local q1 = qid:sub(1,1)
	if pid:sub(1,1) ~= "P" then return "No property supplied" end
	if q1 ~= "Q" and q1 ~= "M" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return "No item for this page" end
	return "<pre>" .. mw.dumpObject( mw.wikibase.getAllStatements( qid, pid ) ) .. "</pre>"
end

p.checkvalue = function( frame )
	local args
	if frame.args.val then
		args = frame.args
	else
		args = frame:getParent().args
	end
	local val = args.val
	if not val then return nil end
	local pid = mw.text.trim(args.pid or args[1] or "P1"):upper()
	local qid = (args.qid or ""):upper()
	if pid:sub(1,1) ~= "P" then return nil end
	if qid:sub(1,1) ~= "Q" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return nil end
	ranks = setRanks(args.rank)
	local stats = {}
	if ranks.b then
		stats = mw.wikibase.getBestStatements(qid, pid)
	else
		stats = mw.wikibase.getAllStatements( qid, pid )
	end
	if not stats[1] then return nil end
	if stats[1].mainsnak.datatype == "wikibase-item" then
		for k, v in pairs( stats ) do
			ms = v.mainsnak
			if ranks[v.rank:sub(1,1)] and ms.snaktype == "value" and ms.datavalue.value.id == val then
				return val
			end
		end
	end
	return nil
end

p.url2 = function(frame)
	local txt = frame.args.url or ""
	if txt == "" then return nil end
	local url, icon = txt:match("(.+)&nbsp;(.+)")
	url = url or txt
	icon = icon or ""
	local prot, addr = url:match("(http[s]*://)(.+)")
	prot = prot or url
	addr = addr or ""
	local disp, n = addr:gsub( "^([^/]+)/$", "%1" ):gsub("%/", "<wbr/>/"):gsub("%.", "<wbr/>.")
	return '<span class="url">[' .. prot .. addr .. " " .. disp .. "]</span>&nbsp;" .. icon
end

p.getWebsite = function(frame)
	local url = frame.args.url or ""
	if url:upper() == "NONE" then return nil end

	local qid = frame.args.qid or ""
	if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return nil end

	local urls = {}
	local quals = {}
	if url == "" then
		local prop52 = mw.wikibase.getBestStatements(qid, "P52")
		for k, v in pairs(prop52) do
			if v.mainsnak.snaktype == "value" then
				urls[#urls+1] = v.mainsnak.datavalue.value
				if v.qualifiers and v.qualifiers["P208"] then
					local au = v.qualifiers["P208"][1]
					if au.snaktype == "value" then
						quals[#urls] = au.datavalue.value
					end
				end
			end
		end
	else
		urls[1] = url
	end
	if #urls == 0 then return nil end

	local out = {}
	for i, u in ipairs(urls) do
		local link = quals[i] or u
		local prot, addr = u:match("(http[s]*://)(.+)")
		addr = addr or u
		local disp, n = addr:gsub("%.", "<wbr/>%.")
		out[#out+1] = '<span class="url">[' .. link .. " " .. disp .. "]</span>"
	end

	local langcode = findLang(frame.args.lang).code
	local noicon = parseParam(frame.args.noicon, false)
	if url == "" and not noicon then
		out[#out] = out[#out] .. createicon(langcode, qid, "P52")
	end

	local ret = ""
	if #out > 1 then
		ret = mw.getCurrentFrame():expandTemplate{title = "ubl", args = out}
	else
		ret = out[1]
	end

	return ret
end

p.getAllLabels = function(frame)
	local args = frame.args or frame:getParent().args or {}

	local qid = args.qid
	if qid == "" then qid = nil end

	local entity = mw.wikibase.getEntity(qid)
	if not entity then return i18n["entity-not-found"] end

	local labels = entity.labels
	if not labels then return i18n["labels-not-found"] end

	local out = {}
	for k, v in pairs(labels) do
		out[#out+1] = v.value .. " (" .. v.language .. ")"
	end

	return table.concat(out, "; ")
end

p.getAllDescriptions = function(frame)
	local args = frame.args or frame:getParent().args or {}

	local qid = args.qid
	if qid == "" then qid = nil end

	local entity = mw.wikibase.getEntity(qid)
	if not entity then return i18n["entity-not-found"] end

	local descriptions = entity.descriptions
	if not descriptions then return i18n["descriptions-not-found"] end

	local out = {}
	for k, v in pairs(descriptions) do
		out[#out+1] = v.value .. " (" .. v.language .. ")"
	end

	return table.concat(out, "; ")
end

p.getAllAliases = function(frame)
	local args = frame.args or frame:getParent().args or {}

	local qid = args.qid
	if qid == "" then qid = nil end

	local entity = mw.wikibase.getEntity(qid)
	if not entity then return i18n["entity-not-found"] end

	local aliases = entity.aliases
	if not aliases then return i18n["aliases-not-found"] end

	local out = {}
	for k1, v1 in pairs(aliases) do
		local lang = v1[1].language
		local val = {}
		for k1, v2 in ipairs(v1) do
			val[#val+1] = v2.value
		end
		out[#out+1] = table.concat(val, ", ") .. " (" .. lang .. ")"
	end

	return table.concat(out, "; ")
end

p.showNoLinks = function(frame)
	local out = {}
	for k, v in pairs(donotlink) do
		out[#out+1] = k
	end
	table.sort( out )
	return table.concat(out, "; ")
end

function p.checkValidity(frame)
	local id = mw.text.trim(frame.args[1] or "")
	if mw.wikibase.isValidEntityId(id) then
		return true
	else
		return false
	end
end

function p.getEntityFromTitle(frame)
	local args=frame.args
	if not args[1] then args=frame:getParent().args end
	if not args[1] then return nil end
	local title = mw.text.trim(args[1])
	local site = args.site or ""
	local showdab = parseParam(args.showdab, true)
	qid = mw.wikibase.getEntityIdForTitle(title, site)
	if qid then
		local prop1 = mw.wikibase.getBestStatements(qid, "P1")[1]
		if not showdab and prop1 and prop1.mainsnak.datavalue.value.id == "Q220" then
			return nil
		else
			return qid
		end
	end
end

function p.getDatePrecision(frame)
	local args=frame.args
	if not args[1] then args=frame:getParent().args end
	local default = tonumber(args[2] or args.default) or 0
	local prop = mw.text.trim(args[1] or "")
	if prop == "" then return default end
	local qid = args.qid or ""
	if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
	if not qid then return default end
	local onlysrc = parseParam(args.onlysourced or args.osd, true)
	local stat = mw.wikibase.getBestStatements(qid, prop)
	for i, v in ipairs(stat) do
		local prec = (onlysrc == false or sourced(v))
			and v.mainsnak.datavalue
			and v.mainsnak.datavalue.value
			and v.mainsnak.datavalue.value.precision
		if prec then return prec end
	end
	return default
end


return p