local p = {}
local defaultlang = mw.getCurrentFrame():callParserFunction("int", "lang")
local defaultlinktype = {'commonswiki', 'wikipedia'} -- sites accepted for internal links
local fb = require "Module:Fallback"
local tools = require 'Module:Wikidata/Tools'
local getClaims = require "Module:Wikidata/GetClaims".getClaims
local i18n = tools.i18n

local formatError = tools.formatError

local function fblist(lang)
	return fb.fblist(lang or defaultlang)
end

function p.getLabel(entity, lang, labelformat)
	if (not entity) or (entity == "") then
		return nil -- error handling ?
	end
	if (not lang) or (lang == "") then
		lang = defaultlang
	end
	if type(labelformat) == 'function' then
		return labelformat(entity)
	end
	
--[[ using mw.wikibase.label (much more memory efficient) but
	* incompatible with ?uselang
	* useful only when the Wikidata entity is not loaded, so useless when a Wikipedia link is required
	if (type(entity) == 'string') and (lang == defaultlang) then -- much more memory efficient
		return mw.wikibase.label(entity)
	end
]]--
	if type(entity) == 'string' then
		entity = mw.wikibase.getEntityObject(entity)
	end
	if entity and entity.labels then
		for i, lg in pairs(fblist(lang)) do
			if entity.labels[lg] then
				return entity.labels[lg].value
			end
		end
	end
end

function p.formatEntity( entity, params )

	-- UNFOLD PARAMETERS
	if (not entity) or (entity == "") then
		return nil --formatError('entity-not-found')
	end
	local id = entity
	if type(id) == 'table' then
		id = id.id
	end
	params = params or {}
	local lang = params.lang or defaultlang
	local speciallabels = params.speciallabels
	local displayformat = params.displayformat
	local labelformat = params.labelformat
	local defaultlabel = params.defaultlabel or id
	local linktype = params.link or defaultlinktype
	local defaultlinktype = params.defaultlink
	local defaultlinkquery = params.defaultlinkquery

	if speciallabels and speciallabels[id] then --speciallabels override the standard label + link combination
		return speciallabels[id]
	end
	if params.displayformat == 'raw' then
		return id
	end

	local link, label
	local str = '' -- text to be returned	
	
	-- GET LABEL
	label = p.getLabel(entity, lang, labelformat)

	-- if no label, return ID + link to WIkidata to make it intelligible
	if not label then
		if (defaultlabel == '-') then 
			return nil
		end
		link = tools.siteLink(id, 'wikidata')
		return str .. '[[' .. link .. '|' .. id .. ']]'
	end


	-- GET LINK
	if (linktype == '-') then
		return str .. label
	end

	-- use the linktype parameter to know which site to use
	if type(linktype) == 'string' then
		linktype = {linktype}
	end

	for i, lg in pairs(fblist(lang)) do
		link = tools.siteLink(entity, linktype[1], lg)
		if link or (linktype == "commons") then -- if we have a link or if site has only one language: break
			break
		end
	end

	if (not link) and (linktype[2]) then
		link = tools.siteLink(entity, linktype[2], lang)
	end

	-- if no link, use arg defaultlinkquery
	if (not link) and defaultlinkquery then
		defaultlinkquery.excludespecial = true
		defaultlinkquery.entity = entity
		local claims = getClaims(defaultlinkquery)
		if claims then
			for i, j in pairs(claims) do
				local id = tools.getMainId(j)
				link = tools.siteLink(id, linktype, lang)
				if link then
					break
				end
			end
		end	
	end
	
	if link then
		return str .. '[[' .. link .. '|' .. label .. ']]'
	end

	return str .. label
end

return p