MG_LevelSys = MG_LevelSys or {}
MG_LevelSys_Config = MG_LevelSys_Config or {}

MG_LevelSys.PlayerSkills = MG_LevelSys.PlayerSkills or {}

DarkRP.registerDarkRPVar("xp", net.WriteFloat, net.ReadFloat)
DarkRP.registerDarkRPVar("level", fp{fn.Flip(net.WriteInt), 32}, fp{net.ReadInt, 32})
DarkRP.registerDarkRPVar("points", fp{fn.Flip(net.WriteInt), 32}, fp{net.ReadInt, 32})

local meta = FindMetaTable("Player")

local getDarkRPVar = meta.getDarkRPVar

function meta:getLevel()
	return getDarkRPVar(self, "level") or 1
end

function meta:getXP()
	return getDarkRPVar(self, "xp") or 0
end

local getLevel = meta.getLevel

function meta:getMaxXP()
	local level = getLevel(self) or 1
	return math.Round(MG_LevelSys_Config.DefaultXP * (1 + (MG_LevelSys_Config.XPMult - 1) * (level - 1)))
end

function meta:hasLevel(level)
	return getLevel(self) >= level
end

function meta:getPoints()
	return getDarkRPVar(self, "points") or 0
end

local getPoints = meta.getPoints

function meta:hasPoints(points)
	return getPoints(self) >= points
end

function meta:getSkills()
	return (SERVER and MG_LevelSys.PlayerSkills[self]) or (CLIENT and MG_LevelSys.PlayerSkills) or {}
end

local getSkills = meta.getSkills

function meta:hasSkill(id)
	local skills = getSkills(self)
	return skills[id] and true or false
end

function meta:hasSkillEquipped(id)
	local skills = getSkills(self)
	return skills[id] and skills[id][2] and true or false
end

function meta:getSkillTier(id)
	local skills = getSkills(self)
	return skills[id] and tonumber(skills[id][1]) or 0
end

local Team = meta.Team

function meta:getSkillPercentage(id, skip, update)
	local skills = getSkills(self)

	local skill_cfg = MG_LevelSys.SortedSkills[id]
	if !skill_cfg or (!skip and (!skills[id] or !skills[id][2] or Team(self) == TEAM_EVENT)) then return 0 end -- Für Events verbieten

	local max_tier = skill_cfg.max or MG_LevelSys_Config.MaxTiers

	local perc = (skill_cfg.perc * (math.min(max_tier, ((tonumber(skills[id] and skills[id][1] or 0) or 0) + (update and 1 or 0))) / max_tier)) / 100

	perc = hook.Run("MG_LevelSys:SkillPercentageMult", self, perc, id, skip, update) or perc

	return perc
end

function meta:getResetRefund()
	local refund = 0
	for skill_id, data in pairs(getSkills(self)) do
		local skill_cfg = MG_LevelSys.SortedSkills[skill_id]
		if skill_cfg then
			for i=1, data[1] do
				refund = refund + (i * (MG_LevelSys_Config.PricePerTier * (skill_cfg.pricemult or 1)))
			end
		end
	end
	refund = math.floor(refund) * MG_LevelSys_Config.RefundMult
	return refund
end

function meta:getTradeMult()
	return MG_LevelSys_Config.XPCost * (1 - self:getSkillPercentage("general_merchant") - self:getSkillPercentage("general_merchant2"))
end

MG_LevelSys.SortedSkills = {}
MG_LevelSys.MaxSkillLevel = 1
MG_LevelSys.SkillCount = 0

timer.Simple(0, function()
	for cat, contents in pairs(MG_LevelSys_Config.Skills) do
		for _, v in ipairs(contents) do
			MG_LevelSys.SortedSkills[v.id] = v
			MG_LevelSys.MaxSkillLevel = MG_LevelSys.MaxSkillLevel + (v.max or MG_LevelSys_Config.MaxTiers)
			MG_LevelSys.SkillCount = MG_LevelSys.SkillCount + 1
		end
	end

	print("[MG Levelsystem] "..MG_LevelSys.SkillCount.." skills until level "..MG_LevelSys.MaxSkillLevel.." successfully loaded.")
end)