if SERVER then
	CreateConVar("sbox_maxbells", 3)
end

TOOL.Category = "Construction"
TOOL.Name = "#tool.bell.name"

TOOL.ClientConVar["model"] = "models/easydoorbell/buttonbasic.mdl"
TOOL.ClientConVar["sound"] = "doorbells/bell.mp3"
TOOL.ClientConVar["volume"] = 0.75
TOOL.ClientConVar["delay"] = 0.25
TOOL.ClientConVar["description"] = ""

TOOL.Information = {
	{name = "left"},
	{name = "right"}
}

cleanup.Register("bells")

if CLIENT then
	language.Add("tool.bell.name", "Klingel")
	language.Add("tool.bell.desc", "Klingel, welche betätigt werden kann um einen Ton abzuspielen.")
	language.Add("tool.bell.left", "Klingel befestigen/aktualisieren")
	language.Add("tool.bell.right", "Klingel erstellen")
	language.Add("tool.bell.sound", "Ton")
	language.Add("tool.bell.volume", "Lautstärke")
	language.Add("tool.bell.delay", "Cooldown")
	language.Add("tool.bell.delay.help", "Zeit zwischen dem zweifachen Betätigen der Klingel.")
	language.Add("tool.bell.text", "Beschriftung")
	language.Add("max_bells", "Maximale Klingeln")
	language.Add("Undone_Bell", "Undone Bell")
	language.Add("Cleanup_bells", "Bells")
	language.Add("Cleaned_bells", "Cleaned up all Bells")
	language.Add("SBoxLimit_bells", "You've hit the Bell Limit!")
end

local function IsValidBellModel(model)
	local modellower = model:lower()
	for mdl in pairs(list.Get("BellModels")) do
		if mdl:lower() == modellower then
			return true
		end
	end
	return false
end

local sounds = {"doorbells/standard.mp3", "doorbells/electronic.mp3", "doorbells/buzzer.mp3", "doorbells/bell.mp3", "doorbells/ring.mp3"}
local function IsValidBellSound(sound)
	if sound == "" then return true end
	for _, v in pairs(sounds) do
		if v == sound then
			return true
		end
	end
	return false
end

function TOOL:RightClick(trace, worldweld)
	local ent = trace.Entity
	if IsValid(ent) and ent:IsPlayer() then return false end
	if SERVER and !util.IsValidPhysicsObject(ent, trace.PhysicsBone) then return false end
	if CLIENT then return true end
	local model = self:GetClientInfo("model")
	local description = self:GetClientInfo("description")
	local sound = self:GetClientInfo("sound")
	local volume = math.Clamp(self:GetClientNumber("volume"), 0, 1)
	local delay = math.Clamp(self:GetClientNumber("delay"), 0.25, 10)
	local ply = self:GetOwner()
	if (IsValid(ent) and ent:GetClass() == "bell" and ent:GetPlayer() == ply) then
		ent:SetLabel(description)
		ent.sound = sound
		ent.volume = volume
		ent.delay = delay
		ent.Delay = nil
		return true
	end
	if !util.IsValidModel(model) or !util.IsValidProp(model) or !IsValidBellModel(model) then return false end
	if !IsValidBellSound(sound) then return false end
	if !self:GetSWEP():CheckLimit("bells") then return false end
	local ang = trace.HitNormal:Angle()
	if model == "models/adi/buttonbell.mdl" then
		ang.pitch = ang.pitch + 90
	end
	local bell = MakeBell(ply, model, ang, trace.HitPos, sound, volume, delay, description)
	local min = bell:OBBMins()
	bell:SetPos(trace.HitPos)
	undo.Create("Bell")
		undo.AddEntity(bell)
		if (worldweld and ent != NULL) then
			local weld = constraint.Weld(bell, ent, 0, trace.PhysicsBone, 0, 0, true)
			if IsValid(bell:GetPhysicsObject()) then
				bell:GetPhysicsObject():EnableCollisions(false)
			end
			bell:SetCollisionGroup(COLLISION_GROUP_WORLD)
			bell.nocollide = true
			ply:AddCleanup("bells", weld)
			undo.AddEntity(weld)
		end
		undo.SetPlayer(ply)
	undo.Finish()
	return true
end

function TOOL:LeftClick(trace)
	return self:RightClick(trace, true)
end

