-- Den ordning fallback language hämtas, om svensk label saknas. Engelska först, därefter bokmål, danska, etc...
-- local fallback = {'en', 'nb', 'da', 'nn', 'de', 'fr', 'es', 'it', 'pt'}
local formatera = require('وحدة:Math')
local i18n = {
    ["errors"] = {
        ["property-param-not-provided"] = "Property parameter not provided.",
        ["entity-not-found"] = "Entity not found.",
        ["unknown-claim-type"] = "Unknown claim type.",
        ["unknown-snak-type"] = "Unknown snak type.",
        ["unknown-datatype"] = "Unknown datatype.",
        ["unknown-entity-type"] = "Unknown entity type.",
        ["unknown-value-module"] = "You must set both value-module and value-function parameters.",
        ["value-module-not-found"] = "The module pointed by value-module not found.",
        ["value-function-not-found"] = "The function pointed by value-function not found."
    },
    ["somevalue"] = "", --''غير محدد''
    ["novalue"] =''--قيمة مجهولة
}
local sortingproperties = {'P585','P571','P580','P569','P582','P570'}

local cateref = ' [[تصنيف:صفحات بها مراجع ويكي بيانات]]'

function catewikidatainfo(options)
	local prop = options.property
local catewikidatainfo = ' [[تصنيف:صفحات بها بيانات ويكي بيانات|'.. (prop or 'wikidata')..']]'
return catewikidatainfo 
end

function versalisering(label, options)
	local versalisering = options.versalisering
	if options.firstversalisering and options.num == 1 then 
		versalisering = options.firstversalisering
	end
	if not versalisering or versalisering == '' then
		return label
	end
	if versalisering == 'lcfirst' then
		return mw.getCurrentFrame():preprocess("{{lcfirst: " .. label .. " }}")
	elseif versalisering == 'ucfirst' then
		return mw.language.getContentLanguage():ucfirst( label )
	elseif versalisering == 'lc' then
		return mw.getCurrentFrame():preprocess("{{lc: " .. label .. " }}")
	elseif versalisering == 'uc' then
		return mw.getCurrentFrame():preprocess("{{uc: " .. label .. " }}")
	end
	return label
end
function getqualifierbysortingproperty(claim, sortingproperty)
	for k, v in pairs(sortingproperty) do
		if claim.qualifiers and claim.qualifiers[v] and claim.qualifiers[v][1].snaktype == 'value' then
			return claim.qualifiers[v][1].datavalue.value.time 
		end
	end
	return nil
end

function getDate(claim, options)
	local sortingproperty = sortingproperties
	if type(options.sortingproperty) == 'table' then
		sortingproperty = options.sortingproperty
	elseif type(options.sortingproperty) == 'string' then
		sortingproperty = {options.sortingproperty}
	end
	return getqualifierbysortingproperty(claim, sortingproperty) 
end

function getDateArb(claim, options)
	local sortingproperty = options.sortingproperty or 'P569'
	if claim.mainsnak.snaktype == 'value' then
		local item = claim.mainsnak.datavalue.value['numeric-id']
		if claim.mainsnak.datavalue.value['entity-type'] == 'item' then
			item = 'Q' .. item
		elseif claim.mainsnak.datavalue.value['entity-type'] == 'property' then 
			item = 'P' .. item
		end
		return formatStatements({property = sortingproperty, entityId = item, enbarten = 'ja', sortbytime = 'chronological', noref = 'ja'})
	end
end

function comparedates(a, b) 
	if a and b then
		return a > b
	elseif a then
		return true
	end
end

function sortbyqualifier(claims, options)
	
	table.sort(claims, function(a,b)
		local timeA = getDate(a, options)
		local timeB = getDate(b, options)
		if options.sortbytime == 'inverted' then
			return comparedates(timeB, timeA)
		else
			return comparedates(timeA, timeB)
		end
	end
	)
	return claims
end

function sortbyarb(claims, options)
	
	table.sort(claims, function(a,b)
		local timeA = getDateArb(a, options)
		local timeB = getDateArb(b, options)
		if options.sortbyarbitrary == 'inverted' then
			return comparedates(timeB, timeA)
		else
			return comparedates(timeA, timeB)
		end
	end
	)
	return claims
end

