local Anims = {}

-- Load animations after the languages for translation purposes
hook.Add("loadCustomDarkRPItems", "loadAnimations", function()
	Anims[ACT_GMOD_GESTURE_BOW] = DarkRP.getPhrase("bow")
	Anims[ACT_GMOD_TAUNT_MUSCLE] = DarkRP.getPhrase("sexy_dance")
	Anims[ACT_GMOD_GESTURE_BECON] = DarkRP.getPhrase("follow_me")
	Anims[ACT_GMOD_TAUNT_LAUGH] = DarkRP.getPhrase("laugh")
	Anims[ACT_GMOD_TAUNT_PERSISTENCE] = DarkRP.getPhrase("lion_pose")
	Anims[ACT_GMOD_GESTURE_DISAGREE] = DarkRP.getPhrase("nonverbal_no")
	Anims[ACT_GMOD_GESTURE_AGREE] = DarkRP.getPhrase("thumbs_up")
	Anims[ACT_GMOD_GESTURE_WAVE] = DarkRP.getPhrase("wave")
	Anims[ACT_GMOD_TAUNT_DANCE] = DarkRP.getPhrase("dance")
end)

function DarkRP.addPlayerGesture(anim, text)
	if !anim then DarkRP.error("Argument #1 of DarkRP.addPlayerGesture (animation/gesture) does !exist.", 2) end
	if !text then DarkRP.error("Argument #2 of DarkRP.addPlayerGesture (text) does !exist.", 2) end

	Anims[anim] = text
end

function DarkRP.removePlayerGesture(anim)
	if !anim then DarkRP.error("Argument #1 of DarkRP.removePlayerGesture (animation/gesture) does !exist.", 2) end

	Anims[anim] = nil
end

local function physGunCheck(ply)
	local hookName = "darkrp_anim_physgun_" .. ply:EntIndex()
	hook.Add("Think", hookName, function()
		if IsValid(ply) and
			ply:Alive() and
			ply:GetActiveWeapon():IsValid() and
			ply:GetActiveWeapon():GetClass() == "weapon_physgun" and
			ply:KeyDown(IN_ATTACK) and
			(ply:GetAllowWeaponsInVehicle() or !ply:InVehicle()) then
			local ent = ply:GetEyeTrace().Entity
			if IsValid(ent) and ent:IsPlayer() and !ply.SaidHi then
				ply.SaidHi = true
				ply:DoAnimationEvent(ACT_SIGNAL_GROUP)
			end
		else
			if IsValid(ply) then
				ply.SaidHi = nil
			end
			hook.Remove("Think", hookName)
		end
	end)
end

hook.Add("KeyPress", "darkrp_animations", function(ply, key)
	if key == IN_ATTACK then
		local weapon = ply:GetActiveWeapon()

		if weapon:IsValid() then
			local class = weapon:GetClass()

			-- Saying hi/hello to a player
			if class == "weapon_physgun" then
				physGunCheck(ply)
			end
		end
	end
end)

if CLIENT then
	surface.CreateFont("play_anim", {font = "Trebuchet MS", size = 22, weight = 1000, blursize = 0, scanlines = 0, antialias = true})
end

local animation_time, animation_delay, gesture = 0, 0, ""
local function DrawProgressBar(label, color, filled)
	filled = math.Clamp(filled, 0, 1)
	local w, h = 200, 20
	local centerx, centery = ScrW() / 2, ScrH() - 130
	local x, y = centerx - w / 2, centery - h / 2
	surface.SetDrawColor(Color(255, 255, 255, 200))
	surface.DrawOutlinedRect(x, y, w, h)
	surface.SetDrawColor(color)
	surface.DrawRect(x + 2, y + 2, (w - 4) * filled, h - 4)
	surface.SetDrawColor(color)
	surface.DrawRect(x + 2, y + 2, (w - 4) * filled, h - 4)
	draw.SimpleTextOutlined(label, "play_anim", centerx, centery - 1, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 1, color_black)