if SERVER then
	function MakeBell(ply, model, ang, pos, sound, volume, delay, description, nocollide)
		if IsValid(ply) and !ply:CheckLimit("bells") then return false end
		if !IsValidBellModel(model) then return false end
		local bell = ents.Create("bell")
		if !IsValid(bell) then return false end
		bell:SetModel(model)
		bell:SetAngles(ang)
		bell:SetPos(pos)
		bell:Spawn()
		bell:SetPlayer(ply)
		bell:SetLabel(description)
		if (nocollide == true) then
			if IsValid(bell:GetPhysicsObject()) then
				bell:GetPhysicsObject():EnableCollisions(false)
			end
			bell:SetCollisionGroup(COLLISION_GROUP_WORLD)
		end
		table.Merge(bell:GetTable(), {
			ply = ply,
			sound = sound,
			volume = volume,
			delay = delay,
			nocollide = nocollide,
			description = description
		})
		if IsValid(ply) then
			ply:AddCount("bells", bell)
			ply:AddCleanup("bells", bell)
		end
		DoPropSpawnedEffect(bell)
		return bell
	end
	duplicator.RegisterEntityClass("bell", MakeBell, "Model", "Ang", "Pos", "sound", "description", "nocollide")
end

function TOOL:UpdateGhostBell(ent, ply)
	if !IsValid(ent) then return end
	local trace = ply:GetEyeTrace()
	local trace_ent = trace.Entity
	if !trace.Hit or IsValid(trace_ent) and (trace_ent:GetClass() == "bell" or trace_ent:IsPlayer()) then
		ent:SetNoDraw(true)
		return
	end
	local ang = trace.HitNormal:Angle()
	if ent:GetModel() == "models/adi/buttonbell.mdl" then
		ang.pitch = ang.pitch + 90
	end
	ent:SetPos(trace.HitPos)
	ent:SetAngles(ang)
	ent:SetNoDraw(false)
end

function TOOL:Think()
	local mdl = self:GetClientInfo("model")
	if !IsValidBellModel(mdl) then self:ReleaseGhostEntity() return end
	if !IsValid(self.GhostEntity) or self.GhostEntity:GetModel() != mdl then
		self:MakeGhostEntity(mdl, Vector(0, 0, 0), Angle(0, 0, 0))
	end
	self:UpdateGhostBell(self.GhostEntity, self:GetOwner())
end

local ConVarsDefault = TOOL:BuildConVarList()
function TOOL.BuildCPanel(CPanel)
	CPanel:AddControl("Header", {Description = "#tool.bell.desc"})
	CPanel:AddControl("ComboBox", {MenuButton = 1, Folder = "bell", Options = {["#preset.default"] = ConVarsDefault}, CVars = table.GetKeys(ConVarsDefault)})
	local bell_sounds = {Label = "#tool.bell.sound", MenuButton = 0, Options = {}, CVars = {}}
	bell_sounds["Options"]["Kein Ton"] = {bell_sound = ""}
	bell_sounds["Options"]["Standard"] = {bell_sound = "doorbells/standard.mp3"}
	bell_sounds["Options"]["Klingel"] = {bell_sound = "doorbells/bell.mp3"}
	bell_sounds["Options"]["Elektronisch"] = {bell_sound = "doorbells/electronic.mp3"}
	bell_sounds["Options"]["Buzzer"] = {bell_sound = "doorbells/buzzer.mp3"}
	bell_sounds["Options"]["Ringen"] = {bell_sound = "doorbells/ring.mp3"}
	CPanel:AddControl("ComboBox", bell_sounds)
	CPanel:AddControl("Slider", {Type = "Float", Label = "#tool.bell.volume", Command = "bell_volume", Min = 0, Max = 1})
	CPanel:AddControl("Slider", {Type = "Float", Label = "#tool.bell.delay", Command = "bell_delay", Min = 0.25, Max = 10, Help = true})
	CPanel:AddControl("TextBox", {Label = "#tool.bell.text", Command = "bell_description", MaxLenth = "20"})
	CPanel:AddControl("PropSelect", {Label = "#tool.bell.model", ConVar = "bell_model", Height = 0, Models = list.Get("BellModels")})
end

list.Set("BellModels", "models/easydoorbell/buttonbasic.mdl", {})
list.Set("BellModels", "models/easydoorbell/buttonfancy.mdl", {})
list.Set("BellModels", "models/easydoorbell/buttonmodern.mdl", {})
list.Set("BellModels", "models/adi/buttonbell.mdl", {})