---@diagnostic disable: undefined-global

local p = {}
local Frame_args = {}
local filterclaims = require("Module:Wikidata2/filter_claims")
local sortclaims = require("Module:Wikidata2/sort_claims")
local Moduleill_wd2
local Moduledump
local Moduletext
local Modulecite
local Moduleflags
local InfoboxImage
local ModuleGlobes
local formatera
local weblink

local citetitle = "Module:Cite Q"
if nil ~= string.find(mw.getCurrentFrame():getTitle(), "ملعب", 1, true) then
	citetitle = "Module:Cite Q/ملعب"
end

local i18n = {
	["errors"] = {
		["property-param-not-provided"] = "وسيط property غير متوفر.",
		["entity-not-found"] = "الكيان غير موجود.",
		["unknown-claim-type"] = "نوع claim غير معروف.",
		["unknown-snak-type"] = "نوع snak غير معروف.",
		["unknown-datatype"] = "نوع data غير معروف.",
		["unknown-entity-type"] = "نوع entity غير معروف.",
		["unknown-value-module"] = "يجب عليك تعيين كل من  value-module و value-function.",
		["unknown-claim-module"] = "يجب عليك تعيين كل من claim-module و claim-function.",
		["unknown-property-module"] = "يجب عليك تعيين كل من property-module و property-function.",
		["property-module-not-found"] = "الوحدة المستخدمة في وسيط property-module غير موجودة.",
		["property-function-not-found"] = "الوظيفة المستخدمة في وسيط property-function غير موجودة.",
		["value-module-not-found"] = "الوحدة المستخدمة في وسيط value-module غير موجودة.",
		["value-function-not-found"] = "الوظيفة المستخدمة في وسيط value-function غير موجودة.",
		["claim-module-not-found"] = "الوحدة المستخدمة في وسيط claim-module غير موجودة.",
		["claim-function-not-found"] = "الوظيفة المستخدمة في وسيط claim-function غير موجودة."
	},
	["noarabiclabel"] = "تصنيف:صفحات_ويكي_بيانات_بحاجة_لتسمية_عربية",
	["warnDump"] = "[[تصنيف:Called function 'Dump' from module Wikidata]]",
	["somevalue"] = "", --'"غير محدد"'
	["novalue"] = "", --قيمة مجهولة
	["cateref"] = "[[" .. "تصنيف:صفحات بها مراجع ويكي بيانات" .. "]]",
	["to translate"] = "صفحات تستعمل معطيات من ويكي بيانات بحاجة لترجمة",
	["trackingcat"] = "صفحات تستخدم خاصية $1",
	["see-wikidata-value"] = "الاطلاع ومراجعة البيانات على ويكي داتا",
	["see-wikidata"] = "راجع العنصر من ويكي بيانات المقابل",
	["see-another-project"] = "مقالة على $1",
	["see-another-language"] = "مقالة على ويكيبيديا $1"
}
local falsetitles = {
	"قالب:قيمة ويكي بيانات",
	"وحدة:Wikidata2"
}

local skiip_items = {
	["P106"] = {
		"Q42857", -- prophet
		"Q14886050", -- terrorist
		"Q2159907" -- criminal
	}
}

local function isvalid(x)
	if x and x ~= "" and x ~= "لا" then return x end
	return nil
end

local function isvalids(xs)
	for _, x in pairs(xs) do
		if isvalid(x) then
			return x
		end
	end
	return nil
end

local function isntvalid(x)
	if not x or x == "" or x == nil then return true end
	return false
end

function formatFromPattern(str, options)
	-- [[  function to replace $1 with string  ]]
	if isvalid(options.pattern) then
		str = string.gsub(str, "%%", "%%%%")
		str = mw.ustring.gsub(options.pattern, "$1", str)
	end
	return str
end

function No_Tracking_cat(options)
	if isvalid(options.formatting) == "raw" or isvalid(options.formatting) == "sitelink" then
		return true
	end
	-- local notracking = isvalid(options.nocate) or isvalid(options.notracking) or isvalid(Frame_args.notracking)
	-- local raw = isvalid(options.raw) or isvalid(Frame_args.raw) or isvalid(options.raw2) or isvalid(Frame_args.raw2)
	-- local nolink = isvalid(options.nolink) or isvalid(Frame_args.nolink)

	local notracking = isvalids({ options.nocate, options.notracking, Frame_args.notracking })
	local raw = isvalids({ options.raw, Frame_args.raw, options.raw2, Frame_args.raw2 })
	local nolink = isvalids({ options.nolink, Frame_args.nolink })

	if notracking or raw or nolink then
		return true
	end
	local pagetitle = mw.title.getCurrentTitle().text
	for _, title in pairs(falsetitles) do
		if string.find(pagetitle, title, 1, true) then
			mw.log("notracking for title with: " .. title)
			return true
		end
	end
	return false
end

function addTrackingCategory(options)
	if No_Tracking_cat(options) then
		return ""
	end
	local cat = require("Module:Wikidata/تتبع").makecategory1
	local category = cat(options)
	local nbsp = " "
	if isvalid(options.nbsp) then
		nbsp = ""
	end
	if isvalid(category) then
		return nbsp .. category
	end
	return ""
end

function catewikidatainfo(options)
	--[[  function to add tracking category ]]
	if No_Tracking_cat(options) then
		return ""
	end
	local cat = ""
	local prop = options.property
	cat = cat .. " [[" .. "تصنيف:صفحات بها بيانات ويكي بيانات|" ..
		(prop or "wikidata") .. "]]"
	if isntvalid(options.nolink) then
		return cat
	else
		return ""
	end
end

function get_entityId(options)
	local id = isvalid(options.entityId) or isvalid(options.id) or isvalid(options.qid)
	if id then
		return id
	end
	if isvalid(options.page) then
		id = mw.wikibase.getEntityIdForTitle(options.page)
	else
		id = mw.wikibase.getEntityIdForCurrentPage()
	end
	return id or ""
end