function getLabelFromFallBack( id ) 
	local entity = getEntityFromId( id )
	if not entity.labels then
		return {value = '[[d:' .. id .. '|' .. id .. ']][[تصنيف:صفحات_على_ويكي_بيانات_دون_تسمية_عربية]]', language = ''}
	end
 	for k, v in pairs(fallback) do
		if entity.labels[v] then
			return {value = entity.labels[v].value, language = entity.labels[v].language}
		end
	end
	-- Om inget fallback-språk finns av de i variabeln ovan, så används det först definierade i objektet
	if entity.labels then 
		for v, k in pairs(entity.labels) do
			return {value = k.value, language = k.language}
		end
	end
	return {value = '-', language = ''}
end

function getEntityFromId( id )
	if id then 
		return mw.wikibase.getEntityObject( id )
	else
		return mw.wikibase.getEntityObject() 
	end
end
 
function getEntityIdFromValue( value )
    if value['entity-type'] == 'item' then
        return 'Q' .. value['numeric-id']
    elseif value['entity-type'] == 'property' then
        return 'P' .. value['numeric-id']
    else
        return formatError( 'unknown-entity-type' )
    end
end
 
function formatError( key )
    return i18n.errors[key]
end
 
 
function formatStatements( options, ref )
   	local formattedStatements = {}
   	local claims = {}
   	if not options.property then
       	return formatError( 'property-param-not-provided' )
   	end

    if type(ref) == 'table' then -- för de fall där funktionen anropas och alla claims redan finns i en tabell
		claims = ref[options.property] or {}
	else
 
    	--Get entity
    	local entity = nil
    	if options.entity and type( options.entity ) == "table" then
        	entity = options.entity
    	else
        	entity = getEntityFromId( options.entityId )
    	end
 
    	if not entity then
        	return '' --TODO error?
    	end
 
    	if not entity.claims or not entity.claims[options.property:upper()] then
        	return '' --TODO error?
    	end
 
    	--Format statement and concat them cleanly
		if options.rank == 'best' or not options.rank then 
			claims = entity:getBestStatements( options.property:upper() )
		elseif options.rank == 'valid' then
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
	    		if statement.rank == 'preferred' or statement.rank == 'normal' then
    				table.insert( claims, statement )
    			end
			end
		elseif options.rank == 'all' then
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
				table.insert( claims, statement )
			end
		else
			for i, statement in pairs( entity.claims[options.property:upper()] ) do
				if statement.rank == options.rank then
					table.insert( claims, statement )
				end
			end
		end
		if options.avoidqualifier then
			local claims2 = {}
			for i, statement in pairs( claims ) do	
				if not statement.qualifiers or not statement.qualifiers[options.avoidqualifier:upper()] then
					table.insert( claims2, statement)
				end
			end
			claims = claims2
		end
		--om det finns vissa statements som har en qualifier som säger "språk = svenska", ta bara med dessa
		--alternativt om det finns statements som har en qualifier som säger "skriptsystem == latinska alfabetet"
		if not options.langpref or options.langpref == '' then
			local claims2 = {}
			for i, statement in pairs( claims ) do
				if statement.qualifiers and statement.qualifiers.P407 then
					for k, v in pairs( statement.qualifiers.P407 ) do
						if v.snaktype == 'value' and v.datavalue.value['numeric-id'] == 13955 then -- Q13955 = 'العربية'
							table.insert( claims2, statement )
						end
					end
				elseif statement.qualifiers and statement.qualifiers.P282 then
					for k, v in pairs( statement.qualifiers.P282 ) do
						if v.snaktype == 'value' and v.datavalue.value['numeric-id'] == 8196 then -- Q8196 = 'أبجدية عربية'
							table.insert( claims2, statement )
						end
					end
				end
			end
			if #claims2 > 0 then
				claims = claims2
			end
		end
		if options.sortbytime == 'chronological' or options.sortbytime == 'inverted' then
			claims = sortbyqualifier(claims, options)
		elseif options.sortbyarbitrary == 'chronological' or options.sortbyarbitrary == 'inverted' then
			claims = sortbyarb(claims, options)
		end
	end
	if options.enbarten and options.enbarten ~= '' and #claims > 1 then
		claims = {claims[1]}
	end
	local statementsraw = {}
	if claims then
		for i, statement in pairs( claims ) do
			options.num = i
			local stat = formatStatement( statement, options )
			if stat then
				local s = stat.value
				local d = stat.datum
				local tf = stat.tifr
				local awardqual = stat.foto
				local pr = stat.pr
				local utgivort = stat.utgivort
				local ro = stat.ro
				local qp1a = stat.qp1a
				local onlyqualifier = stat.onlyqualifier
				local qp1 = stat.qp1
				local qp2 = stat.qp2
				local qp3 = stat.qp3
				local qp4 = stat.qp4
				local qp5 = stat.qp5

				local amatch =stat.amatch
				local goal =stat.goal

				local start2 = stat.start1
				local finish2 = stat.finish1
				local before2 = stat.before1
				local after2 = stat.after1
				local constituency2 = stat.constituency1
				local series2 = stat.series1
				local electedin2 = stat.electedin1
				local P1001 = stat.pp1001

				if s == '' then s = nil end
				if s then
			if options.football and options.football ~= '' then
				s =mw.getCurrentFrame():expandTemplate{ title = "صندوق معلومات سيرة كرة قدم/سطر فريق", args = {(start2 or ''),(finish2 or '') ,s,amatch,goal } }
			end
			
			if options.office and options.office ~= '' then
				s = mw.getCurrentFrame():expandTemplate{ title = "معلومات صاحب منصب/منصب ويكي بيانات/نواة", args = {office = s, termstart = start2, termend = finish2, constituency = constituency2, predecessor = before2, successor = after2, series= series2,electedin=electedin2,jurisdiction=P1001,entityId=options.entityId} } 

			end
					if qp1 and options.qual1 and options.qual1 and qp1a and options.qual1a and options.qual1a ~= '' then
						s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (').. (options.qual1pref or '').. qp1 ..(options.qualifiersuffix or ')'))  .. mw.text.tag('small', {}, (options.qualifierprefix or ' (') .. (options.qp1apref or '')  .. qp1a .. (options.qualifiersuffix or ')')) 
					else
					if qp1 and options.qual1 and options.qual1 ~= '' then
						s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (').. (options.qual1pref or '') .. qp1 .. (options.qualifiersuffix or ')')) 
					else
					if qp1a and options.qual1a and options.qual1a ~= '' then
						s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (').. (options.qp1apref or '') .. qp1a .. (options.qualifiersuffix or ')')) 
					end end end
					if qp2 and options.qual2 and options.qual2 ~= '' then
						s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (').. (options.qual2pref or '') .. qp2 .. (options.qualifiersuffix or ')')) 
					end
					if qp3 and options.qual3 and options.qual3 ~= '' then
						s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (').. (options.qual3pref or '') .. qp3 .. (options.qualifiersuffix or ')')) 
					end
					if qp4 and options.qual4 and options.qual4 ~= '' then
						s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (').. (options.qual4pref or '') .. qp4 .. (options.qualifiersuffix or ')')) 
					end
					if qp5 and options.qual5 and options.qual5 ~= '' then
						s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (').. (options.qual5pref or '') .. qp5 .. (options.qualifiersuffix or ')')) 
					end
					if options.justthisqual then
						if onlyqualifier then 
							s = onlyqualifier 
						else
							if not options.justthisqual ~= '' then s = nil  end-- We need only the qualifier
						end
					end
					if ro and options.withro and options.withro ~= '' then
						s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (') .. ro .. (options.qualifiersuffix or ')'))
					end
					if d and options.withdate and options.withdate ~= '' then
						if options.withdate == 'y' then
							s = s .. mw.text.tag('small', {},  (options.qualifierprefix or ' (') 'سنة ' .. d .. (options.qualifiersuffix or ')'))
						else
							s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (') .. d .. (options.qualifiersuffix or ')'))
						end
					end
					if awardqual and options.awardqua and options.awardqua ~= '' then
						s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (') .. awardqual .. (options.qualifiersuffix or ')'))
					end
					if tf and options.withintervall and options.withintervall ~= '' then
						if options.withintervall == 'gift' then
							s = s .. mw.text.tag('br') .. mw.text.tag('small', {}, (options.qualifierprefix or ' (') .. tf .. (options.qualifiersuffix or ')'))
						else
						if options.withintervall == 'before' then
							s = mw.text.tag('small', {}, (options.qualifierprefix or ' (') .. tf .. (options.qualifiersuffix or ')')) .. s
						else
							s = s .. mw.text.tag('small', {}, (options.qualifierprefix or ' (') .. tf .. (options.qualifiersuffix or ')'))
						end end
					end
					if utgivort and options.withutgivort and options.withutgivort ~= '' then
						if options.withutgivort == 'قوسين' then
							s = s .. ' ' .. mw.text.tag('small', {}, (options.qualifierprefix or ' (') .. utgivort .. (options.qualifiersuffix or ')'))
						else
							s = s .. ' ' .. utgivort
						end
					end
					if options.getsimpleproperty == 'född' and pr and pr ~= '' then
						s = s .. ' ' .. mw.text.tag('small', {}, (options.qualifierprefix or ' (') 'f. ' .. pr .. (options.qualifiersuffix or ')'))
					end
					if options.getsimpleproperty == 'parentes' and pr and pr ~= '' then
						s = s .. ' ' .. mw.text.tag('span', {}, (options.qualifierprefix or ' (') .. pr .. (options.qualifiersuffix or ')'))
					end
					if options.getsimpleproperty == 'avnågon' and pr and pr ~= '' then
						s = s .. ' ' .. mw.text.tag('span', {}, ' av ' .. pr .. '')
					end
					if type(ref) == 'table' or (options.noref and options.noref ~='') then --Inte leta efter referenser om själva anropet görs från en referens
						table.insert( formattedStatements, s )
					else
						local t = formatReferences( statement, options )
						stat.ref = t
						if options.justref and options.justref ~= '' then
							table.insert( formattedStatements, t )
							
					else table.insert( formattedStatements, s .. t )
						end
					end
				end
				table.insert(statementsraw, stat)
			end
		end
	end
	local tot = mw.text.listToText( formattedStatements, options.separator, options.conjunction )
	if tot == '' then tot = nil end
	if options.raw and options.raw ~= '' then
		return statementsraw
	end
	return tot
