if SERVER then
	AddCSLuaFile()
end

game.AddAmmoType({name = "breach_charges", dmgtype = DMG_GENERIC})

if CLIENT then
	language.Add("breach_charges_ammo", "Türsprengladungen")

	SWEP.Slot = 3
	SWEP.SlotPos = 5
	SWEP.DrawCrosshair = false
end

SWEP.PrintName = "Türsprengladung"
SWEP.Author = "Modern Gaming"
SWEP.Instructions = "Linksklick, um die Türsprengladung anzubringen.\nLinksklick nach Anbringen einer Türsprengladung, um diese hochzusprengen."
SWEP.Purpose = "Hiermit können Türen aufgesprengt werden.\nFunktioniert nicht mit Fading Doors."
SWEP.Spawnable = true
SWEP.UseHands = true
SWEP.HoldType = "slam"
SWEP.ViewModel = Model("models/weapons/c_slam.mdl")
SWEP.WorldModel = Model("models/weapons/w_slam.mdl")
SWEP.PlaceSound = Sound("weapons/slam/mine_mode.wav")
SWEP.ClickSound = Sound("ui/buttonclick.wav")

SWEP.Primary.ClipSize = 1
SWEP.Primary.DefaultClip = 1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "breach_charges"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = ""

SWEP.DeploySpeed = 3
SWEP.DeployDetSpeed = 0.75
SWEP.DetonateSpeed = 0.25
SWEP.Range = 5000

SWEP.SupportsFadingDoors = true

if SERVER then
	hook.Add("canDropWeapon", "BreachCharge_DropDoorBreach", function(ply, wep)
		if !IsValid(wep) then return end
		if wep:GetClass() == "weapon_breach" and wep:Clip1() <= 0 and ply:GetAmmoCount("breach_charges") <= 0 then
			return false
		end
	end)
end

function SWEP:SetupDataTables()
	self:NetworkVar("Float", 0, "DeployTimer")
	self:NetworkVar("Float", 1, "DeployDetTimer")
	self:NetworkVar("Float", 2, "DetonateTimer")
	self:NetworkVar("Bool", 0, "Attaching")
	self:NetworkVar("Bool", 1, "DetActive")
	self:NetworkVar("Entity", 0, "Door")
	self:NetworkVar("Entity", 1, "Mine")
end

function SWEP:Initialize()
	self:SetHoldType(self.HoldType)
end

function SWEP:Deploy()
	self:PlayDefault()
	self:ResetConfig()
	if IsValid(self:GetMine()) then
		self:DeployDetonator()
	else
		self:SetDetActive(false)
	end
	self:SetHoldType(self.HoldType)
	return true
end

function SWEP:Holster()
	self:ResetConfig()
	return true
end

function SWEP:PrimaryAttack()
	local det_active = self:GetDetActive()
	if det_active and IsValid(self:GetMine()) and self:GetDetonateTimer() == 0 then
		self:EmitSound(self.ClickSound)
		self:SendWeaponAnim(ACT_SLAM_DETONATOR_DETONATE)
		self:SetDetonateTimer(CurTime() + self.DetonateSpeed)
		return
	end
	if !IsValid(self.Owner) or self:GetAttaching() or self:GetDeployDetTimer() > 0 or det_active then return end
	self.Owner:LagCompensation(true)
	local mg = self.Owner:GetEyeTrace()
	self.Owner:LagCompensation(false)
	local ent = mg.Entity
	if !IsValid(ent) or (self.SupportsFadingDoors and !ent:GetNW2Bool("isFadingDoor") and (!ent:isDoor() or !ent:isKeysOwnable())) or ent:GetNW2Bool("BreachAttached") then return end
	local distance = self.Owner:GetShootPos():DistToSqr(mg.HitPos)
	if distance > self.Range then return end
	local can_attach = hook.Run("BreachCharge_CanAttach", self.Owner, ent, self)
	if can_attach == false then return end
	self:SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH)
	self:SetAttaching(true)
	self:SetDeployTimer(CurTime() + self.DeploySpeed)
	self:SetDoor(ent)
	self:SetHoldType("pistol")
	hook.Run("BreachCharge_BeginAttach", self.Owner, ent, self)
end

function SWEP:SecondaryAttack()
end

function SWEP:Reload()
end

function SWEP:ResetConfig()
	self:SetDeployTimer(0)
	self:SetDeployDetTimer(0)
	self:SetDetonateTimer(0)
	self:SetAttaching(false)
	self:SetDetActive(false)
	self:SetDoor(NULL)
end

function SWEP:PlayDefault()
	self:SendWeaponAnim(ACT_SLAM_TRIPMINE_DRAW)
	self:SetNextPrimaryFire(CurTime() + self:SequenceDuration() * 0.8)
end

function SWEP:Detonate()
	self:ResetConfig()
	self:PlayDefault()
	if !SERVER then return end
	local mine = self:GetMine()
	if IsValid(mine) and mine.Explode then
		mine:Explode()
	end
end

function SWEP:DeployDetonator()
	self:SendWeaponAnim(ACT_SLAM_DETONATOR_DRAW)
	self:ResetConfig()
	self:SetDetActive(true)
	self:SetNextPrimaryFire(CurTime() + self:SequenceDuration())
