local p = {}

function findInTable(vObject, tObject)
	if type(tObject) == type({}) then
		for i, v in ipairs(tObject) do
			if mw.dumpObject(v) == mw.dumpObject(vObject) then
				return mw.dumpObject(i)
			end
		end
	end
	return nil
end

function getArgs(tFrame, bPreferParent, bAppend)
	local t, tI, tP, tPI = {}, {}, {}, {}
	if type(tFrame) == type({}) then
		if 
			(type(tFrame.getParent) == type(type)) and 
			(type(tFrame:getParent()) == type({})) and
			(type(tFrame:getParent().args) == type({}))
		then
			for i, v in pairs(tFrame:getParent().args) do
				if
					(type(i) == type(0)) and (i == math.floor(i)) and (i > 0)
				then
					tPI[i] = v
				else
					tP[i] = v
				end
			end
		end
		if type(tFrame.args) == type({}) then
			for i, v in pairs(tFrame.args) do
				if
					(type(i) == type(0)) and (i == math.floor(i)) and (i > 0)
				then
					tI[i] = v
				else
					t[i] = v
				end
			end
		end
	end
	if bPreferParent then
		tI, tPI = tPI, tI
		t, tP = tP, t
	end
	for i, v in pairs(t) do
		tP[i] = v
	end
	t = tP
	if bAppend then
		for i = 1, table.maxn(tPI) do
			tI[table.maxn(tI) + 1] = tPI[i]
		end
	else
		for i, v in pairs(tI) do
			tPI[i] = v
		end
		tI = tPI
	end
	for i, v in pairs(tI) do
		t[i] = v
	end
	return t
end

function getError(sDisplay, sCategory)
	sDisplay = sDisplay and tostring(sDisplay) or ""
	sCategory = sCategory and "[[Category:" .. tostring(sCategory) .. "]]" or ""
	return '<span class="error">' .. sDisplay .. sCategory .. '</span>'
end

function getInfo()
	return {
		modulename = "Module:Aux";
	}
end

function getLang()
	return mw.language.getContentLanguage():getCode()
end

function writeDate(sISO, sEtc)
	if not (type(sISO) == type("")) then
		return nil
	end
	sISO = mw.ustring.match(sISO, "%S.*")
	local sY = mw.ustring.match(sISO, "^[-]?[0-9]+")
	sY = (
		mw.ustring.gsub(sY, "[0-9]*", "") ..
		mw.ustring.gsub(mw.ustring.sub(mw.ustring.gsub(
			sY, "[^0-9]*", ""
		), 1, -2), "^0*", "") ..
		mw.ustring.sub(mw.ustring.gsub(sY, "[^0-9]*", ""), -1)
	)
	sISO = mw.ustring.gsub(sISO, "^[-]?[0-9]+", "")
	if not tonumber(sY) then
		return nil
	end
	sISO = mw.ustring.gsub(sISO, "^%s*[-]%s*", "")
	local nM = tonumber(mw.ustring.match(sISO, "^[0-9]+"))
	sISO = mw.ustring.gsub(sISO, "^[0-9]+", "")
	if not nM then
		if mw.ustring.match(sISO, "^%s*$") then
			if not (mw.ustring.gsub(sY, "[0-9]+", "") == "") then
				return mw.ustring.gsub(sY, "^[^0-9]+", "") .. " v. Chr" .. (
					sEtc and mw.ustring.match(sEtc, "^.") == "." and "" or "."
				)
			else
				return sY
			end
		else
			return nil
		end
	elseif nM > 12 then
		return nil
	end
	sISO = mw.ustring.gsub(sISO, "^%s*[-]%s*", "")
	local nD = tonumber(mw.ustring.match(sISO, "^[0-9]+"))
	sISO = mw.ustring.gsub(sISO, "^[0-9]+", "")
	local tM = {}
	for i = 1, 12 do
		tM[i] = mw.getCurrentFrame():callParserFunction(
			"#time", "F", "1111-" .. i, getLang()
		)
	end
	local s = ""
	if not (mw.ustring.gsub(sY, "[0-9]+", "") == "") then
		s = s .. mw.ustring.gsub(sY, "^[^0-9]+", "") .. " v. Chr" .. (
			sEtc and mw.ustring.match(sEtc, "^.") == "." and "" or "."
		)
	else
		s = s .. sY
	end
	if not nD then
		if mw.ustring.match(sISO, "^%s*$") then
			return tM[nM] .. " " .. s
		else
			return nil
		end
	elseif nD > ({
		31;
		(tonumber(mw.ustring.sub(sY,-2)) % 4 == 0) and 29 or 28;
		31;
		30;
		31;
		30;
		31;
		31;
		30;
		31;
		30;
		31;
	})[nM] then
		return nil
	else
		local tMm = tM
		if mw.ustring.match(sISO, "^%s*$") then
			return nD .. ". " .. tMm[nM] .. " " .. s
		else
			return nil
		end
	end