function p.countSiteLinks(id)
	local numb = 0
	local entity = mw.wikibase.getEntity(id)
	if entity and entity.sitelinks then
		for i, v in pairs(entity.sitelinks) do
			numb = numb + 1
		end
	end
	return numb
end

function make_format_num(String)
	local line = String
	line = mw.getCurrentFrame():preprocess("{{ {{{|safesubst:}}}formatnum: " .. String .. " }}")
	line = mw.ustring.gsub(line, "٫", ".")
	line = mw.ustring.gsub(line, "٬", ",")
	return line
end

function formatcharacters(label, options)
	local formatch = options.formatcharacters
	--if options.FormatfirstCharacter and options.num == 1 then
	--formatch = options.FormatfirstCharacter
	--end

	local String2 = mw.ustring.gsub(label, "–", "-")
	local march_y =
		mw.ustring.match(String2, "%d%d%d%d%-%d%d%d%d", 1) or mw.ustring.match(String2, "%d%d%-%d%d%d%d", 1) or
		mw.ustring.match(String2, "%d%d%d%d", 1) or
		mw.ustring.match(String2, "%d%d%d%d%-%d%d", 1) or
		mw.ustring.match(String2, "%d%d%d%d", 1)

	if isvalid(options.illwd2y) then
		return march_y or label
	end
	if isvalid(options.illwd2noy) and march_y then
		label = mw.ustring.gsub(label, march_y, "")
		return label
	end

	if isntvalid(formatch) then
		return label
	end

	local prepr = {
		["lcfirst"] = "{{lcfirst: " .. label .. " }}",
		["lc"] = "{{lc: " .. label .. " }}",
		["uc"] = "{{uc: " .. label .. " }}"
	}
	if prepr[formatch] then
		return mw.getCurrentFrame():preprocess(prepr[formatch])
	elseif formatch == "ucfirst" then
		return mw.language.getContentLanguage():ucfirst(label)
	elseif formatch == "formatnum" then
		return make_format_num(label)
	end
	return label
end

function descriptionIn(langcode, id) -- returns item description for a given language
	if isntvalid(langcode) then
		langcode = "ar"
	end
	langcode = mw.text.trim(langcode or "")
	id = mw.text.trim(id or "")
	-- Lua memory used 640,195/52,428,800 bytes
	return mw.wikibase.getDescriptionByLang(id, langcode) or ""
	--[[
	-- Lua memory used 3,982,457/52,428,800 bytes
	if langcode == "ar" then
		local description, lange = mw.wikibase.getDescriptionWithLang(id)
		if lange == langcode then
			return description
		else
			return nil
		end
	else
		local entity = getEntityFromId(id)
		if entity and entity.descriptions then
			local description = entity.descriptions[langcode]
			if description and description.value then
				if description["language"] == langcode then
					return description.value
				end
			end
		end
	end
	return nil
	]]
end

function labelIn(langcode, id) -- returns item label for a given language
	if isntvalid(langcode) then
		langcode = "ar"
	end
	if type(id) ~= "string" then
		id = tostring(id)
	end
	langcode = mw.text.trim(langcode or "")
	id = mw.text.trim(id or "")
	local label = mw.wikibase.getLabelByLang(id, langcode) or nil
	return label
end

function filter_langs(claims, options)
	local claims7 = {}
	local arabic_id = { ["P407"] = 13955, ["P282"] = 8196 } -- Q13955 = "العربية", Q8196 = "أبجدية عربية"

	for _, statement in pairs(claims) do
		for prop, id in pairs(arabic_id) do
			if statement.qualifiers and statement.qualifiers[prop] then
				for _, v in pairs(statement.qualifiers[prop]) do
					if v.snaktype == "value" and v.datavalue.value["numeric-id"] == id then
						table.insert(claims7, statement)
						break
					end
				end
			end
		end
	end

	if #claims7 > 0 then
		claims = claims7
	end

	return claims
end

--[[

  functions

]]

function getEntityFromId(id)
	return isvalid(id) and mw.wikibase.getEntity(id) or mw.wikibase.getEntity()
end

function formatError(key)
	return i18n.errors[key]
end

function formatDatavalue(datavalue, datatype, options)
	--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, datatype, options) }
	end

	--Default dataformatters
	local dataformatters = {
		["wikibase-item"] = formatwikibaseitem,
		["wikibase-property"] = formatwikibaseproperty,
		["commonsMedia"] = formatcommonsMedia,
		["math"] = formatmath,
		["time"] = formattime,
		["external-id"] = formatexternalid,
		["string"] = formatstring,
		["globe-coordinate"] = formatcoordinate,
		["quantity"] = formatquantity,
		["url"] = formaturl,
		["monolingualtext"] = formatmonolingualtext,
		["geo-shape"] = formatgeoshape,
		["tabular-data"] = formattabulardata
	}

	local dataformatter = dataformatters[datatype]
	if not dataformatter then
		return { value = formatError("unknown-data-type") }
	end
	return dataformatter(datavalue, datatype, options)
end

function formatSnak(snak, options)
	if snak.snaktype == "somevalue" then
		local somevalue = options.somevalue or i18n["somevalue"]
		return { value = somevalue }
	elseif snak.snaktype == "novalue" then
		local novalue = options.novalue or i18n["novalue"]
		return { value = novalue }
	elseif snak.snaktype == "value" then
		local s = formatDatavalue(snak.datavalue, snak.datatype, options)
		if s and s.value and isvalid(s.value) then
			s.value = (options.prefix or "") .. s.value .. (options.suffix or "")
		end
		return s
	else
		return { value = formatError("unknown-snak-type") }
	end
end