end

function SWEP:ResetDeploy()
	self:ResetConfig()
	self:PlayDefault()
end

function SWEP:CheckReload()
	if self:Clip1() <= 0 and self.Owner:GetAmmoCount("breach_charges") > 0 then
		self:SetClip1(1)
		self.Owner:SetAmmo(self.Owner:GetAmmoCount("breach_charges") - 1, "breach_charges")
	end
end

function SWEP:CheckForRemoval(valid_check)
	if !SERVER or !IsValid(self.Owner) then return end
	if (valid_check and !IsValid(self:GetMine()) or !valid_check and true) and self:Clip1() <= 0 and self.Owner:GetAmmoCount("breach_charges") <= 0 then
		if self.Owner:GetActiveWeapon() == self then
			self.Owner:ConCommand("lastinv")
		end
		self.Owner:StripWeapon(self.ClassName)
		return false
	end
	self:CheckReload()
end

function SWEP:DoorBreachThink()
	if self:GetAttaching() then
		local deploy_timer = self:GetDeployTimer()
		if deploy_timer > 0 then
			local mg = self.Owner:GetEyeTrace()
			local ent = mg.Entity
			if !IsValid(ent) or ent != self:GetDoor() or (self.SupportsFadingDoors and !ent:GetNW2Bool("isFadingDoor") and (!ent:isDoor() or !ent:isKeysOwnable())) or ent:GetNW2Bool("BreachAttached") then
				self:ResetDeploy()
				return
			end
			local distance = self.Owner:GetShootPos():DistToSqr(mg.HitPos)
			if distance > self.Range then
				self:ResetDeploy()
				return
			end
			if deploy_timer < CurTime() then
				if SERVER then
					local slam = ents.Create("door_breach")
					if !IsValid(slam) then self:ResetDeploy() return end
					slam:SetPos(mg.HitPos + mg.HitNormal)
					slam:SetAngles(mg.HitNormal:Angle() + Angle(90, 0, 0))
					slam:SetParent(ent)
					slam:SetDetonator(self)
					slam:SetPlacer(self.Owner)
					slam.Owner = self.Owner
					self:SetMine(slam)
					slam:Spawn()
					slam:Activate()
					slam:EmitSound(self.PlaceSound)
					ent:SetNW2Bool("BreachAttached", true)
					hook.Run("BreachCharge_Attach", self.Owner, self:GetDoor(), slam)
				end
				self:ResetConfig()
				self:SetDeployDetTimer(CurTime() + self.DeployDetSpeed)
				self:SetNextPrimaryFire(CurTime() + self.DeployDetSpeed)
				self:SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH2)
				self:TakePrimaryAmmo(1)
			end
		end
	else
		self:SetHoldType(self.HoldType)
	end
end

function SWEP:DetonatorThink()
	local active_mine, det_active, deploy_det = IsValid(self:GetMine()), self:GetDetActive(), self:GetDeployDetTimer()
	if !active_mine and det_active then
		self:ResetDeploy()
	end
	if deploy_det > 0 then
		if deploy_det < CurTime() then
			self:DeployDetonator()
		end
	elseif self:GetNextPrimaryFire() <= CurTime() and active_mine and !det_active then
		self:DeployDetonator()
	end
end

function SWEP:DetonateThink()
	local det_timer = self:GetDetonateTimer()
	if det_timer > 0 and det_timer < CurTime() and IsValid(self:GetMine()) and self:GetDetActive() then
		self:Detonate()
	end
end

function SWEP:Think()
	if !IsValid(self.Owner) then return end
	self:DetonateThink()
	self:DetonatorThink()
	self:DoorBreachThink()
	self:CheckForRemoval(true)
end

if !CLIENT then return end

local gradientup = Material("gui/gradient_up")
local gradientdown = Material("gui/gradient_down")

function SWEP:DrawProgressBar(label, color, filled)
	filled = math.Clamp(filled, 0, 1)
	local w, h = 300, 20
	local centerx, centery = ScrW() / 2, ScrH() / 2 - 20
	local x, y = centerx - w / 2, centery - h / 2
	surface.SetDrawColor(color_white)
	surface.DrawOutlinedRect(x, y, w, h)
	surface.SetDrawColor(color)
	surface.SetMaterial(gradientdown)
	surface.DrawTexturedRect(x + 2, y + 2, (w - 4) * filled, h - 4)
	surface.SetDrawColor(Color(color.r / 2, color.g / 2, color.b/ 2))
	surface.SetMaterial(gradientup)
	surface.DrawTexturedRect(x + 2, y + 2, (w - 4) * filled, h - 4)
	draw.SimpleTextOutlined(label, "DermaDefaultBold", centerx, centery - 1, color_white, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 1, Color(0, 0, 0))
end

function SWEP:DrawHUD()
	if self:GetAttaching() then
		local deploying = self:GetDeployTimer()
		if deploying > 0 then
			local text = "Türsprengladung anbringen..."
			local color = Color(255, 0, 0)
			local time = (CurTime() - (self:GetDeployTimer() - self.DeploySpeed)) / self.DeploySpeed
			self:DrawProgressBar(text, color, time)
		end
	end
end