AddCSLuaFile()

if CLIENT then
	SWEP.Slot = 5
	SWEP.SlotPos = 1
	SWEP.DrawAmmo = false
	SWEP.DrawCrosshair = false
end

SWEP.PrintName = "Lock Pick"
SWEP.Author = "DarkRP Developers"
SWEP.Instructions = "Left or right click to pick a lock"
SWEP.Contact = ""
SWEP.Purpose = ""
SWEP.IsDarkRPLockpick = true

SWEP.ViewModelFOV = 62
SWEP.ViewModelFlip = false
SWEP.ViewModel = Model("models/weapons/c_crowbar.mdl")
SWEP.WorldModel = Model("models/weapons/w_crowbar.mdl")

SWEP.UseHands = true

SWEP.Spawnable = true
SWEP.AdminOnly = true
SWEP.Category = "DarkRP (Utility)"

SWEP.Sound = Sound("physics/wood/wood_box_impact_hard3.wav")

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

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

function SWEP:SetupDataTables()
	self:NetworkVar("Bool", 0, "IsLockpicking")
	self:NetworkVar("Float", 0, "LockpickStartTime")
	self:NetworkVar("Float", 1, "LockpickEndTime")
	self:NetworkVar("Float", 2, "NextSoundTime")
	self:NetworkVar("Int", 0, "TotalLockpicks")
	self:NetworkVar("Entity", 0, "LockpickEnt")
end

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

function SWEP:PrimaryAttack()
	self:SetNextPrimaryFire(CurTime() + 0.5)
	if self:GetIsLockpicking() then return end
	local Owner = self:GetOwner()
	if !IsValid(Owner) then return end
	Owner:LagCompensation(true)
	local trace = Owner:GetEyeTrace()
	Owner:LagCompensation(false)
	local ent = trace.Entity
	if !IsValid(ent) or ent.DarkRPCanLockpick == false then return end
	local canLockpick = hook.Call("canLockpick", nil, Owner, ent, trace)
	if canLockpick == false then return end
	if canLockpick ~= true and (
			trace.HitPos:DistToSqr(Owner:GetShootPos()) > 10000 or
			(not GAMEMODE.Config.canforcedooropen and ent:getKeysNonOwnable()) or
			(not ent:isDoor() and !ent:IsVehicle() and !string.find(string.lower(ent:GetClass()), "vehicle") and (not GAMEMODE.Config.lockpickfading or !ent.isFadingDoor))
		) then
		return
	end
	self:SetHoldType("pistol")
	self:SetIsLockpicking(true)
	self:SetLockpickEnt(ent)
	self:SetLockpickStartTime(CurTime())
	local endDelta = hook.Call("lockpickTime", nil, Owner, ent) or util.SharedRandom("DarkRP_Lockpick"..self:EntIndex().."_"..self:GetTotalLockpicks(), 10, 20)
	self:SetLockpickEndTime(CurTime() + endDelta)
	self:SetTotalLockpicks(self:GetTotalLockpicks() + 1)
	if IsFirstTimePredicted() then
		hook.Call("lockpickStarted", nil, Owner, ent, trace)
	end
	if CLIENT then
		self.Dots = ""
		self.NextDotsTime = SysTime() + 0.5
		return
	end
	local onFail = function(ply) if ply == Owner then hook.Call("onLockpickCompleted", nil, ply, false, ent) end end

	hook.Add("PlayerDeath", self, fc{onFail, fn.Flip(fn.Const)})
	hook.Add("PlayerDisconnected", self, fc{onFail, fn.Flip(fn.Const)})

	hook.Add("onLockpickCompleted", self, fc{fp{hook.Remove, "PlayerDisconnected", self}, fp{hook.Remove, "PlayerDeath", self}})
end

function SWEP:Holster()
	if self:GetIsLockpicking() and self:GetLockpickEndTime() ~= 0 then
		self:Fail()
	end
	return true
end

function SWEP:Succeed()
	self:SetHoldType("normal")
	local ent = self:GetLockpickEnt()
	self:SetIsLockpicking(false)
	self:SetLockpickEnt(nil)
	if !IsValid(ent) then return end
	local override = hook.Call("onLockpickCompleted", nil, self:GetOwner(), true, ent)
	if override then return end
	if ent.isFadingDoor and ent.fadeActivate and !ent.fadeActive then
		ent:fadeActivate()
		if IsFirstTimePredicted() then timer.Simple(5, function() if IsValid(ent) and ent.fadeActive then ent:fadeDeactivate() end end) end
	elseif ent.Fire then
		ent:keysUnLock()
		ent:Fire("open", "", .6)
		ent:Fire("setanimation", "open", .6)
	end
end

function SWEP:Fail()
	self:SetIsLockpicking(false)
	self:SetHoldType("normal")
	hook.Call("onLockpickCompleted", nil, self:GetOwner(), false, self:GetLockpickEnt())
	self:SetLockpickEnt(nil)
end

local dots = {
	[0] = ".",
	[1] = "..",
	[2] = "...",
	[3] = ""
}
function SWEP:Think()
	if !self:GetIsLockpicking() or self:GetLockpickEndTime() == 0 then return end
	if CurTime() >= self:GetNextSoundTime() then
		self:SetNextSoundTime(CurTime() + 1)
		local snd = {1,3,4}
		local rndsound = tostring(snd[math.Round(util.SharedRandom("DarkRP_LockpickSnd"..CurTime(), 1, #snd))])
		local volume = 1
		volume = hook.Run("DarkRP_LockpickVolume", self, volume) or volume
		self:EmitSound("weapons/357/357_reload"..rndsound..".wav", 50, 100, volume)
	end
	if CLIENT and (not self.NextDotsTime or SysTime() >= self.NextDotsTime) then
		self.NextDotsTime = SysTime() + 0.5
		self.Dots = self.Dots or ""
		local len = string.len(self.Dots)
		self.Dots = dots[len]
	end
	local trace = self:GetOwner():GetEyeTrace()
	if !IsValid(trace.Entity) or trace.Entity ~= self:GetLockpickEnt() or trace.HitPos:DistToSqr(self:GetOwner():GetShootPos()) > 10000 then
		self:Fail()
	elseif self:GetLockpickEndTime() <= CurTime() then
		self:Succeed()
	end
end

function SWEP:DrawHUD()
	if !self:GetIsLockpicking() or self:GetLockpickEndTime() == 0 then return end
	self.Dots = self.Dots or ""
	local w = ScrW()
	local h = ScrH()
	local x, y, width, height = w / 2 - w / 10, h / 2 - 60, w / 5, h / 15
	draw.RoundedBox(8, x, y, width, height, Color(10, 10, 10, 120))
	local time = self:GetLockpickEndTime() - self:GetLockpickStartTime()
	local curtime = CurTime() - self:GetLockpickStartTime()
	local status = math.Clamp(curtime / time, 0, 1)
	local BarWidth = status * (width - 16)
	local cornerRadius = math.Min(8, BarWidth / 3 * 2 - BarWidth / 3 * 2 % 2)
	draw.RoundedBox(cornerRadius, x + 8, y + 8, BarWidth, height - 16, Color(255 - (status * 255), 0 + (status * 255), 0, 255))
	draw.DrawNonParsedSimpleText(DarkRP.getPhrase("picking_lock")..self.Dots, "Trebuchet24", w / 2, y + height / 2, color_white, 1, 1)
end

function SWEP:SecondaryAttack()
	self:PrimaryAttack()
end