function formatStatement(statement, options)
	if options["claim-module"] or options["claim-function"] then
		if not options["claim-module"] or not options["claim-function"] then
			return { value = formatError("unknown-claim-module") }
		end
		local formatter = require("Module:" .. options["claim-module"])
		if formatter == nil then
			return { value = formatError("claim-module-not-found") }
		end
		local fun = formatter[options["claim-function"]]
		if fun == nil then
			return { value = formatError("claim-function-not-found") }
		end
		return { value = fun(statement, options) }
	elseif statement.type == "statement" then
		local s = formatSnak(statement.mainsnak, options)
		if isvalid(s) then
			s.qualifiers = {}
			if statement.qualifiers then
				local qualu = formatqualifiers(statement, s, options)
				--if isvalid(qualu) then table.insert(qualu) end
			end
			if statement.references then
				if isvalid(options.reff) then
					s.reff = formatReferences(statement, options)
				end
			end
		end
		return s
	elseif not statement.type then
		return formatSnak(statement, options)
	end
	return { value = formatError("unknown-claim-type") }
end

function formatOneStatement(statement, ref, options)
	local value = nil
	local stat = formatStatement(statement, options)
	if not stat then
		return { v = value, raw = stat }
	end

	local s = stat.value
	if isntvalid(s) then
		return { v = value, raw = stat }
	end

	if not stat.qualifiers then
		stat.qualifiers = {}
	end

	local P585 = stat.P585 or ""
	local tf = stat.tifr
	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 reff = stat.reff

	if reff and isvalid(options.reff) then
		s = s .. reff
	end
	if isvalid(options.template) then
		s =
			mw.getCurrentFrame():expandTemplate {
				title = options.template,
				args = {
					stat.QQ1,
					s,
					stat.QQ2,
					stat.QQ3,
					stat.QQ4,
					stat.QQ5,
					stat.QQ6,
					stat.QQ7,
					stat.QQ8,
					stat.QQ9,
					stat.QQ10,
					entityId = options.entityId,
					v1 = options.v1,
					id = stat.ID
				}
			}
	end
	if isvalid(options.football) then
		s =
			mw.getCurrentFrame():expandTemplate {
				title = "صندوق معلومات سيرة كرة قدم/سطر فريق",
				args = {
					stat.qualifiers.P580 or "",
					stat.qualifiers.P582 or "",
					s,
					stat.amatch,
					stat.goal
				}
			}
	end

	local function qoo(Prefix, qualpref, p, Suffix)
		if isvalid(p) then
			local stri = (Prefix or " (") .. (qualpref or "") .. p .. (Suffix or ")")
			if isvalid(options.nosmall) then
				return stri
			else
				return mw.text.tag("small", {}, stri)
			end
		end
	end

	local QPrefix = isvalid(options.qualifierprefix)
	local QSuffix = isvalid(options.qualifiersuffix)

	if isvalid(qp1) and isvalid(options.qual1) and isvalid(qp1a) and isvalid(options.qual1a) then
		s = s ..
			qoo(QPrefix, options.qual1pref, qp1, QSuffix) .. qoo(QPrefix, options.qp1apref, qp1a, QSuffix)
	elseif isvalid(qp1) and isvalid(options.qual1) then
		s = s .. qoo(QPrefix, options.qual1pref, qp1, QSuffix)
	elseif isvalid(qp1a) and isvalid(options.qual1a) then
		s = s .. qoo(QPrefix, options.qp1apref, qp1a, QSuffix)
	end

	if isvalid(qp2) and isvalid(options.qual2) then
		s = s .. qoo(QPrefix, options.qual2pref, qp2, QSuffix)
	end

	if isvalid(qp3) and isvalid(options.qual3) then
		s = s .. qoo(QPrefix, options.qual3pref, qp3, QSuffix)
	end
	if isvalid(qp4) and isvalid(options.qual4) then
		s = s .. qoo(QPrefix, options.qual4pref, qp4, QSuffix)
	end
	if isvalid(qp5) and isvalid(options.qual5) then
		s = s .. qoo(QPrefix, options.qual5pref, qp5, QSuffix)
	end

	if isvalid(options.justthisqual) then
		if onlyqualifier then
			s = onlyqualifier
		else
			s = nil -- We need only the qualifier
		end
	end

	if isvalid(P585) and isvalid(options.withdate) then
		if options.withdate == "y" then
			s = s .. qoo(QPrefix, "سنة ", P585, QSuffix)
		elseif options.withdate == "before" then
			s = "*" .. P585 .. ":" .. s .. "\n"
		else
			s = s .. qoo(QPrefix, "", P585, QSuffix)
		end
	end

	local bothdates = options.bothdates
	if tf and isvalid(bothdates) then
		if bothdates == "line" then
			s = s .. mw.text.tag("br") .. qoo(QPrefix, "", tf, QSuffix)
		elseif bothdates == "before" then
			s = qoo(QPrefix, "", tf, QSuffix) .. s
		else
			s = s .. qoo(QPrefix, "", tf, QSuffix)
		end
	end

	if type(ref) == "table" or (isvalid(options.noref)) or (isvalid(options.justthisqual)) then
		value = s
	else
		local t = formatReferences(statement, options)
		stat.ref = t
		if isvalid(options.justref) then
			value = t
		elseif isvalid(options.onlyvaluewithref) then
			if isvalid(t) then
				value = s .. t
			end
		else
			value = s .. t
		end
	end
	return { v = value, raw = stat }
end

function get_claims(entity, property, options)
	local claims = {}
	--Format statement and concat them cleanly
	if options.rank == "best" or isntvalid(options.rank) then
		--claims = entity:getAllStatements( property )
		claims = entity:getBestStatements(property)
	elseif options.rank == "valid" then
		for i, statement in pairs(entity.claims[property]) 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[property]) do
			table.insert(claims, statement)
		end
	else
		for i, statement in pairs(entity.claims[property]) do
			if statement.rank == options.rank then
				table.insert(claims, statement)
			end
		end
	end

	return claims
end

