local StarterGui = game:GetService("StarterGui")
StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)

local frame = script.Parent
frame.Visible = true

local input = game:GetService("UserInputService")

local player = game.Players.LocalPlayer
local backpack = player.Backpack

local stroke = script:WaitForChild("UIStroke")

local currentTool = nil

local tools = {}

local frames = {}

local function isToolRegistered(tool) return tools[tool] end

local function getToolFrame(tool) return frames[tool] end

local function stockTool(tool) 
	tool.Parent = backpack
	stroke.Parent = script
	stroke.Transparency = 1
	frames[tool].Deselected:Fire()
end

local index = 0

local function setTool(tool)
	if currentTool then stockTool(currentTool) end -- If there is already a tool equipped, dequip it
	if currentTool == tool then currentTool = nil return end -- If this tool is already equipped, remove it and stop
	
	if tonumber(tool.Name) then index = tonumber(tool.Name) end 
	frames[tool].Selected:Fire()
	tool.Parent = player.Character -- Equip the new tool
	stroke.Parent = frames[tool]
	stroke.Transparency = 0.2
	currentTool = tool
end

local nameToInteger = {
	["One"] = 1,
	["Two"] = 2,
	["Three"] = 3,
	["Four"] = 4,
	["Five"] = 5,
	["Six"] = 6,
	["Seven"] = 7,
	["Eight"] = 8,
	["Nine"] = 9
}

input.InputBegan:Connect(function(input,irrelevant)
	if not irrelevant then
		local tools = 0
		for _,item in pairs(frame.ScrollingFrame:GetChildren()) do
			if item:FindFirstChild("ToolReference") then tools = tools + 1 end 
		end
		local inputted = false
		if input.UserInputType == Enum.UserInputType.Keyboard then
			local number = nameToInteger[input.KeyCode.Name]
			if number then inputted = true index = number end
		elseif input.KeyCode == Enum.KeyCode.ButtonR1 then
			inputted = true
			index = index + 1
		elseif input.KeyCode == Enum.KeyCode.ButtonL1 then
			inputted = true
			index = index - 1
		end
		index = math.clamp(index,0,tools+1)
		if not inputted then return end
		local toolFrame = frame.ScrollingFrame:FindFirstChild(tostring(index))
		if toolFrame then
			setTool(toolFrame.ToolReference.Value)
		else
			if currentTool then stockTool(currentTool) currentTool = nil end
		end
	end
end)

local function createToolFrame(tool)
	local toolFrame = frame.ScrollingFrame.Template.Tool:Clone()
	toolFrame.ToolReference.Value = tool
	local layout = tool:WaitForChild("LayoutOrderValue",1)
	if layout then layout = layout.Value
	else layout = #frames end
	toolFrame.LayoutOrder = layout
	frames[tool] = toolFrame
	tools[tool] = tool
	local clone = tool:Clone()
	for _,child in pairs(clone:GetChildren()) do
		if child:IsA("Script") then 
			child:Destroy() 
		end
	end
	toolFrame.Parent = frame.ScrollingFrame
	toolFrame.Visible = true
	toolFrame.Name = tostring(toolFrame.LayoutOrder)
	local viewport = toolFrame.ViewportFrame
	viewport.Name = clone.Name
	clone.Parent = viewport
	local camera = Instance.new("Camera")
	viewport.CurrentCamera = camera
	camera.Parent = viewport
	local label = toolFrame.TextLabel
	label.Text = tool.Name
	local cframe,size = clone:GetBoundingBox()

	local cameraRotation = 45
	local distance = size.Magnitude

	local function rotateCamera() -- To constantly spin the tool view
		camera.CFrame = CFrame.new(cframe.Position) * CFrame.fromEulerAnglesYXZ(-0.3,math.rad(cameraRotation),0)
		camera.CFrame = camera.CFrame + camera.CFrame.LookVector * -(distance/1.2)
	end

	rotateCamera() -- To initialise the camera CFrame once
	
	local mouseInside = 0 -- Rotate camera while the mouse is inside the tool
	local mouseEnter = function(no_back)
		mouseInside = mouseInside + 1
		if not no_back then toolFrame.BackgroundColor3 = Color3.new(0.75,0.75,0.75) end
		if mouseInside == 1 then while wait() and mouseInside > 0 do
			cameraRotation = cameraRotation + 1.5 * mouseInside
			rotateCamera()
		end end
	end
	local mouseLeave = function(no_back)
		mouseInside = mouseInside - 1
		if not no_back then toolFrame.BackgroundColor3 = Color3.new(1,1,1) end
	end
	viewport.MouseEnter:Connect(mouseEnter)
	viewport.MouseLeave:Connect(mouseLeave)
	toolFrame.Selected.Event:Connect(mouseEnter)
	toolFrame.Deselected.Event:Connect(mouseLeave)
	return toolFrame
end

local function unregisterTool(tool)
	--print(tool:GetFullName())
	if currentTool == tool then stroke.Parent = script currentTool = nil end
	if frames[tool] then frames[tool]:Destroy() end
	frames[tool] = nil
	tools[tool] = nil
end

local function registerTool(tool) 
	if isToolRegistered(tool) then return end -- Don't register an existing tool
	
	tool.AncestryChanged:Connect(function(tool,parent) -- Event for when parent changes
		if not (parent == player.Character or parent == backpack) then -- If the tool is not a parent of the character or backpack, it is dropped
			unregisterTool(tool)
		end
	end)
	
	createToolFrame(tool)
	
	-- todo: save me
	frames[tool].InputEnded:Connect(function(inputObject) -- When the mouse button or touch is clicked (XBOX + VR CONTROL NEEDED)
		if inputObject.UserInputType == Enum.UserInputType.MouseButton1 or inputObject.UserInputType == Enum.UserInputType.Touch then
			setTool(tool)
		end
	end)
	--[[frames[tool].TouchTap:Connect(function()
		setTool(tool)
	end)]]
end

game.Players.LocalPlayer.ChildAdded:Connect(function(child)
	if currentTool then unregisterTool(currentTool) end
	if child:IsA("Backpack") then backpack = child end
	backpack.ChildAdded:Connect(registerTool)
	backpack.ChildRemoved:Connect(registerTool)
end)

for _,tool in pairs(backpack:GetChildren()) do
	registerTool(tool)
end