if not SERVER then return end

local function zrmine_FindValidConnectEntity(DropedEnt, searchrange)
	local validEnts = {}

	for k, v in pairs(ents.FindInSphere(DropedEnt:GetPos(), searchrange)) do
		if (v ~= DropedEnt and v.connected_module == nil) then
			if (string.sub(DropedEnt:GetClass(), 1, 17) == "zrms_conveyorbelt") then
				if (v:GetClass() == "zrms_crusher") then
					table.insert(validEnts, v)
				elseif (string.sub(v:GetClass(), 1, 17) == "zrms_conveyorbelt") then
					if (v:GetBuildMode() == false and DropedEnt:GetPos():Distance(v:GetAttachment(v:LookupAttachment("output")).Pos) < searchrange) then
						table.insert(validEnts, v)
					end
				elseif (string.sub(v:GetClass(), 1, 12) == "zrms_refiner") then
					if IsValid(v.connected_Parent) then
						table.insert(validEnts, v)
					end
				elseif (string.sub(v:GetClass(), 1, 13) == "zrms_splitter") then
					if IsValid(v.connected_Parent) then
						table.insert(validEnts, v)
					end
				elseif (string.sub(v:GetClass(), 1, 11) == "zrms_sorter") then
					if IsValid(v.connected_Parent) then
						table.insert(validEnts, v)
					end
				end
			elseif (string.sub(DropedEnt:GetClass(), 1, 13) == "zrms_inserter") then
				if (string.sub(v:GetClass(), 1, 17) == "zrms_conveyorbelt") then
					if IsValid(v.connected_Parent) then
						table.insert(validEnts, v)
					end
				elseif (string.sub(v:GetClass(), 1, 12) == "zrms_refiner") then
					if IsValid(v.connected_Parent) then
						table.insert(validEnts, v)
					end
				elseif (v:GetClass() == "zrms_crusher") then
					table.insert(validEnts, v)
				end
			elseif (string.sub(DropedEnt:GetClass(), 1, 13) == "zrms_splitter") then
				if (string.sub(v:GetClass(), 1, 17) == "zrms_conveyorbelt" and IsValid(v.connected_Parent)) then
					table.insert(validEnts, v)
				end
			elseif (string.sub(DropedEnt:GetClass(), 1, 11) == "zrms_sorter") then
				if (string.sub(v:GetClass(), 1, 17) == "zrms_conveyorbelt" and IsValid(v.connected_Parent)) then
					table.insert(validEnts, v)
				end
			elseif (string.sub(DropedEnt:GetClass(), 1, 12) == "zrms_refiner") then
				if (string.sub(v:GetClass(), 1, 12) == "zrms_refiner") then
					if IsValid(v.connected_Parent) then
						table.insert(validEnts, v)
					end
				elseif (string.sub(v:GetClass(), 1, 17) == "zrms_conveyorbelt") then
					if IsValid(v.connected_Parent) then
						table.insert(validEnts, v)
					end
				end
			end
		end
	end

	return validEnts
end

local function zrmine_FindNearestEntity(aents, pos, range)
	local nearestEnt

	for i, entity in ipairs(aents) do
		local distance = pos:Distance(entity:GetPos())

		if (distance <= range) then
			nearestEnt = entity
			range = distance
		end
	end

	return nearestEnt
end

local function zrmine_CheckPlayerAllowed(ply, FoundEnt, DroppedEnt)
	if (not zrmine.f.IsOwner(ply, FoundEnt) or not zrmine.f.IsOwner(ply, DroppedEnt)) then
		zrmine.f.Notify(ply, zrmine.language.Module_DontOwn, 1)

		return true
	else
		return false
	end
end