end

function writeLang(sLang)
	if (not sLang) or sLang == getLang() then
		return nil
	else
		sLang = mw.language.fetchLanguageName(sLang, getLang()) or sLang
	end
	return sLang
end

function p.evalAnd(frame)
	local vR = ""
	if type(frame) == type({}) then
		if 
			(type(frame.getParent) == type(type)) and 
			(type(frame:getParent()) == type({})) and
			(type(frame:getParent().args) == type({}))
		then
			for i, v in ipairs(frame:getParent().args) do
				if v and not (v == "") then
					vR = v
				else
					return ""
				end
			end
		end
		if type(frame.args) == type({}) then
			for i, v in ipairs(frame.args) do
				if v and not (v == "") then
					vR = v
				else
					return ""
				end
			end
		end
	end
	return vR
end

function p.evalOr(frame)
	if type(frame) == type({}) then
		if 
			(type(frame.getParent) == type(type)) and 
			(type(frame:getParent()) == type({})) and
			(type(frame:getParent().args) == type({}))
		then
			for i, v in ipairs(frame:getParent().args) do
				if v and not (v == "") then
					return v
				end
			end
		end
		if type(frame.args) == type({}) then
			for i, v in ipairs(frame.args) do
				if v and not (v == "") then
					return v
				end
			end
		end
	end
	return ""
end

function p.findValue(frame)
	local tArg = getArgs(frame)
	if tArg["value"] then
		return findInTable(tArg["value"], tArg) or ""
	end
	return ""
end

function p.getWebRef(frame)
	local tArg = getArgs(frame)
	if tArg["url"] and tArg["title"] and writeDate(tArg["accessdate"]) then
		local vR = ""
		if tArg["author"] then
			vR = vR .. tArg["author"] .. ": "
		end
		vR = vR .. "''[" .. tArg["url"] .. " " .. tArg["title"] .. "]''"
		if tArg["cotitle"] then
			vR = vR .. " " .. tArg["cotitle"]
		end
		vR = vR .. "."
		if tArg["work"] then
			vR = vR .. " In: ''" .. tArg["work"] .. "''."
		end
		if tArg["publisher"] then
			vR = vR .. " " .. tArg["publisher"] .. "."
		end
		if tArg["pages"] then
			vR = vR .. " S. " .. tArg["pages"] .. "."
		end
		if writeLang(tArg["language"]) or tArg["format"] then
			local s = ""
			if writeLang(tArg["language"]) then
				s = s .. writeLang(tArg["language"])
			end
			if tArg["format"] then
				s = s .. (s == "" and "" or ", ") .. tArg["format"]
			end
			vR = vR .. " (" .. s .. ")"
		end
		if writeDate(tArg["date"]) then
			vR = vR .. " " .. writeDate(tArg["date"], ".") .. "."
		end
		vR = vR .. " Ofgeruff den " .. writeDate(tArg["accessdate"], ".") .. "."
		if tArg["archiveurl"] then
			local s = ""
			if writeDate(tArg["archivedate"]) then
				s = s .. " den " .. writeDate(tArg["archivedate"], ".")
			end
			vR = vR .. " [" .. tArg["archiveurl"] .. " Archivéiert]" .. s .. "."
		end
		if tArg["quote"] then
			vR = vR .. " „" .. tArg["quote"] .. "“"
		end
		if tArg["comment"] then
			vR = vR .. " " .. tArg["comment"]
		end
		return vR
	else
		return getError(
			"[[" .. getInfo().modulename .. "]]",
			"Seiten, die fehlerhafte Argumente in Vorlagenaufrufen verwenden"
		)
	end
