if SERVER then 
	include("ballistic_shields/sh_bs_util.lua") 
	include("ballistic_shields/sv_bs_util.lua") 
end
include("bs_config.lua") 
include("ballistic_shields/sh_bs_lang.lua") 

SWEP.PrintName = "Schweres Schild"
SWEP.Instructions = "Linksklick zum Aufbrechen einer Tür.\nRechtsklick um die Sichtbarkeit zu Konfigurieren."
SWEP.Spawnable = true

SWEP.ViewModel = ""
SWEP.WorldModel = Model("models/bshields/hshield.mdl")

SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom	= false

SWEP.Slot = 3
SWEP.SlotPos = 20
SWEP.DrawAmmo = false
SWEP.DrawCrosshair = false

SWEP.Primary.Damage = 50
SWEP.Primary.Delay = 1.5
SWEP.Primary.ClipSize = -1
SWEP.Primary.DefaultClip = -1
SWEP.Primary.Automatic = false
SWEP.Primary.Ammo = "none"
SWEP.Secondary.ClipSize = -1
SWEP.Secondary.DefaultClip = -1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"

SWEP.CanVisToggle = 0
SWEP.VisToggle = false
SWEP.IsShield = true
SWEP.DoorDamage = 25

function SWEP:Initialize()
	self:SetHoldType("melee2")
end

function SWEP:DrawWorldModel()
	self:SetNoDraw(true) 
end

local ShieldIcon = Material("bshields/ui/heavy_shield", "smooth")
local BackgroundIcon = Material("bshields/ui/background")
function SWEP:DrawHUD()
	if (bshields.config.disablehud) then return end
	surface.SetDrawColor(255,255,255,200)	
	surface.SetMaterial(BackgroundIcon)
	surface.DrawTexturedRect(ScrW()/2-ScrH()/10, ScrH()/2-ScrH()/30+ScrH()/3, ScrH()/5, ScrH()/15)
	surface.SetDrawColor(255,255,255,125)

	local ply = LocalPlayer()
	local aim = ply:EyeAngles():Forward()
	local tr = util.TraceLine({
		start  = ply:GetShootPos() ,
		endpos = ply:GetShootPos() + aim * 100,
		filter = {ply, ply.bs_shieldIndex and Entity(ply.bs_shieldIndex)}
	})
	if IsValid(tr.Entity) and tr.Entity:isDoor() and ply:EyePos():DistToSqr(tr.HitPos) <= 4000 then
		draw.SimpleTextOutlined(bshields.lang[bshields.config.language].hshieldprim, "bshields.HUD", ScrW()/2-ScrH()/32, ScrH()/2-ScrH()/28+ScrH()/3+ScrH()/22, color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, 1, Color(20,20,20,255)) 
	else
		draw.SimpleTextOutlined(bshields.lang[bshields.config.language].hshieldprim, "bshields.HUD", ScrW()/2-ScrH()/32, ScrH()/2-ScrH()/28+ScrH()/3+ScrH()/22, Color(255, 255, 255, 25), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, 1, Color(20,20,20,255)) 
	end
	surface.SetMaterial(ShieldIcon)
	surface.DrawTexturedRect(ScrW()/2-ScrH()/10.2, ScrH()/2-ScrH()/32+ScrH()/3, ScrH()/16, ScrH()/16) 
	if (self.VisToggle) then
		draw.SimpleTextOutlined(bshields.lang[bshields.config.language].sec, "bshields.HUD", ScrW()/2-ScrH()/32, ScrH()/2-ScrH()/28+ScrH()/3+ScrH()/48, Color(255, 255, 255, 25), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, 1, Color(20,20,20,255)) 
	else
		draw.SimpleTextOutlined(bshields.lang[bshields.config.language].sec, "bshields.HUD", ScrW()/2-ScrH()/32, ScrH()/2-ScrH()/28+ScrH()/3+ScrH()/48, color_white, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, 1, Color(20,20,20,255)) 
	end
end