end

local function ProgressDraw()
	local curtime = CurTime()
	local progress = (curtime - animation_time) / animation_delay
	DrawProgressBar(gesture, Color(0, 175, 0, 150), progress)

	if progress >= 1 then
		hook.Remove("HUDPaint", "DarkRP_DoAnimation")
	end
end

if SERVER then
	local function CustomAnim(ply, cmd, args)
		if !IsValid(ply) then return end

		local wep = ply:GetActiveWeapon()
		if !wep:IsValid() or wep:GetClass() != "keys" then return end
		if ply:InVehicle() and !ply:GetAllowWeaponsInVehicle() then return end

		local Gesture = tonumber(args[1] or 0)
		if !Anims[Gesture] then return end

		local RP = RecipientFilter()
		RP:AddAllPlayers()

		umsg.Start("_DarkRP_CustomAnim", RP)
			umsg.Entity(ply)
			umsg.Short(Gesture)
		umsg.End()
	end
	concommand.Add("_DarkRP_DoAnimation", CustomAnim)
	return
end

local function CustomAnimation(um)
	local ply = um:ReadEntity()
	local act = um:ReadShort()
	if !IsValid(ply) then return end
	ply:AnimRestartGesture(GESTURE_SLOT_CUSTOM, act, true)

	if ply == LocalPlayer() then
		local curtime = CurTime()
		animation_time = curtime
		local seq_id = ply:SelectWeightedSequence(act)
		animation_delay = ply:SequenceDuration(seq_id)
		gesture = Anims[act]

		hook.Add("HUDPaint", "DarkRP_DoAnimation", ProgressDraw)
	end
end
usermessage.Hook("_DarkRP_CustomAnim", CustomAnimation)

local function KeysAnims(um)
	local ply = um:ReadEntity()
	local act = um:ReadString()

	if !IsValid(ply) then return end
	ply:AnimRestartGesture(GESTURE_SLOT_CUSTOM, act == "usekeys" and ACT_GMOD_GESTURE_ITEM_PLACE or ACT_HL2MP_GESTURE_RANGE_ATTACK_FIST, true)
end
usermessage.Hook("anim_keys", KeysAnims)