function formatStatements(options, LuaClaims)
	local valuetable = {} -- formattedStatements
	local claims = {}

	if isntvalid(options.property) and isvalid(options.pid) then
		options.property = options.pid
	end

	if isntvalid(options.property) then
		return formatError("property-param-not-provided")
	end
	local option1 = options.option1
	if option1 and options.option1value then
		options[option1] = options.option1value
		options['"' .. option1 .. '"'] = options.option1value
		--mw.log( "option1: " .. option1 .. "value: " .. options.option1value  )
	end
	if type(LuaClaims) == "table" then
		claims = LuaClaims[options.property] or {}
		mw.log("module:wikidata2: claims = LuaClaims[options.property]")
	else
		--Get entity
		local entity = nil
		if options.entity and type(options.entity) == "table" then
			entity = options.entity
		else
			local id = get_entityId(options)
			if isvalid(id) then
				--mw.ustring.match(id, "Q%d+") or mw.ustring.match(id, "P%d+")
				if mw.wikibase.isValidEntityId(id) and mw.wikibase.entityExists(id) then
					options.entityId = id
					options.qid = id
				else
					mw.addWarning(id .. " لا يمثل معرف ويكي بيانات صحيح")
					return ""
				end
			end
			entity = getEntityFromId(id)
		end
		if not entity then
			return ""
		end
		--local property = mw.wikibase.resolvePropertyId( options.property:upper() )
		local property = options.property:upper()

		if not entity.claims or not entity.claims[property] then
			if isvalid(options.otherproperty) then
				options.property = options.otherproperty
				property = options.otherproperty:upper()
			end
		end
		if property == nil then
			return ""
		end
		if not entity.claims or not entity.claims[property] then
			return "" --TODO error?
		end
		claims = get_claims(entity, property, options)
	end

	if isntvalid(options.langpref) then
		claims = filter_langs(claims, options)
	end
	if isvalid(options.sort_before_filter) then
		claims = sortclaims.sort_claims(claims, options)
		claims = filterclaims.filter_claims(claims, options)
	else
		claims = filterclaims.filter_claims(claims, options)
		claims = sortclaims.sort_claims(claims, options)
	end
	
	local statementsraw = {}
	local All_claims = claims
	if claims then
		if options["property-module"] or options["property-function"] then
			if not options["property-module"] or not options["property-function"] then
				return formatError("unknown-property-module")
			end
			local formatter = require("Module:" .. options["property-module"])
			if not formatter then
				return formatError("property-module-not-found")
			end
			local fun = formatter[options["property-function"]]
			if not fun then
				return formatError("property-function-not-found")
			end

			mw.log("work with property-module: " .. options["property-module"] .. "|" .. options["property-function"])
			return fun(claims, options)
		else
			for i, statement in pairs(claims) do
				options.num = i
				local va = formatOneStatement(statement, LuaClaims, options)
				if va.v then
					table.insert(valuetable, va.v)
				end
				table.insert(statementsraw, va.raw)
			end
		end
	end

	if isvalid(options.raw) then
		if isvalid(options.rawtolua) then
			return mw.getCurrentFrame():extensionTag("source", mw.dumpObject(statementsraw), { lang = "lua" })
		end
		return statementsraw
	end

	local priff = ""
	local Separator = options.separator  -- or ""
	local Conjunction = options.conjunction -- or ""

	if Separator == "br" or Conjunction == "br" then
		Separator = mw.text.tag("br")
	end
	if Separator == "*" then
		priff = "\n*"
		Separator = "\n*"
	end
	if Separator == "#" then
		priff = "\n#"
		Separator = "\n#"
	end
	if isvalid(options.justref) then
		priff = ""
		Separator = ""
	end

	local tot = mw.text.listToText(valuetable, Separator, Separator)
	if #valuetable > 1 then
		tot = priff .. tot
	end

	if isntvalid(tot) then
		tot = nil
	end
	if isvalid(options.returnnumberofvalues) or options.returnnumberofvalues == true then
		return tot, #valuetable
	end
	if isvalid(options.numberofclaims) then
		return #All_claims
	end
	return tot
end

function formatReferences(statement, options)
	local ic = 1
	local reference = {}
	local numberofref = tonumber(options.numberofreferences) or 7
	local qid = get_entityId(options)
	local statementreferences = statement.references

	if statementreferences then
		if Modulecite == nil then
			Modulecite = require(citetitle)
		end
		for i, ref in ipairs(statementreferences) do
			if ref.snaks and numberofref >= ic then
				local s = Modulecite._cite_wikidata(ref, qid)
				if isvalid(s) then
					ic = ic + 1
					table.insert(reference, s)
				end
			end
		end
	end

	local final = table.concat(reference)
	if isvalid(final) then
		final = final .. i18n.cateref
	end
	return final or ""
end

function formatqualifiers(statement, s, options)
	s.qualifiers = {}

	local function qua(p, firstvalue, modifytime)
		local vvv
		if isvalid(p) then
			vvv = formatStatements({
				property = p,
				enlabelcate = "t",
				firstvalue = (firstvalue or ""),
				modifytime = (modifytime or "longdate"),
				noref = "t"
			}, statement.qualifiers) or ""
			s.qualifiers[p] = vvv
			return vvv
		end
	end

	if isvalid(options.template) then
		s.ID = statement.mainsnak.datavalue.value.id
		s.QQ1 = qua(options.Q1)
		s.QQ2 = qua(options.Q2)
		s.QQ3 = qua(options.Q3)
		s.QQ4 = qua(options.Q4)
		s.QQ5 = qua(options.Q5)
		s.QQ6 = qua(options.Q6)
		s.QQ7 = qua(options.Q7)
		s.QQ8 = qua(options.Q8)
		s.QQ9 = qua(options.Q10)
		s.QQ10 = qua(options.Q10)
	end

	if isvalid(options.football) then
		if statement.qualifiers.P1350 or statement.qualifiers.P1351 then
			s.amatch = qua("P1350", "true")
			s.goal = qua("P1351", "true")
		end
	end

	if isvalid(options.withdate) then
		--if statement.qualifiers.P585 then
		s.P585 = qua("P585", "true", options.modifyqualifiertime)
	end

	local bothdates_option = options.bothdates
	if isvalid(bothdates_option) then
		if statement.qualifiers.P580 or statement.qualifiers.P582 then
			local f = qua("P580", "true", options.modifyqualifiertime)
			local t = qua("P582", "true", options.modifyqualifiertime)
			s.tifr = f .. "–" .. t
		end
	end

	local function quaaal(opti, options)
		if isvalid(opti) and statement.qualifiers[opti] then
			local kkk =
				formatStatements(
					{
						property = opti,
						noref = "t",
						separator = options.qualifierseparator,
						conjunction = options.qualifierconjunction,
						size = options.size,
						image = options.image,
						modifytime = options.modifyqualifiertime,
						enlabelcate = "t",
						langpref = options.langpref,
						showlang = options.showlang
					},
					statement.qualifiers
				) or ""

			s.qualifiers[opti] = kkk
			return kkk
		end
	end

	if isvalid(options.justthisqual) and statement.qualifiers[options.justthisqual] then
		s.onlyqualifier = quaaal(options.justthisqual, options)
	end
	if isvalid(options.qual1) and statement.qualifiers[options.qual1] then
		s.qp1 = quaaal(options.qual1, options)
	end
	if isvalid(options.qual1a) and statement.qualifiers[options.qual1a] then
		s.qp1a = quaaal(options.qual1a, options)
	end
	if isvalid(options.qual2) and statement.qualifiers[options.qual2] then
		s.qp2 = quaaal(options.qual2, options)
	end
	if isvalid(options.qual3) and statement.qualifiers[options.qual3] then
		s.qp3 = quaaal(options.qual3, options)
	end
	if isvalid(options.qual4) and statement.qualifiers[options.qual4] then
		s.qp4 = quaaal(options.qual4, options)
	end
	if isvalid(options.qual5) and statement.qualifiers[options.qual5] then
		s.qp5 = quaaal(options.qual5, options)
	end