function SWEP:BuildShield()
	local owner = self:GetOwner()
	local holdtype = 0
	bshield_remove(owner)
	local owner_tb = owner:GetTable()
	owner_tb.bs_type = "heavy_shield"
	owner_tb.bs_shield = ents.Create("bs_shield")
	if !IsValid(owner_tb.bs_shield) then return end
	owner_tb.bs_shield.Model = "models/bshields/hshield.mdl"
	owner_tb.bs_shield.Mass = 100
	owner_tb.bs_shield:SetCollisionGroup(COLLISION_GROUP_WORLD)
	owner_tb.bs_shield:SetMoveType(MOVETYPE_NONE)
	owner_tb.bs_shield:SetPos(owner:GetPos())
	local att = owner:LookupAttachment("anim_attachment_RH")
	if (att == 0) then
		holdtype = 1
	end
	if (holdtype == 0) then	
		owner_tb.bs_shield:SetParent(owner, att)
		owner_tb.bs_shield:SetLocalAngles(bshields.shields[1][1].angles)
		owner_tb.bs_shield:SetLocalPos(bshields.shields[1][1].position)
	else
		att = owner:LookupAttachment("forward") != 0 and owner:LookupAttachment("forward") or owner:LookupAttachment("eyes") != 0 and owner:LookupAttachment("eyes")
		if (att == 0) then
			owner_tb.bs_shield:Remove()
			owner_tb.bs_shield = nil
			return
		end
		owner_tb.bs_shield:SetParent(owner, att)
		owner_tb.bs_shield:SetLocalAngles(bshields.shields[2][1].angles)
		owner_tb.bs_shield:SetLocalPos(bshields.shields[2][1].position)
	end
	owner_tb.bs_shield.holdtype = holdtype
	owner_tb.bs_shield.pos = {owner_tb.bs_shield:GetLocalAngles(), owner_tb.bs_shield:GetLocalPos()}
	owner_tb.bs_shield.model = owner:GetModel()
	owner_tb.bs_shield:Spawn()
	self.HP = self.HP or bshields.config.shieldhps["hshield"]
	owner_tb.bs_shield:SetHealth(self.HP)
	owner_tb.bs_shield.MaxHP = self.MaxHP
	owner_tb.bs_shield:ColorShield()
	net.Start("bs_shield_info")
		net.WriteUInt(owner_tb.bs_shield:EntIndex(), 16) 
	net.Send(owner)
end

function SWEP:Deploy()
	self.CanVisToggle = 0
	self.VisToggle = false
	self.HP = self.HP or bshields.config.shieldhps["hshield"]
	self.MaxHP = bshields.config.shieldhps["hshield"]
	if SERVER then
		timer.Simple(0, function()
			if IsValid(self) and IsValid(self.Owner) and self.Owner:GetActiveWeapon() == self then
				self:BuildShield()
			end
		end)
	end
	return true
end

function SWEP:Think()
	local owner = self:GetOwner()
	if owner:IsValid() then
		if owner.bs_shield and owner:GetModel() != owner.bs_shield.model then
			self:BuildShield()
		end
	end
end

local function canRam(ply)
	return IsValid(ply) and ply.warranted == true
end

local function ramDoor(ply, ent)
	if (!GAMEMODE.Config.canforcedooropen and ent:getKeysNonOwnable()) then return false end
	local allowed = false
	if GAMEMODE.Config.doorwarrants and ent:isKeysOwned() and !ent:isKeysOwnedBy(ply) then
		for _, v in ipairs(player.GetAll()) do
			if ent:isKeysOwnedBy(v) and canRam(v) then
				allowed = true
				break
			end
		end
	else
		allowed = true
	end
	local keysDoorGroup = ent:getKeysDoorGroup()
	if GAMEMODE.Config.doorwarrants and keysDoorGroup then
		local teamDoors = RPExtraTeamDoors[keysDoorGroup]
		if teamDoors then
			allowed = false
			for _, v in ipairs(player.GetAll()) do
				if table.HasValue(teamDoors, v:Team()) and canRam(v) then
					allowed = true
					break
				end
			end
		end
	end
	if CLIENT then return allowed end
	if !allowed then
		DarkRP.notify(ply, 1, 5, DarkRP.getPhrase("warrant_required"))
		return false
	end
	ent:keysUnLock()
	ent:Fire("open", "", 0.6)
	ent:Fire("setanimation", "open", 0.6)
	return true
end

local function ramFadingDoor(ply, ent)
	local Owner = ent:CPPIGetOwner()
	if CLIENT then return canRam(Owner) end
	if !canRam(Owner) then
		DarkRP.notify(ply, 1, 5, DarkRP.getPhrase("warrant_required"))
		return false
	end
	if !ent.fadeActive then
		ent:fadeActivate()
		timer.Simple(5, function()
			if IsValid(ent) and ent.fadeActive then
				ent:fadeDeactivate()
			end
		end)
	end
	return true
end

local door_hp = {
	["default"] = 200,
	["fading_door"] = 150
}
local door_repair = 60
local function DoorDamage(ent, force)
	ent.DoorMaxHP = ent.DoorMaxHP or door_hp[ent:GetName()] or ent.isFadingDoor and door_hp["fading_door"] or door_hp["default"]
	ent.DoorHP = ent.DoorHP or ent.DoorMaxHP
	ent.DoorHP = ent.DoorHP - force
	if ent.DoorHP <= 0 then
		ent.DoorHP = nil
		timer.Remove("bshields_repair_"..ent:EntIndex())
		return true
	end
	timer.Create("bshields_repair_"..ent:EntIndex(), door_repair, 1, function()
		if IsValid(ent) then
			ent.DoorMaxHP = nil
			ent.DoorHP = nil
		end
	end)
end