local function zrmine_gravgun_drop(ply, ent)
	-- Used do place a basket to a refiner
		if (string.sub(ent:GetClass(), 1, 11) == "zrms_basket") then
			for k, v in pairs(ents.FindInSphere(ent:GetPos(), 25)) do
				if (string.sub(v:GetClass(), 1, 12) == "zrms_refiner" and v.connected_Parent ~= nil and v.connected_Basket == nil) then
					local pos = v:GetPos() + v:GetUp() * 5 + v:GetRight() * 45

					if (ent:GetPos():Distance(pos) < 30) then
						v:Place_Basket(ent)
						break
					end
				elseif (string.sub(v:GetClass(), 1, 12) == "zrms_melter") then
					local orepos = v:GetPos() + v:GetUp() * 75
					local coalpos = v:GetPos() + v:GetForward() * 60 + v:GetUp() * 10
					local basket_rType = ent:GetResourceType()
					local basket_rAmount = ent:GetResourceAmount()

					if (basket_rType == "Coal") then
						if (ent:GetPos():Distance(coalpos) < 50 and basket_rAmount > 0) then
							v:Add_Coal(ent)
							break
						end
					else
						if (ent:GetPos():Distance(orepos) < 25) then
							if (basket_rAmount <= 0 and basket_rType == "Empty") then
								v:Collect_Resource(ent, ply)
								break
							elseif (basket_rAmount > 0 and basket_rType ~= "Empty") then
								v:Add_Resource(ent, ply)
								break
							end
						end
					end
				end
			end
		end

		/*
		-- Used to input gravel in to a crusher or gravel crate
		if (string.sub(ent:GetClass(), 1, 13) == "zrms_resource") then
			for k, v in pairs(ents.FindInSphere(ent:GetPos(), 25)) do
				if (v:GetClass() == "zrms_crusher") then
					v:Add_Resource(ent, ply)
					break
				elseif (v:GetClass() == "zrms_gravelcrate") then
					if (v:Return_StoredAmount() > zrmine.config.GravelCrates_Capacity) then
						zrmine.f.Notify(ply, zrmine.language.Crate_Full, 1)

						return
					end

					v:Add_ResourceJunk(ent)
					break
				end
			end
		end
		*/
		-- Used to input gravelcrate in to a crusher
		if (string.sub(ent:GetClass(), 1, 16) == "zrms_gravelcrate") then
			for k, v in pairs(ents.FindInSphere(ent:GetPos(), 25)) do
				if (v:GetClass() == "zrms_crusher") then
					v:Add_GravelCrate(ent, ply)
					break
				end
			end
		end

		-- Used to connect a module
		if (string.sub(ent:GetClass(), 1, 12) == "zrms_refiner") then
			local validEnts = zrmine_FindValidConnectEntity(ent, 40)

			if (table.Count(validEnts) > 0) then
				local nearestEnt = zrmine_FindNearestEntity(validEnts, ent:GetPos(), 1000)
				if (zrmine_CheckPlayerAllowed(ply, nearestEnt, ent)) then return end
				nearestEnt:ConnectModule(ent)
			end
		end

		if (string.sub(ent:GetClass(), 1, 13) == "zrms_splitter") then
			local validEnts = zrmine_FindValidConnectEntity(ent, 25)

			if (table.Count(validEnts) > 0) then
				local nearestEnt = zrmine_FindNearestEntity(validEnts, ent:GetPos(), 1000)
				if (zrmine_CheckPlayerAllowed(ply, nearestEnt, ent)) then return end
				nearestEnt:ConnectModule(ent)
			end
		end

		if (string.sub(ent:GetClass(), 1, 11) == "zrms_sorter") then
			local validEnts = zrmine_FindValidConnectEntity(ent, 25)

			if (table.Count(validEnts) > 0) then
				local nearestEnt = zrmine_FindNearestEntity(validEnts, ent:GetPos(), 1000)
				if (zrmine_CheckPlayerAllowed(ply, nearestEnt, ent)) then return end
				nearestEnt:ConnectModule(ent)
			end
		end
		if (string.sub(ent:GetClass(), 1, 13) == "zrms_inserter") then
			local validEnts = zrmine_FindValidConnectEntity(ent, 25)

			if (table.Count(validEnts) > 0) then
				local nearestEnt = zrmine_FindNearestEntity(validEnts, ent:GetPos(), 1000)
				if (zrmine_CheckPlayerAllowed(ply, nearestEnt, ent)) then return end
				nearestEnt:ConnectModule(ent)
			end
		end

		if (string.sub(ent:GetClass(), 1, 17) == "zrms_conveyorbelt") then
			local validEnts = zrmine_FindValidConnectEntity(ent, 50)

			if (table.Count(validEnts) > 0) then
				local nearestEnt = zrmine_FindNearestEntity(validEnts, ent:GetPos(), 1000)
				if (zrmine_CheckPlayerAllowed(ply, nearestEnt, ent)) then return end
				nearestEnt:ConnectModule(ent)
			end
		end

		-- Used to add bars into a storage crate
		if (ent:GetClass() == "zrms_storagecrate") then
			for k, v in pairs(ents.FindInSphere(ent:GetPos(), 30)) do
				if (v:GetClass() == "zrms_bar" and not IsValid(v:GetParent())) then
					if (ent.BarCount < 12) then
						ent:Add_Bar(v)
					else
						break
					end
				end
			end
		end

		/*
		if (ent:GetClass() == "zrms_bar") then
			for k, v in pairs(ents.FindInSphere(ent:GetPos(), 15)) do
				if (v:GetClass() == "zrms_storagecrate" and v.BarCount < 12) then
					v:Add_Bar(ent)
					break
				end
			end
		end
		*/
	end

	hook.Add("GravGunOnDropped", "zrmine_gravgun_drop", zrmine_gravgun_drop)