end

function get_property1(options, item)
	--[[ function to get countries flags without reload large countries items ]]
	local flagprop = { "p27", "p1532", "p17", "p495", "p1376" }
	local work_flag = false
	if string.lower(options.property1) == "p41" then
		for k, l in pairs(flagprop) do
			if string.lower(options.property) == l then
				work_flag = true
			end
		end
	end
	local caca = ""
	local size = options.size or ""
	if isntvalid(size) then
		size = "20"
	end
	if work_flag then
		if Moduleflags == nil then
			Moduleflags = require("Module:Wikidata2/Flags")
		end
		local flag = Moduleflags[item]
		if isntvalid(flag) then
			flag =
				formatStatements(
					{
						property = options.property1,
						otherproperty = options.otherproperty1,
						entityId = item,
						rank = options.property1rank,
						pattern = options.property1pattern,
						formatting = options.property1formatting,
						noref = "t",
						firstvalue = "t"
					}
				)
			--mw.log("get flag2 :" .. flag .. ", for item ".. item )
		end
		if isvalid(flag) then     -- return real image
			if isvalid(options.image) then -- return real image
				caca = "[[ملف:" .. flag .. "|" .. size .. "px|" .. "border" .. "]]"
				--caca = Infobox_Image( {image=flag, size=size, maxsize = "280x330px", center=options.center} )
				--mw.log("get flag :" .. flag .. ", for item ".. item )
			end
		end
	end
	if isntvalid(caca) then
		caca =
			formatStatements(
				{
					property = options.property1,
					otherproperty = options.otherproperty1,
					entityId = item,
					rank = options.property1rank,
					pattern = options.property1pattern,
					formatting = options.property1formatting,
					size = options.size,
					image = options.image,
					noref = "t",
					firstvalue = "t"
				}
			)
	end
	return caca
end

function formatsitelink(entityId, options)
	--[[ function to get only the value with link ]]
	local link = sitelink(entityId)
	if isvalid(link) and isntvalid(options.nolink) then
		return "[[" .. link .. "]]" .. catewikidatainfo(options)
	end
	return link
end

function formatwikibaseitem(datavalue, datatype, options)
	--[[  datatype	wikibase-item	]]
	local value
	local itemqid = datavalue.value.id
	local Skipped = skiip_items[options.property] or {}
	for k, v in pairs(Skipped) do
		if datavalue.value.id == v then
			return { value = "", item = "" }
		end
	end
	if isvalid(options.formatting) then
		if options.formatting == "raw" then
			return { value = itemqid, item = itemqid }
		elseif options.formatting == "rawtotemplate" and isvalid(options.rawtotemplate) then
			local args = { q = itemqid, no1 = options.no1 or "", no2 = options.no2 or "" }
			value = mw.getCurrentFrame():expandTemplate { title = options.rawtotemplate, args = args } .. "\n"
			return { value = value, item = itemqid }
		elseif options.formatting == "sitelink" then
			value = formatsitelink(datavalue.value.id, options)
			return { value = value, item = itemqid }
		else
			value = formatcharacters(datavalue.value, options)
			if isvalid(options.pattern) then
				value = formatFromPattern(value, options)
			end
			return { value = value, item = itemqid }
		end
	end

	local itemValue = formatEntityId(itemqid, options).value
	if isvalid(itemValue) then
		if isvalid(options.property1) and options.property1:upper():sub(1, 1) == "P" then
			local prop1value = get_property1(options, itemqid)
			if isvalid(prop1value) then
				prop1value = (options.property1pref or "") .. "" .. prop1value .. "" .. (options.property1suff or "")
				value = prop1value .. " " .. itemValue
				if isvalid(options.property1after) then
					value = itemValue .. prop1value
				end
			else
				value = itemValue
			end
			return { value = value, item = itemqid }
		elseif isvalid(options.propertyimage) then
			local p_f = options.propertyimageformatting or options.formattingpropertyimage
			local vas =
				formatStatements(
					{
						property = options.propertyimage,
						formatting = p_f,
						entityId = itemqid,
						rank = options.rank,
						pattern = options.pattern,
						size = options.size,
						image = options.image,
						noref = "t",
						avoidvalue = options.avoidvaluepropertyimage,
						firstvalue = "t",
						nolink = options.nolink
					}
				)
			if isvalid(vas) then
				return { value = vas }
			end
		elseif isvalid(options.property2) then
			local caca =
				formatStatements(
					{
						property = options.property2,
						entityId = itemqid,
						noref = options.noref,
						rank = options.rank,
						pattern = options.property2pattern,
						size = options.size,
						image = options.image,
						propertyimage = options.property3,
						firstvalue = "t"
					}
				)
			if isvalid(caca) then
				return { value = caca .. " " .. itemValue }
			end
		end
	end
	return { value = itemValue, item = itemqid }
