------------------------------------------------------------------------------
-- module local variables and functions copied from Module:Wikidata

local function printError(code)
	return '<span class="error">' .. (i18n.errors[code] or code) .. '</span>'
end

local function printDatavalueEntity(data, parameter)
	-- data fields: entity-type [string], numeric-id [int, Wikidata id]
	local id
	
	if data["entity-type"] == "item" then id = "Q" .. data["numeric-id"]
	elseif data["entity-type"] == "property" then id = "P" .. data["numeric-id"]
	else return printError("unknown-entity-type")
	end
	
	if parameter then
		if parameter == "link" then
			local linkTarget = mw.wikibase.sitelink(id)
			local linkName = mw.wikibase.label(id)
			if linkTarget then
				-- if there is a local Wikipedia article link to it using the label or the article title
				return "[[" .. linkTarget  .. "|" .. (linkName or linkTarget) .. "]]"
			else
				-- if there is no local Wikipedia article output the label or link to the Wikidata object to let the user input a proper label
				if linkName then return linkName else return "[[:d:" .. id .. "|" .. id .. "]]" end
			end
		else
			return data[parameter]
		end
	else
		return mw.wikibase.label(id) or id
	end
end

local function getSnakValue(snak, parameter)
	if snak.snaktype == "value" then
		-- call the respective snak parser
		if snak.datavalue.type == "string" then return snak.datavalue.value
		elseif snak.datavalue.type == "wikibase-entityid" then return printDatavalueEntity(snak.datavalue.value, parameter)
		end
	end
	return mw.wikibase.renderSnak(snak)
end
 
local function getQualifierSnak(claim, qualifierId)
	-- a "snak" is Wikidata terminology for a typed key/value pair
	-- a claim consists of a main snak holding the main information of this claim,
	-- as well as a list of attribute snaks and a list of references snaks
	if qualifierId then
		-- search the attribute snak with the given qualifier as key
		if claim.qualifiers then
			local qualifier = claim.qualifiers[qualifierId]
			if qualifier then return qualifier[1] end
		end
		return nil, printError("qualifier-not-found")
	else
		-- otherwise return the main snak
		return claim.mainsnak
	end
end
 
local function getValueOfClaim(claim, qualifierId, parameter)
	local error
	local snak
	snak, error = getQualifierSnak(claim, qualifierId)
	if snak then
		return getSnakValue(snak, parameter)
	else
		return nil, error
	end
end

------------------------------------------------------------------------------
-- module local variables and functions derived from Module:Wikidata but customized

local function getValue(claims, sortindices, frame)
	local qualifierId = frame.args["qualifier"]
	local parameter = frame.args["parameter"]
	local list = frame.args["list"]
	local references = frame.args["references"]
	local showerrors = frame.args["showerrors"]
	local showerrors = true
	
	local result
	local error
	if list then
		local value
		-- iterate over all elements and return their value (if existing)
		result = {}
		for idx in pairs(claims) do
			local claim = claims[sortindices[idx]]
			value, error =  getValueOfClaim(claim, qualifierId, parameter)
			if not value and showerrors then value = error end
			if value and references then value = value .. getReferences(frame, claim) end
			result[#result + 1] = value
		end
		result = table.concat(result, list)
	else
		-- return first element	
		local claim = claims[sortindices[1]]
		result, error = getValueOfClaim(claim, qualifierId, parameter)
		if result and references then result = result .. getReferences(frame, claim) end
	end
	return result
end

------------------------------------------------------------------------------
-- module export functions

local p = {}

function p.getPreferredOfficeholder(frame)
	local id = frame.args["id"]	-- "id" should be nil
	local showerrors = frame.args["showerrors"]
	local default = frame.args["default"]
	if default then showerrors = nil end
	local showerrors = true
	
	local entity = mw.wikibase.getEntity(id)
	local claims = entity['claims']['P1308']
	
	-- get initial sort indices
	local sortindices = {}
	for idx in pairs(claims) do
		sortindices[#sortindices + 1] = idx
	end
	-- sort by claim rank
	local comparator = function(a, b)
		local rankmap = { deprecated = 2, normal = 1, preferred = 0 }
		local ranka = rankmap[claims[a].rank or "normal"]
		local rankb = rankmap[claims[b].rank or "normal"]
		return ranka < rankb
 	end
	table.sort(sortindices, comparator)
	
	result = getValue(claims, sortindices, frame)
 
	if result then return result else
		if showerrors then return error else return default end
	end
end

function p.getPreferredOfficeholderLink(frame)
	frame.args["parameter"] = "link"
	return p.getPreferredOfficeholder(frame)
end

function p.getPreferredOfficeholderStarttime(frame)
	frame.args["qualifier"] = "P580"
	return p.getPreferredOfficeholder(frame)
end

function p.getPreferredOfficeholderCountry(frame)
	frame.args["qualifier"] = "P17"
	return p.getPreferredOfficeholder(frame)
end

function p.getPreferredOfficeholderCountryLink(frame)
	frame.args["parameter"] = "link"
	return p.getPreferredOfficeholderCountry(frame)
end

return p