function SWEP:PrimaryAttack()
	if !DarkRP then return end
	self:SetNextPrimaryFire(CurTime() + self.Primary.Delay)

	local owner = self.Owner
	if !IsValid(owner) then return end

	owner:SetAnimation(PLAYER_ATTACK1)

	if !SERVER or !IsValid(owner.bs_shield) then return end

	owner:LagCompensation(true)

	local aim = owner:EyeAngles():Forward()
	local tr = util.TraceLine({
		start  = owner:GetShootPos() ,
		endpos = owner:GetShootPos() + aim * 100,
		filter = {owner, owner.bs_shield}
	})

	owner:LagCompensation(false)

	local ent = tr.Entity
	if !IsValid(ent) then return end
	if !(ent:isDoor() or (bshields.config.breachfdoors and ent.isFadingDoor and !ent.fadeActive and ent.fadeActivate)) then return end
	if owner:EyePos():DistToSqr(tr.HitPos) > 4000 then return end
	if ent.toDetonate then return end

	if !ent.fadeActive and ent.fadeActivate and bshields.config.breachfdoors then
		ent:EmitSound("npc/metropolice/gear2.wav") 
		ent.toDetonate = true
		timer.Simple(0.2, function()
			if !IsValid(self) or !IsValid(owner) or !IsValid(ent) and !ent.fadeActivate then
				ent.toDetonate = nil
				return
			end
			ent.toDetonate = nil
			local aim = owner:EyeAngles():Forward()
			local tr = util.TraceLine({
				start  = owner:GetShootPos() ,
				endpos = owner:GetShootPos() + aim * 100,
				filter = {owner, owner.bs_shield}
			})
			if tr.Entity == ent and owner:EyePos():DistToSqr(tr.HitPos) <= 4000 then
				ent:EmitSound("physics/metal/metal_box_break1.wav")
				if DoorDamage(ent, self.Primary.Damage) then
					local rammed = ramFadingDoor(owner, ent)
					if rammed then
						local edata = EffectData()
						edata:SetOrigin(ent:GetPos())
						edata:SetMagnitude(5)
						edata:SetScale(2)
						edata:SetRadius(5)
						util.Effect("HelicopterMegaBomb", edata, true, true)
						if IsValid(owner.bs_shield) then
							owner.bs_shield:TakeDamage(self.DoorDamage)
						end
						hook.Run("ballistic_shields_dbreach", owner, ent)
					end
				end
			end
		end)
	elseif ent:isDoor() then
		ent:EmitSound("npc/metropolice/gear2.wav")
		ent.toDetonate = true
		timer.Simple(0.2, function()
			if !IsValid(self) or !IsValid(owner) or !IsValid(ent) or !ent:isDoor() then return end
			ent.toDetonate = nil
			local aim = owner:EyeAngles():Forward()
			local tr = util.TraceLine({
				start  = owner:GetShootPos() ,
				endpos = owner:GetShootPos() + aim * 100,
				filter = {owner, owner.bs_shield}
			})
			if tr.Entity == ent and owner:EyePos():DistToSqr(tr.HitPos) <= 4000 then
				ent:EmitSound("physics/metal/metal_box_break1.wav")
				if DoorDamage(ent, self.Primary.Damage) then
					local rammed = ramDoor(owner, ent)
					if rammed then
						local effectdata = EffectData()
						effectdata:SetOrigin(ent:GetPos() - Vector(0, 0, 16))
						effectdata:SetMagnitude(5)
						effectdata:SetScale(2)
						effectdata:SetRadius(5)
						util.Effect("HelicopterMegaBomb", effectdata, true, true)
						if IsValid(owner.bs_shield) then
							owner.bs_shield:TakeDamage(self.DoorDamage)
						end
						hook.Run("ballistic_shields_dbreach", owner, ent)
					end
				end
			end
		end)
	end
end

function SWEP:SecondaryAttack()
	if CLIENT then
		if self.CanVisToggle > CurTime() then return end
		surface.PlaySound("weapons/smg1/switch_single.wav")
		if !self.VisToggle then
			self.VisToggle = true
		else
			self.VisToggle = false
		end
		self.CanVisToggle = CurTime() + 0.2
	end
end

function SWEP:ShouldDrawViewModel()
	local ply = LocalPlayer()
	local shield = ply.bs_shieldIndex and Entity(ply.bs_shieldIndex)
	if !IsValid(shield) then return end
	local col = shield:GetColor()
	col.a = self.VisToggle and 125 or 255
	shield:SetColor(col)
end

if CLIENT then return end

function SWEP:Holster()
	bshield_remove(self.Owner, function(hp)
		self.HP = hp
	end)
	return true
end

function SWEP:OnRemove()
	bshield_remove(self.Owner, function(hp)
		self.HP = hp
	end)
end

function SWEP:OnDrop()
	bshield_remove(self.Owner, function(hp)
		self.HP = hp
	end)
end