end

function formatwikibaseproperty(datavalue, datatype, options)
	--[[  datatype	wikibase-property	]]
	local tid = ""
	if isvalid(options.formatting) then
		if options.formatting == "raw" then
			tid = datavalue.value.id
		end
	else
		tid = formatEntityId(datavalue.value.id, options).value
	end
	return { value = tid }
end

function formattabulardata(datavalue, datatype, options)
	--[[  tabular-data ]]
	local data = "[[commons:" .. datavalue.value .. "|" .. datavalue.value .. "]]"
	return { value = data }
end

function formatgeoshape(datavalue, datatype, options)
	--[[  geo-shape	 ]]
	local shape = "[[commons:" .. datavalue.value .. "|" .. datavalue.value .. "]]"
	return { value = shape }
end

function formatcommonsMedia(datavalue, datatype, options)
	local tid
	--[[ commonsMedia ]]
	local size = options.size or ""
	if isvalid(options.image) then -- return real image
		--tid = "[[ملف:" .. datavalue.value  .. "|".. (options.size or "20").."px|border]]"
		--if isvalid(options.center) then
		--tid = "[[ملف:" .. datavalue.value  .. "|".. (options.size or "20").."px|border|center]]"
		--end
		--tid = "[[ملف:" .. datavalue.value  .. "|".. (options.size or "60").."px|".."border".."]]"
		local params = { image = datavalue.value, maxsize = "280x330px", center = (options.center or "") }
		if isvalid(options.size) then
			params.size = size
		end
		if InfoboxImage == nil then
			InfoboxImage = require("Module:InfoboxImage")
		end
		tid = InfoboxImage.Infobox_Image(params)
	else
		tid = formatcharacters(datavalue.value, options)
	end
	return { value = tid }
end

function formatmath(datavalue, datatype, options)
	--[[datatype math ]]
	--return	{value=mw.text.tag("math", {}, "".. datavalue.value.."") } -- that doesn't work well
	local result = mw.getCurrentFrame():callParserFunction("#tag:math", datavalue.value)
	return { value = result }
end

function formatstring(datavalue, datatype, options)
	--[[  datatype string ]]
	local par = options.pattern
	local result = formatcharacters(datavalue.value, options)
	local tid = result

	if isvalid(options.stringpattern) then
		tid = mw.ustring.gsub(options.stringpattern, "$1", datavalue.value)
	elseif isvalid(par) then
		if par ~= "autourl" and par ~= "autourl2" and par ~= "autourl3" and par ~= "autourl4" then
			tid = formatFromPattern(result, options)
		end
	end
	return { value = tid }
end