if CLIENT then
	local function LoadFont()
		screenWidth = ScrW()
		screenHeight = ScrH()

		surface.CreateFont("AnimSWEP.Base", {
			font = "Roboto",
			size = screenHeight * 0.0245,
			weight = 500,
		})
	end
	LoadFont()

	hook.Add("OnScreenSizeChanged", "AnimationSWEP.OnScreenSizeChanged", LoadFont)

	local MAT_Gesture = Material("edgehud/icon_gesture.png", "smooth")
	local edgeWidth = 2
	local function DrawEdges(x, y, width, height, edgeSize)
		surface.DrawRect(x, y, edgeSize, edgeWidth)
		surface.DrawRect(x, y + edgeWidth, edgeWidth,edgeSize - edgeWidth)
		local XRight = x + width
		surface.DrawRect(XRight - edgeSize, y, edgeSize, edgeWidth)
		surface.DrawRect(XRight - edgeWidth, y + edgeWidth, edgeWidth, edgeSize - edgeWidth)
		local YBottom = y + height
		surface.DrawRect(XRight - edgeSize, YBottom - edgeWidth, edgeSize, edgeWidth)
		surface.DrawRect(XRight - edgeWidth, YBottom - edgeSize, edgeWidth, edgeSize - edgeWidth)
		surface.DrawRect(x, YBottom - edgeWidth, edgeSize, edgeWidth)
		surface.DrawRect(x, YBottom - edgeSize, edgeWidth, edgeSize - edgeWidth)
	end

	local gestureFrame
	local function AnimationMenu(ply)
		if IsValid(gestureFrame) then return end
		local wep = ply:GetActiveWeapon()
		if !wep:IsValid() or wep:GetClass() != "keys" then return end
		if ply:InVehicle() and !ply:GetAllowWeaponsInVehicle() then return end
		hook.Add("HUDShouldDraw","EdgeHUD:RemoveCrosshair_GestureMenu",function(name)
			if name == "CHudCrosshair" then return false end
		end)
		local gesturePanels = {}
		gestureFrame = vgui.Create("DPanel")
		gestureFrame:SetSize(screenWidth, screenHeight)
		gestureFrame:Center()
		gestureFrame:MakePopup()
		gestureFrame:ParentToHUD()
		gestureFrame.Paint = function()
		end
		gestureFrame.OnRemove = function()
			hook.Remove("HUDShouldDraw", "EdgeHUD:RemoveCrosshair_GestureMenu")
		end
		local closeCooldown = CurTime() + 0.2
		local allowClose = false
		gestureFrame.Think = function()
			if input.IsKeyDown(KEY_R) then
				if closeCooldown > CurTime() or !allowClose then return end
				gestureFrame:Remove()
			else
				allowClose = true
			end
		end
		for k, v in pairs(Anims) do
			local gestureButton = vgui.Create("DButton", gestureFrame)
			gestureButton:SetText(v)
			gestureButton.DoClick = function()
				RunConsoleCommand("_DarkRP_DoAnimation", k)
				gestureFrame:Remove()
			end
			table.insert(gesturePanels, gestureButton)
		end
		local radius = ScrH() * 0.4
		local seg = table.Count(gesturePanels)
		local circleData = {}
		for i = 1, seg do
			local a = math.rad((i / seg) * -360)
			table.insert(circleData, {x = screenWidth / 2 + math.sin(a) * radius, y = screenHeight / 2 + math.cos(a) * radius})
		end
		local buttonWidth = ScrH() * 0.18
		local buttonHeight = ScrH() * 0.075
		local iconSize = buttonHeight * 0.35
		local closeButtonGesture = vgui.Create("DButton", gestureFrame)
		closeButtonGesture:SetText("Schließen")
		closeButtonGesture:SetSize(ScrH() * 0.12, ScrH() * 0.04)
		closeButtonGesture:SetPos(ScrW() / 2 - closeButtonGesture:GetWide() / 2, ScrH() / 2 - closeButtonGesture:GetTall() / 2)
		closeButtonGesture.DoClick = function()
			gestureFrame:Remove()
		end
		table.insert(gesturePanels, closeButtonGesture)
		for k, v in pairs(gesturePanels) do
			v:SetFont("AnimSWEP.Base")
			v:SetTextColor(color_white)
			v.Paint = function(s, w, h)
				surface.SetDrawColor(s:IsHovered() and Color(80, 80, 80, 200) or Color(50, 50, 50, 200))
				surface.DrawRect(0, 0, w, h)
				surface.SetDrawColor(Color(255, 255, 255, 50))
				surface.DrawOutlinedRect(0, 0, w, h)
				surface.SetDrawColor(Color(255, 255, 255, 120))
				DrawEdges(0, 0, w, h, 8)
			end
			if circleData[k] then
				v:SetSize(buttonWidth, buttonHeight)
				v:SetPos(circleData[k].x - v:GetWide() / 2, circleData[k].y - v:GetTall() / 2)
				local oldPaint = v.Paint
				v.Paint = function(s, w, h)
					oldPaint(s, w, h)
					surface.SetDrawColor(color_white)
					surface.SetMaterial(MAT_Gesture)
					surface.DrawTexturedRect(w / 2 - iconSize / 2, h * 0.15, iconSize, iconSize)
					draw.SimpleText(v:GetValue(), "AnimSWEP.Base", w / 2, h * 0.85, color_white ,TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM)
					return true
				end
			end
		end
	end
	concommand.Add("_DarkRP_AnimationMenu", AnimationMenu)
end