end

function p.supplyWebRef(frame)
	local tArg = getArgs(frame)
	local t = {
		sub = getInfo().modulename .. "/Refs";
	}
	if tArg[1] then
		repeat
			t.subname = t.sub
			t.sub = require(t.sub)
			t.sub = (type(t.sub) == type(type)) and t.sub
			if t.sub then
				if (type(t.sub(tArg[1])) == type({})) then
					return getWebRef({args = t.sub(tArg[1])})
				end
				t.sub = (type(t.sub(tArg[1])) == type("")) and t.sub(tArg[1])
			end
		until not t.sub
	end
	t.sub = t.subname or t.sub
	return getError(
		"[[" .. t.sub .. "]]",
		"Seiten, die fehlerhafte Argumente in Vorlagenaufrufen verwenden"
	)
end

function p.testArgs(frame)
	local s = ""
	local tArg = getArgs(frame)
	tArg = getArgs(frame, tArg.prefer, tArg.append)
	for i, v in pairs(tArg) do
		if type(mw.text[tArg.mw1text]) == type(type) then
			v = mw.text[tArg.mw1text](v)
		end
		if type(mw.text[tArg.mw2text]) == type(type) then
			v = mw.text[tArg.mw2text](v)
		end
		if type(mw.getCurrentFrame()[tArg.mw0frame]) == type(type) then
			v = mw.getCurrentFrame()[tArg.mw0frame](mw.getCurrentFrame(), v)
		end
		s = s .. "|" .. i .. "=" .. mw.ustring.sub(
			v,
			tonumber(tArg.start) or 1,
			tonumber(tArg["end"]) or -1
		)
	end
	return s
end

function p.testLang(frame)
	local tArg = getArgs(frame)
	if tArg["code"] and tArg["func"] then
		local tLang = mw.getLanguage(tArg["code"])
		if tArg["func"] == "formatNum" then
			tArg[2] = {}
			for i, v in pairs(tArg) do
				if type(i) == type("") then
					tArg[2][i] = v
				end
			end
		elseif findInTable(tArg["func"], {
			"formatDuration";
			"getDurationIntervals";
		}) then
			tArg[1] = tonumber(tArg[1])
			tArg[2] = {}
			for i, v in pairs(tArg) do
				if type(i) == type("") then
					tArg[2][i] = v
				end
			end
		elseif findInTable(tArg["func"], {
			"convertPlural";
			"plural";
		}) then
			tArg[1] = tonumber(tArg[1])
		end
		return mw.dumpObject(tLang[tArg["func"]](
			tLang, tArg[1], tArg[2], tArg[3], tArg[4], tArg[5], tArg[6]
		))
	end
end

function p.unstripNoWikiRow(frame)
	local tArg = getArgs(frame)
	local s = ""
	if table.maxn(tArg) > 0 then
		local i = 0
		tArg["from"] = tArg["from"] or tArg["wouhier"]
		tArg["from"] = tonumber(tArg["from"]) or 1
		tArg["from"] = math.max(1, math.min(math.floor(
			tArg["from"]
		), table.maxn(tArg)))
		tArg["to"] = tArg["to"] or tArg["wouhin"]
		tArg["to"] = tonumber(tArg["to"]) or 1
		tArg["to"] = math.max(0, math.min(math.floor(
			tArg["to"]
		), table.maxn(tArg)))
		s = "|-"
		repeat
			if i > 0 then
				tArg[i] = tArg[i] or ""
				s = s .. "\n| " .. (
					(i == tArg["from"]) and
					mw.text.tag("tt", {}, tArg[i]) or
					tArg[i]
				) .. " "
			end
			if i == tArg["to"] then
				s = s .. "\n| " .. mw.getCurrentFrame():preprocess(
					mw.text.unstripNoWiki(tArg[tArg["from"]] or "")
				) .. " "
			end
			i = i + 1
		until i > table.maxn(tArg)
	end
	return s
end

return p