function formatexternalid(datavalue, datatype, options)
	local result = formatcharacters(datavalue.value, options)
	if isntvalid(options.pattern) then
		return { value = result } --just return value
	end
	local patter =
		formatStatements({ property = "P1630", entityId = options.property, firstvalue = "t", noref = "t", rank = "all" }) -- get formatter URL

	local par = options.pattern
	local tid = result

	if isvalid(patter) then -- if P1630 are there
		local pp = formatFromPattern(datavalue.value, { pattern = patter })
		local plabel = mw.wikibase.getLabel(options.property) or pp
		local ppp = mw.ustring.gsub(pp, " ", "_")

		local results = {
			["autourl"] = ppp,                                 -- like http://example.com/$1.html
			["autourl2"] = "[" .. ppp .. " " .. datavalue.value .. "]", -- like [http://example.com/$1.html $1]
			["autourl3"] = "[" .. ppp .. " " .. ppp .. "]",    -- like [http://example.com/$1.html http://example.com/$1.html]
			["autourl4"] = "[" .. ppp .. " " .. plabel .. "]"
		}
		if results[par] then
			tid = results[par]
		else
			tid = formatFromPattern(result, options)
		end
	elseif isvalid(par) then
		if par ~= "autourl" and par ~= "autourl2" and par ~= "autourl3" and par ~= "autourl4" then
			tid = formatFromPattern(result, options)
		end
	end
	return { value = tid }
end

function formattime(datavalue, datatype, options)
	--[[  datatype	time  ]]
	local ModuleTime = require "Module:wikidata2/time"
	local timen = datavalue.value
	local tid = ModuleTime.getdate(timen, options)
	-- local tid = mw.getCurrentFrame():preprocess(mall)
	if isvalid(options.modifytime) then
		if options.modifytime == "q" then
			local mall = datavalue.value.time
			tid = mw.getCurrentFrame():preprocess(mall)
		elseif options.modifytime == "precision" then
			local mall = datavalue.value.precision
			tid = mw.getCurrentFrame():preprocess(mall)
		end
	end
	return { value = tid }
end

function formatcoordinate(datavalue, datatype, options)
	--[[  datatype	globe-coordinate  ]]
	--local GlobeCoordinate = require "Module:GlobeCoordinate"
	--return {value=GlobeCoordinate.newFromWikidataValue( datavalue.value ):toHtml()}
	if ModuleGlobes == nil then
		ModuleGlobes = require("Module:Wikidata2/Globes")
	end
	local coord = datavalue.value
	local globe = datavalue.value.globe
	local globe2 = ModuleGlobes[globe] or ""
	local results = {
		["latitude"] = coord.latitude,
		["longitude"] = coord.longitude,
		["dimension"] = coord.dimension,
		["precision"] = coord.precision,
		["globe"] = globe:match("Q%d+"),
		["globe2"] = globe2
	}

	local pro = options.formatting and results[options.formatting]
	if pro == nil then
		pro =
			mw.getCurrentFrame():preprocess(
				"{{ {{{|safesubst:}}}#invoke:Coordinates|coord" ..
				"|" .. coord.latitude ..
				"|" .. coord.longitude ..
				"|display=inline" ..
				"|globe:" .. globe2 .. "_type:landmark" ..
				"|format=" .. (options.formatcoord or "") .. "}}"
			) .. catewikidatainfo(options)
	end

	return { value = pro }
end

function formatquantity(datavalue, datatype, options)
	--[[  datatype quantity	 ]]
	local amount, unit = datavalue.value.amount, datavalue.value.unit
	amount = mw.ustring.gsub(amount, "+", "")
	if unit then
		unit = unit:match("Q%d+")
	end
	if formatera == nil then
		formatera = require("Module:Wikidata2/Math")
	end
	local number = formatera.newFromWikidataValue(datavalue.value)
	mw.log("number: " .. number)
	local unitraw = unit
	if unit then
		-- يتحقق اذا كان هناك اي اختصار لوحدة القياس
		--if lab and ( isntvalid(options.nounitshort) ) then
		if isvalid(options.unitshort) then
			local lab =
				options.label or formatStatements({ property = "P498", entityId = unit, firstvalue = "t", noref = "t" }) or
				formatStatements(
					{ property = "P5061", entityId = unit, firstvalue = "t", langpref = options.langpref, noref = "t" }
				) or
				""
			local s =
				formatEntityId(unit, { label = lab, enlabelcate = "t", nolink = (options.nounitlink or options.nolink) })
			unit = s.value
		else
			local s = formatEntityId(unit, { nolink = options.nounitlink, enlabelcate = "t" })
			unit = s.value
		end
	end
	if options.formatcharacters and options.formatcharacters == "formatnum" then
		amount = make_format_num(amount)
	end
	local Value = amount .. " " .. (unit or "")
	if isvalid(options.nounit) then
		Value = amount
	end
	return { value = Value, amount = amount, unit = unit, unitraw = unitraw }
end

function formaturl(datavalue, datatype, options)
	--[[  datatype	url	 ]]
	local label = options.label
	if isvalid(options.urllabel) then
		label = options.urllabel
	end
	local va = mw.ustring.gsub(datavalue.value, " ", "_")
	if label == nil and options.property == "P856" then
		label = "الموقع الرسمي"
	end
	if isvalid(options.displayformat) == "weblink" then
		if weblink == nil then
			weblink = require("Module:Weblink")
		end
		return { value = weblink.makelink(va) }
	end
	if isvalid(options.formatting) == "raw" then
		return { value = va }
	end
	local pro = va
	if isvalid(label) then
		pro = "[" .. va .. " " .. label .. "]"
	end
	return { value = pro }
end

function formatmonolingualtext(datavalue, datatype, options) -- showlang
	local text = datavalue.value.text
	if isvalid(options.textformat) == "text" then
		return { value = text }
	end
	if Moduletext == nil then
		Moduletext = require "Module:wikidata2/monolingualtext"
	end
	local tid = Moduletext._main(datavalue, datatype, options)
	return { value = tid }
end

function Labelfunction(qid, arlabel, options) -- label with no arwiki sitelink
	local value
	local cat = ""
	local en_label = mw.wikibase.getLabel(qid) or ""

	if isvalid(options.illwd2) then
		if Moduleill_wd2 == nil then
			Moduleill_wd2 = require("Module:Wikidata2/Ill-WD2")
		end
		value = Moduleill_wd2.Ill_WD2_label(qid, arlabel, options)
		--
	elseif isvalid(arlabel) then
		value = arlabel
		--
	elseif isntvalid(options.justarabic) then
		local use_en_label = isvalid(options.enlabelcate) or isvalid(options.use_en_labels)
		if isvalid(en_label) and use_en_label then
			value = en_label
		end
	end

	return { value = value or "", cat = cat }
end

function formatEntityId(qid, options)
	local labeloption = options.label
	local label = ""
	local value
	local arlabel = labelIn("ar", qid) or "" -- The arabic label
	local link = mw.wikibase.getSitelink(qid)

	if isvalid(labeloption) then
		label = labeloption
	elseif isvalid(arlabel) then
		--mw.log("arlabel" .. arlabel)
		label = arlabel
	elseif isvalid(link) then
		label = link
		arlabel = link
	end

	if isvalid(link) then
		-- elseif isvalid(arlabel) then
		local linklabel = isvalid(label) or link
		if (isntvalid(options.nolink)) then
			value = "[[:" .. link .. "|" .. formatcharacters(linklabel, options) .. "]]"
			label = linklabel
		else
			value = formatcharacters(linklabel, options)
			label = linklabel
		end
	else
		local va = Labelfunction(qid, arlabel, options)
		label = va.value
		value = va.value -- .. va.cat
	end
	return { value = value or "", label = label or "" }
end

function sitelink(id, wikisite)
	local site = wikisite or mw.wikibase.getGlobalSiteId() -- "arwiki"
	local link = ""
	--local link = mw.wikibase.getSitelink( id, site ) or ""

	local entity = mw.wikibase.getEntity(id)
	if
		entity and entity.sitelinks and entity.sitelinks["" .. site .. ""] and entity.sitelinks["" .. site .. ""].site and
		entity.sitelinks["" .. site .. ""].title
	then
		if entity.sitelinks["" .. site .. ""].site == site then
			link = entity.sitelinks["" .. site .. ""].title
		end
	end
	return link
end

function p.formatAndCat(args)
	if args == nil then
		return nil
	end

	Frame_args = args
	args.linkback = args.linkback or true
	args.addcat = true
	if isvalid(args.value) and args.value == "-" then
		return nil
	end
	if isvalid(args.value) then
		local val = args.value .. addTrackingCategory(args)
		val = p.addLinkBack(val, args.entity, args.property)
		return val
	end
	return p.formatStatementsFromLua(args)
end

function p.getEntity(id)
	if type(id) == "table" then
		return id
	end
	return getEntityFromId(id)
end

function p.translate(str, rep1, rep2)
	str = i18n[str] or str
	if rep1 and (type(rep1) == "string") then
		str = str:gsub("$1", rep1)
	end
	if rep2 and (type(rep2) == "string") then
		str = str:gsub("$2", rep2)
	end
	return str
end

function p.getId(snak)
	if (snak.snaktype == "value") then
		if snak.datavalue.type == "wikibase-entityid" then
			return "Q" .. snak.datavalue.value["numeric-id"]
		end
	end
end

function p.addLinkBack(str, id, property)
	if not id then
		id = p.getEntity()
	end
	if not id then
		return str
	end
	if type(property) == "table" then
		property = property[1]
	end
	if type(id) == "table" then
		id = id.id
	end
	local class = ""
	if property then
		class = "wd_" .. string.lower(property)
	end
	local icon = "[[ملف:Blue pencil.svg|%s|10px|baseline|class=noviewer|link=%s]]"
	local title = i18n["see-wikidata-value"]
	local url = mw.uri.fullUrl("d:" .. id, "uselang=ar")
	url.fragment = property
	url = tostring(url)
	local v =
		mw.html.create("span"):addClass(class):wikitext(str):tag("span"):addClass("noprint wikidata-linkback"):css(
			"padding-left",
			"0.5em"
		):wikitext(icon:format(title, url)):allDone()
	return tostring(v)
end

function p.formatSnak(snak, options)
	return formatSnak(snak, options)
end

function p.formatEntityId(entityId, options)
	return formatEntityId(entityId, (options or {}))
end

function p.formatStatements(frame, key)
	if frame.args then
		if type(key) == "table" and key ~= {} then
		else
			Frame_args = frame.args
		end
	end
	--[[ The main function ]]
	local args = frame.args
	--If a value if already set, use it
	if isvalid(args.value) then
		return args.value
	end
	local wd_arg = frame:getParent().args["ويكي بيانات"] or
		frame.args["ويكي بيانات"] -- arg used to ban wikidata value
	if isvalid(wd_arg) == "لا" then
		return ""
	end

	local valuesnumb = 0
	local s
	if isvalid(args.returnnumberofvalues) then
		s, valuesnumb = formatStatements(frame.args, key)
		mw.log("valuesnumb: " .. valuesnumb)
		return s, valuesnumb
	end

	local prop = formatStatements(args, key)

	if isvalid(prop) then
		if isvalid(args.mainprefix) then -- mainprefix
			prop = args.mainprefix .. prop
		end
		if isvalid(args.mainsuffix) then -- mainsuffix
			prop = prop .. args.mainsuffix
		end
		if isvalid(args.addTrackingCat) then -- add tracking cat
			prop = prop .. addTrackingCategory(frame.args)
		end
		if isvalid(args.mainsuffixAfterIcon) then -- another suffix but after wikidata icon
			prop = prop .. args.mainsuffixAfterIcon
		end
	else
		if isvalid(args.NoPropValue) then -- value if no local value and no wikidata value
			prop = args.NoPropValue
		end
	end
	return prop
end

function p.formatStatementsFromLua(options, key) --	 main function but to use from lua module
	if options then
		if type(key) == "table" and key ~= {} then
		else
			Frame_args = options
		end
	end

	--If a value if already set, use it
	if isvalid(options.value) then
		return options.value
	end
	local valuesnumb = 0
	local s = formatStatements(options, key)
	if isvalid(options.returnnumberofvalues) then
		s, valuesnumb = formatStatements(options, key)
	end
	if isntvalid(s) then
		s = nil
	end
	if isvalid(s) then
		if isvalid(options.mainprefix) then -- mainprefix
			s = options.mainprefix .. s
		end
		if isvalid(options.mainsuffix) then -- mainsuffix
			s = s .. options.mainsuffix
		end
		if isvalid(options.addTrackingCat) then -- add tracking cat
			s = s .. addTrackingCategory(options)
		end
		if isvalid(options.mainsuffixAfterIcon) then -- another suffix but after wikidata icon
			s = s .. options.mainsuffixAfterIcon
		end
	else
		if isvalid(options.NosValue) then -- value if no local value and no wikidata value
			s = options.NosValue
		end
	end
	if isvalid(options.returnnumberofvalues) then
		--	mw.log( "valuesnumb: " .. valuesnumb )
		return s, valuesnumb
	end
	return s
end

function p.getLabel(entity, lang)
	return labelIn(lang, entity)
end

-- Return the site link for a given data item and a given site (the current site by default)

function p.getSiteLink(frame)
	local site = frame.args[2] or frame.args.site
	local id = frame.args[1] or frame.args.id
	local count = frame.args.countsitelinks
	if isntvalid(id) then
		if isvalid(frame.args.page) then
			id = mw.wikibase.getEntityIdForTitle(frame.args.page)
		end
	end
	if isvalid(count) then
		return p.countSiteLinks(id)
	end
	local link = sitelink(id, site)
	if isvalid(link) then
		return link
	end
end

-- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata
function p.pageId(frame)
	return mw.wikibase.getEntityIdForCurrentPage()
end

function p.descriptionIn(frame)
	local langcode = frame.args[1] or frame.args["lang"]
	local id = frame.args[2] or frame.args["id"]
	return descriptionIn(langcode, id)
end

function p.labelIn(frame)
	local langcode = frame.args[1] or frame.args["lang"]
	local id = frame.args[2] or frame.args["id"]
	return labelIn(langcode, id)
end

function p.EntityIdForTitle(frame)
	local title = frame.args[1]
	local str = mw.wikibase.getEntityIdForTitle(title)
	--mw.log(str)
	return str
end

function p.Qidfortitleandwiki(frame)
	local title = mw.text.trim(frame.args[1] or "")
	local wiki = mw.text.trim(frame.args[2] or "")
	local str = mw.wikibase.getEntityIdForTitle(title, wiki)
	return str
end

function p.isSubclass(frame)
	Moduledump = require "Module:wikidata2/dump"
	return Moduledump.isSubclass(frame)
end

function p.ViewSomething(frame)
	Moduledump = require "Module:wikidata2/dump"
	return Moduledump.ViewSomething(frame)
end

function p.Dump(frame)
	Moduledump = require "Module:wikidata2/dump"
	return Moduledump.Dump(frame)
end

return p