end
function formatReferences( statement, options )
	local reference = {}
	if statement.references then
		local cite = require('وحدة:Cite')
		for i, ref in pairs(statement.references) do
			local items, s = {}, nil
			if ref.snaks then

				if ref.snaks.P248 then
					for j, prop in pairs(ref.snaks.P248) do
						table.insert(items, 'Q' .. prop.datavalue.value['numeric-id'])
					end
				end
				if ref.snaks.P143 then
					for j, prop in pairs(ref.snaks.P143) do
						table.insert(items, 'Q' .. prop.datavalue.value['numeric-id'])
					end
				end
				s = cite.citeitem( items, ref.snaks, options )

			end
			table.insert(reference, mw.getCurrentFrame():expandTemplate{ title = "وسم", args = {'ref', s,ref.hash,cateref}})
		end
	end
	return table.concat(reference)
end

function formatStatement( statement, options )
    if statement.type == 'statement' then
    	local s = formatSnak( statement.mainsnak, options )
    	if statement.qualifiers then
			if statement.qualifiers.P1350 or statement.qualifiers.P1351 then
				s.amatch = formatStatements({property = "P1350", enbarten = 'true'}, statement.qualifiers) or ''
				s.goal = formatStatements({property = "P1351", enbarten = 'true'}, statement.qualifiers) or ''
			end
			
      
			if statement.qualifiers.P580 or statement.qualifiers.P582 or statement.qualifiers.P1365 or statement.qualifiers.P1366 then
				s.start1 = formatStatements({property = "P580", enbarten = 'true'}, statement.qualifiers) or ' '
				s.finish1 = formatStatements({property = "P582", enbarten = 'true'}, statement.qualifiers) or ' '
				s.before1 = formatStatements({property = "P1365", enbarten = 'true'}, statement.qualifiers) or ' '
				s.after1 = formatStatements({property = "P1366", enbarten = 'true'}, statement.qualifiers) or ' '
				s.constituency1 = formatStatements({property = "P768"}, statement.qualifiers) or ' '
				s.series1 = formatStatements({property = "P1545", enbarten = 'true'}, statement.qualifiers) or ' '
				s.electedin1 = formatStatements({property = "P2715"}, statement.qualifiers) or ' '
				s.pp1001 = formatStatements({property = "P1001"}, statement.qualifiers) or ' '

			
			
			end
    		if statement.qualifiers.P585 then
    			s.datum = formatStatements({property = "P585", enbarten = 'true', noref = 'true', modifytime = options.modifyqualifiertime}, statement.qualifiers)
			end
                             local qwe = options.qwer
			if statement.qualifiers.qwe  then
    			s.ro = formatStatements({property = qwe, enbarten = 'true', noref = 'true'}, statement.qualifiers)
			end
			if statement.qualifiers.P574 then
				s.dateoftaxpub = formatStatements({property = "P574", enbarten = 'true', noref = 'true', modifytime = options.modifyqualifiertime}, statement.qualifiers)
			end
			if statement.qualifiers.P405 then
				local auktorer = {}
				for i, j in pairs(statement.qualifiers.P405) do
					if j.snaktype == 'value' then
						local item = 'Q' .. j.datavalue.value['numeric-id']
						local auktorsnamn = formatStatements({property = "P428", entityId = item, noref = 'ja', enbarten = 'ja'})
						if auktorsnamn and auktorsnamn ~= '' then
							table.insert(auktorer, formatEntityId(item, {label = auktorsnamn}).value)
						else
							table.insert(auktorer, formatEntityId(item, {}).value)
						end
					end
				end
				s.auktor = mw.text.listToText(auktorer, ', ', ' & ')
			end	
			if statement.qualifiers.P580 or statement.qualifiers.P582 then
				local f = formatStatements({property = "P580", enbarten = 'true', noref = 'true', modifytime = options.modifyqualifiertime}, statement.qualifiers) or ''
				local t = formatStatements({property = "P582", enbarten = 'true', noref = 'true', modifytime = options.modifyqualifiertime}, statement.qualifiers) or ''
				s.tifr = f .. '–' .. t
			end
			if statement.qualifiers.P585 or statement.qualifiers.P1346 then
				local fo = formatStatements({property = "P585", enbarten = 'true', noref = 'true', modifytime = options.modifyqualifiertime}, statement.qualifiers) or ''
				local to = formatStatements({property = "P1346", enbarten = 'true', noref = 'true'}, statement.qualifiers) or ''
				s.foto = fo .. ' ' .. mw.text.tag('span', {}, ' ' .. to  .. '')
			end
			if statement.qualifiers.P291 then       -- خاصية بلد النشر
				s.utgivort = formatStatements({property = "P291", noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
			end
			if statement.qualifiers.P2096 then
				s.bildtext = formatStatements({property = "P2096", noref = 'true', langpref = (options.langpref or 'ar')}, statement.qualifiers)
			end
			if s then
				if options.qual1 and options.qual1 ~= '' and statement.qualifiers[options.qual1] then         -- عرض تصفيات لبنود الخاصية
					s.qp1 = formatStatements({property = options.qual1, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction,size =options.size,image =options.image}, statement.qualifiers)
				end
				if options.qual1a and options.qual1a ~= '' and statement.qualifiers[options.qual1a] then
					s.qp1a = formatStatements({property = options.qual1a, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
				if options.justthisqual and options.justthisqual ~= '' and statement.qualifiers[options.justthisqual] then
					s.onlyqualifier = formatStatements({property = options.justthisqual , noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
				if options.qual2 and options.qual2 ~= '' and statement.qualifiers[options.qual2] then
					s.qp2 = formatStatements({property = options.qual2, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction,size =options.size,image =options.image}, statement.qualifiers)
				end
				if options.qual3 and options.qual3 ~= '' and statement.qualifiers[options.qual3] then
					s.qp3 = formatStatements({property = options.qual3, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
				if options.qual4 and options.qual4 ~= '' and statement.qualifiers[options.qual4] then
					s.qp4 = formatStatements({property = options.qual4, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
				if options.qual5 and options.qual5 ~= '' and statement.qualifiers[options.qual5] then
					s.qp5 = formatStatements({property = options.qual5, noref = 'true', separator = options.qualifierseparator, conjunction = options.qualifierconjunction}, statement.qualifiers)
				end
			end
    	end
		return s
	elseif not statement.type then
		return formatSnak( statement, options )
    end
	return {value = formatError( 'unknown-claim-type' )}
end
 
function formatSnak( snak, options )
    if snak.snaktype == 'somevalue' then
    	if options.somevalue then
    		if options.somevalue == '' then
    			return nil
    		else
    			return {value = options.somevalue}
    		end
    	end
        return {value =  i18n['somevalue']}
    elseif snak.snaktype == 'novalue' then
    	if options.novalue then
    		if options.novalue == '' then
    			return nil
    		else
    			return {value = options.novalue}
    		end
    	end
        return {value = i18n['novalue']}
    elseif snak.snaktype == 'value' then
    	local s = formatDatavalue( snak.datavalue, options, snak.datatype )
    	if s and options.prefix and options.prefix ~= '' then
    		s.value = options.prefix .. s.value
    	end
    	if s and options.suffix and options.suffix ~= '' then
    		s.value = s.value .. options.suffix
    	end
        if s and s.item and options.getsimpleproperty and options.getsimpleproperty ~= '' and options.getproperty and options.getproperty ~= '' then
        	local pr = formatStatements({property = options.getproperty, entityId = s.item, enbarten = options.getenbarten, noref = 'ja', modifytime = options.getmodifytime, raw = options.getraw})
        	if pr then s.pr = pr end
        end
        return s
    else
        return {value = formatError( 'unknown-snak-type' )}
    end
end
function formatDatavalue( datavalue, options, datatype )
    --Use the customize handler if provided
    if options['value-module'] or options['value-function'] then
        if not options['value-module'] or not options['value-function'] then
            return {value = formatError( 'unknown-value-module' )}
        end
        local formatter = require ('Module:' .. options['value-module'])
        if not formatter then
            return {value = formatError( 'value-module-not-found' )}
        end
        local fun = formatter[options['value-function']]
        if not fun then
            return {value = formatError( 'value-function-not-found' )}
        end
        return {value = fun( datavalue.value, options )}
    end
 
    --Default formatters
   if datatype == 'wikibase-item'  then
        if options.formatting and options.formatting  ~= '' 
		then
			if options.formatting == 'raw' then 
				return {value = getEntityIdFromValue( datavalue.value )}
				else
			end
		elseif options.property1 and options.property1 ~= '' then
				for i, statement in pairs( datavalue ) do

        		local entit = getEntityIdFromValue( datavalue.value )
        		local caca = formatStatements( {property =options.property1, entityId = entit, noref =options.noref ,rank=options.rank,pattern =options.pattern,size =options.size,image =options.image,noref='true',enbarten ='true' })
                        local cooooca = (options.property1pref or '') ..''.. caca ..''.. (options.property1suff or '')
        		local asdf = formatEntityId( entit , options ).value
        			if asdf and asdf  ~= '' then
        		if caca and caca  ~= '' then return {value =  cooooca .. ' '.. asdf  } else return {value = asdf  } end
				end
       end 
		elseif options.propertyimage and options.propertyimage ~= '' then
				for i, statement in pairs( datavalue ) do

        		local entit = getEntityIdFromValue( datavalue.value )
        		local caca = formatStatements( {property =options.propertyimage , entityId = entit, noref =options.noref ,rank=options.rank,pattern =options.pattern,size =options.size,image =options.image,noref='true',enbarten ='true' })
        		local asdf = formatEntityId( entit , options ).value

        		if caca and caca  ~= '' then return {value =  caca } else 
				end
       end 
	   	elseif options.property2 and options.property2 ~= '' then
				for i, statement in pairs( datavalue ) do

        		local entit = getEntityIdFromValue( datavalue.value )

        		local caca = formatStatements( {property =options.property2, entityId = entit, noref =options.noref ,rank=options.rank,pattern =options.pattern,size =options.size,image =options.image,propertyimage =options.property3,enbarten ='true' })
        		local asdf = formatEntityId( entit , options ).value
        			if asdf and asdf  ~= '' then
        		if caca and caca  ~= '' then return {value =  caca .. ' '.. asdf  } else return {value = asdf  } end
				end
       end else
			return {value = formatEntityId( getEntityIdFromValue( datavalue.value ), options ).value}    	
        end 

            elseif datatype == 'wikibase-property' then
        if options.formatting and options.formatting  ~= '' 
		then
			if options.formatting == 'raw' then 
				return {value = getEntityIdFromValue( datavalue.value )}
				else
			end
		else end
			return {value = formatEntityId( getEntityIdFromValue( datavalue.value ), options ).value}    	

            elseif datatype == 'commonsMedia'  then --and datavalue.type == 'string'
        if options.image and options.image ~= '' then
        		return {value = '[[file:' .. datavalue.value  .. '|'.. (options.size or '120')..'px|'..'border'..']]' } 
        else
            return {value = versalisering(datavalue.value, options), label = datavalue.value}
        end
    elseif datatype == 'math'  then 
		 --return	{value = mw.text.tag('math', {}, ''.. datavalue.value..'') }
		 return	{value =mw.getCurrentFrame():callParserFunction( '#tag:math', ''.. datavalue.value..'' ) }
       
    elseif datatype == 'string'  or datatype == 'external-id' then
        if options.pattern and options.pattern ~= '' then
        	if options.pattern == "auktoritetsdata" then
        		local patter = formatStatements( {property = "P1630", entityId = options.property, enbarten = 'true', noref = 'true' })
        		return {value = formatFromPattern( datavalue.value, {pattern = patter} )}
        	elseif options.pattern == "auktoritetsdata2" then
        		local patter = formatStatements( {property = "P1630", entityId = options.property, enbarten = 'true', noref = 'true' })
        		return {value = '[' .. formatFromPattern( datavalue.value, {pattern = patter} ) .. ' ' .. datavalue.value .. ']' } 
        	elseif options.pattern == "auktoritetsdata3" then
        		local patter = formatStatements( {property = "P1630", entityId = options.property, enbarten = 'true', noref = 'true' })
        		return {value = '[' .. formatFromPattern( datavalue.value, {pattern = patter} ) .. ' ' .. formatFromPattern( datavalue.value, {pattern = patter} ) .. ']' } 
        	else
            	return {value = formatFromPattern( versalisering(datavalue.value, options), options )}
            end
        else
            return {value = versalisering(datavalue.value, options), label = datavalue.value}
        end

    elseif datatype == 'time' then
        local Time = require 'Module:Time2'
        local tid = Time.newFromWikidataValue( datavalue.value ):toHtml()
        if options.modifytime == 'Y' then
    		local mall = '{{ {{{|safesubst:}}}#time:Y|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
    		tid = mw.getCurrentFrame():preprocess(mall)
        
    	elseif options.modifytime == 'F' then
    		local mall = '{{ {{{|safesubst:}}}#time:F|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
    		tid = mw.getCurrentFrame():preprocess(mall)

    	elseif options.modifytime == 'j' then
    		local mall = '{{ {{{|safesubst:}}}#time:j|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
    		tid = mw.getCurrentFrame():preprocess(mall)

    	elseif options.modifytime == 'j F Y' then
    		local mall = '{{ {{{|safesubst:}}}#time:j F Y|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
    		tid = mw.getCurrentFrame():preprocess(mall)

    	elseif options.modifytime == 'j F' then
    		local mall = '{{ {{{|safesubst:}}}#time:j F|' .. string.gsub(datavalue.value.time,'-00','-01') .. '}}'
    		tid = mw.getCurrentFrame():preprocess(mall)

    	elseif options.modifytime == 'q' then
    		local mall = datavalue.value.time
    		tid = mw.getCurrentFrame():preprocess(mall)

    	elseif options.modifytime == 'qq' then
    		local mall = datavalue.value
    		tid = mw.getCurrentFrame():preprocess(mall)

        end
        return {value = tid}
        
    elseif datatype == 'globe-coordinate' then
        --local GlobeCoordinate = require 'Module:GlobeCoordinate'
        --return {value = GlobeCoordinate.newFromWikidataValue( datavalue.value ):toHtml()}

		local coord = datavalue.value
		local globetable = { Q2 = 'earth', Q111 = 'mars', Q405 = 'moon'}
	if options.formatting  and options.formatting  ~= '' then
		if options.formatting == 'latitude' then
			return {value =coord.latitude }
		elseif options.formatting == 'longitude' then
			return {value =coord.longitude }
		elseif options.formatting == 'dimension' then
			return {value =coord.dimension }
		elseif options.formatting == 'precision' then
			return {value =coord.precision}
		--elseif options.formatting == 'coord' then
			--return {value = }
		else

		end
		else
			return {value =mw.getCurrentFrame():expandTemplate{ title = "coord", args = {coord.latitude,coord.longitude,display=inline} }..catewikidatainfo(options) }
	end

	elseif datatype == 'quantity' then 
		local amount, unit, cat = datavalue.value.amount, datavalue.value.unit, nil
		if unit then
			unit = unit:match('Q%d+')
		end
		local formatera = require('وحدة:Math')
		local number = formatera.newFromWikidataValue(datavalue.value)

		local unitraw = unit
		if unit then
			-- يتحقق اذا كان هناك اي اختصار لوحدة القياس
			local lab = options.label or formatStatements({property = 'P498', entityId = unit, enbarten = 'true', noref = 'true'}) or formatStatements({property = 'P558', entityId = unit, enbarten = 'true', langpref = options.langpref, noref = 'true'})
			if lab and ( not options.nounitshort or options.nounitshort == '' )  then
				local s = formatEntityId( unit, {label = lab, nolink = (options.nounitlink or options.nolink) })
				unit = s.value
				cat = s.cat
			else -- om det inte finns en förkortning
				local s = formatEntityId( unit, {nolink = options.nounitlink})
				unit = s.value
				cat = s.cat
			end
		end
		return {value = number .. ' ' .. (unit or ''), amount = amount, unit = unit, unitraw = unitraw, cat = cat}
		
	elseif datatype == 'url' then
		if options.label and options.label ~= '' then
			return {value = '[' .. datavalue.value .. ' ' .. options.label .. ']'}
		else
			return {value = datavalue.value}
		end
		
	elseif datatype == 'monolingualtext' then

			lange = '('.. mw.language.fetchLanguageName(datavalue.value.language, 'ar')..')'
		
		if not options.langpref or options.langpref == '' then
			valu = mw.text.tag('span', {title = mw.language.fetchLanguageName(datavalue.value.language, 'ar')}, datavalue.value.text)
		else
			if options.langpref == datavalue.value.language then
				valu  = mw.text.tag('span', {title = mw.language.fetchLanguageName(datavalue.value.language, 'ar')}, datavalue.value.text)
			end
		end
		if options.showlang and options.showlang ~= '' 
		then return {value = valu  ..' '..lange, text = datavalue.value.text}
		else return {value = valu  , text = datavalue.value.text}
			end


    else
        return {value = formatError( 'unknown-datatype' )}
    end
end


function formatEntityId( entityId, options )
	local label = options.label or mw.wikibase.label( entityId )
	if label == '' then
		label = mw.wikibase.label( entityId ) or nil
	end
	
    local link = mw.wikibase.sitelink( entityId )

    if link and (not options.nolink or options.nolink == '') then
        if label and label ~= '' then
            return {value = '[[:' .. link .. '|' .. versalisering(label, options) .. ']]'.. catewikidatainfo(options), label = label }
        else
            return {value = '[[:' .. versalisering(link, options) .. ']]'.. catewikidatainfo(options), label = link }
        end
    else
    	if label then
    		return {value = versalisering(label, options), label = label}
    	else return ''
    		--local s = getLabelFromFallBack( entityId )
    		--local l = mw.language.fetchLanguageName(s.language, 'ar')
    		--if not l or l == '' then
    			--l = 'okänt språk'
    		--end
    		--if s then
    			--return {value = mw.text.tag('span', {title = l, ['data-q'] = entityId, class='modulwikidata2_missingswedishlabel'}, versalisering(s.value, options) ), cat = 'Wikidataetiketter på ' .. l, label = s.value }
    		--end
    	end
    	return '' --{value = entityId, cat = 'som har labels med Qid', label = entityId}
    end
end
 
function formatFromPattern( str, options )
    return mw.ustring.gsub( options.pattern, '$1', str ) .. '' --الحصول على اول نتيجة للدالة
end
 
local p = {}
 
function p.formatEntityId( entityId, options )
	return formatEntityId( entityId, (options or {}) )
end
	
function p.formatStatements( frame, key )
    local args = frame.args
 
    --If a value if already set, use it
    if args.value and args.value ~= '' then
        return args.value
    end
    return formatStatements( frame.args, key )
end
 
function p.formatStatementsFromLua( options, key )
    --If a value if already set, use it
    if options.value and options.value ~= '' then
        return options.value
    end
    local s = formatStatements( options, key )
    if s == '' then
    	s = nil
    end
    return s
end
 
function p.getSiteLink(frame)

	local project = frame.args[1] 
	local id = frame.args[2]
	local entity = mw.wikibase.getEntityObject(id)
	if not entity or entity == '' then return nil end
	local link = entity:getSitelink(project)
	
	var = link
	
	return var
	
end


function descriptionIn(langcode,id)
	local lan = langcode or 'ar'
	local entity = mw.wikibase.getEntityObject(id)
			if entity
			and entity.descriptions 
			and entity.descriptions[''..lan..'']
			and entity.descriptions[''..lan..''].value 
			then
				local lang = entity.descriptions[''..lan..'']
					if lang['language'] == lan then
					return entity.descriptions[''..lan..''].value
					else return nil end
			end
end

function labelIn(langcode,id)
	local lan = langcode or 'ar'
	local entity = mw.wikibase.getEntityObject(id)
			if entity
			and entity.labels 
			and entity.labels[''..lan..'']
			and entity.labels[''..lan..''].value 
			then
				local lang = entity.labels[''..lan..'']
					if lang['language'] == lan then
					return entity.labels[''..lan..''].value
					else return nil end
			end
end

function p.descriptionIn(frame)
	local langcode = frame.args[1]
	local id = frame.args[2] -- "id" must be nil, as access to other Wikidata objects is disabled in Mediawiki configuration

	return descriptionIn( langcode ,id  )
end

function p.labelIn(frame)
	local langcode = frame.args[1]
	local id = frame.args[2] -- "id" must be nil, as access to other Wikidata objects is disabled in Mediawiki configuration

	return labelIn( langcode ,id  )
end
function p.pageId(frame)
	local entity = mw.wikibase.getEntityObject()
	if not entity then return nil else return entity.id end
end

function p.Dump(frame)
	local f = (frame.args[1] or frame.args.id) and frame or frame:getParent()
	local data = mw.wikibase.getEntityObject(f.args.id)
	if not data then
		return i18n.warnDump
	end

	local i = 1
	while true do
		local index = f.args[i]
		if not index then
			return frame:extensionTag("source", mw.dumpObject(data),{ lang= 'lua'}).. i18n.warnDump

		end

		data = data[index] or data[tonumber(index)]
		if not data then
			return i18n.warnDump
		end

		i = i + 1
	end
end

return p