require(game.ReplicatedFirst.ReadyModule)
-- This is a script that handles a tool for creating objects
local player = game.Players.LocalPlayer
-- Gui Objects
local paintFrame = _G:WaitFor("PaintFrame")
--local paintSelection = paintFrame:WaitForChild("ScrollingFrame")
--local paintDefault = paintSelection:WaitForChild("Default")
local userInputEvent = nil

local renderEvent = nil
local mouseModule = require(_G.Modules.MouseModule)

local currentColor = Color3.new(1, 1, 1)
local lastPainted = nil

local input = game:GetService("UserInputService")

local partStateModule = require(_G.Modules.PartStateModule)
local partState = partStateModule.new()

local paintFrame = _G:WaitFor("PaintFrame")

local colorPickerFrame = paintFrame.ColorPickerFrame
local colorSelectorFrame = paintFrame.ColorSelectorFrame
local colorLabel = paintFrame.ColorLabel

local materialSelectorFrame = paintFrame.MaterialSelectorFrame
local materialLabel = paintFrame.MaterialLabel

local polyFrame = paintFrame.PolyFrame
local polyLabel = paintFrame.PolyLabel

-- local label = game:GetService("Selection"):Get()[1] for name,id in ([[DiamondPlate7546654401Metal7547178395Wood7547190453WoodPlanks7547301709SmoothPlastic Rubber14108673018Neon Glass7547304577]]):gmatch("([a-zA-Z]+)([0-9]*)") do local l = label:Clone() l.Parent = label.Parent l.Image = "rbxassetid://"..id l.Name = name end

local hues = {}
local hue = Color3.new(0,0,1)
local finalColor = nil

local function makeColorGradient()
	local n = tonumber
	local t = {}
	for r,g,b in ("100101001011010110100"):gmatch("(.)(.)(.)") do
		local color = Color3.new(n(r),n(g),n(b))
		--table.insert(t,ColorSequenceKeypoint.new(#t/7,color))
		table.insert(hues,color)
	end
	--return ColorSequence.new(t)
end
makeColorGradient()

local function getHue(value)
	local index1 = math.clamp(math.floor(value*6)+1,1,7)
	local index2 = math.clamp(math.floor(value*6)+2,2,7)
	local a = hues[index1]
	local b = hues[index2]
	local alpha = value*6 - math.floor(value*6)
	print(value,index1,index2,alpha)
	return a:Lerp(b,alpha)
end

local function pickerFactory(object,callback,use_x,use_y)
	local held
	local inputs = {[Enum.UserInputType.MouseButton1]=true,[Enum.UserInputType.Touch]=true,[Enum.UserInputType.MouseMovement]=true}
	local function changed(input)
		if input == held or (held and input.UserInputType == Enum.UserInputType.MouseMovement) then
			local p = object.Pointer.Position
			local s = object.Pointer.AbsoluteSize
			local x_scale,y_scale,x_offset,y_offset,x_value,y_value
			if use_x then
				x_scale = math.clamp((input.Position.X - object.AbsolutePosition.X) / (object.AbsoluteSize.X + s.X),0,object.AbsoluteSize.X/(object.AbsoluteSize.X + s.X))
				x_value = math.clamp((input.Position.X - object.AbsolutePosition.X) / (object.AbsoluteSize.X),0,1)
				x_offset = s.X/2
			else
				x_scale = p.X.Scale
				x_offset = p.X.Offset
			end
			if use_y then
				y_scale = math.clamp((input.Position.Y - object.AbsolutePosition.Y) / (object.AbsoluteSize.Y + s.Y),0,object.AbsoluteSize.Y/(object.AbsoluteSize.Y + s.Y))
				y_value = math.clamp((input.Position.Y - object.AbsolutePosition.Y) / (object.AbsoluteSize.Y),0,1)
				y_offset = s.Y/2
			else
				y_scale = p.Y.Scale
				y_offset = p.Y.Offset
			end
			object.Pointer.Position = UDim2.new(x_scale,x_offset,y_scale,y_offset)
			callback(x_value,y_value)
		end
	end
	object.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseButton1 then
			held = input
			changed(input)
		end
	end)
	object.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseButton1 then
			held = nil
		end
	end)
	input.InputChanged:Connect(changed)
end

local saturation = 0
local brightness = 0
local function updateColor()
	finalColor = hue:Lerp(Color3.new(1,1,1),saturation):Lerp(Color3.new(0,0,0),brightness)
	colorSelectorFrame.Preview.BackgroundColor3 = finalColor
	colorLabel.CancelButton.Visible = true
end

pickerFactory(colorPickerFrame.Hue,function(_,y)
	local color = getHue(y)
	hue = color
	colorPickerFrame.Picker.BackgroundColor3 = color
	updateColor()
end,false,true)

pickerFactory(colorPickerFrame.Picker,function(x,y)
	saturation = 1-x
	brightness = y
	updateColor()
end,true,true)

local colorPicking = false
colorSelectorFrame.PickButton.Activated:Connect(function()
	colorPicking = true
	colorSelectorFrame.PickButton.BackgroundColor3 = Color3.new(0.5,1,0.5)
end)

colorLabel.CancelButton.Activated:Connect(function()
	colorLabel.CancelButton.Visible = false
	finalColor = nil
end)

local finalMaterial = nil
local materialStroke = materialSelectorFrame:WaitForChild("UIStroke")
materialStroke.Enabled = true
materialStroke.Parent = nil

for _,item in pairs(materialSelectorFrame:GetChildren()) do
	if item:IsA("ImageButton") then
		item.Activated:Connect(function()
			finalMaterial = Enum.Material[item.Name]
			materialLabel.CancelButton.Visible = true
			materialStroke.Parent = item
		end)
	end
end
materialLabel.CancelButton.Activated:Connect(function()
	materialLabel.CancelButton.Visible = false
	materialStroke.Parent = nil
	finalMaterial = nil
end)

local finalShift = nil
local finalThickness = nil

polyFrame.ShiftButton.Activated:Connect(function()
	if not finalShift then finalShift = 1
	elseif finalShift == 1 then finalShift = -1
	elseif finalShift == -1 then finalShift = nil end

	if not finalShift then polyFrame.ShiftButton.Text = "Shift Off"
	elseif finalShift == -1 then polyFrame.ShiftButton.Text = "Shift Out"
	elseif finalShift == 1 then polyFrame.ShiftButton.Text = "Shift In" end

	polyLabel.CancelButton.Visible = true
end)

polyFrame.ThicknessBox.FocusLost:Connect(function(enter)
	if enter then
		finalThickness = tonumber(polyFrame.ThicknessBox.Text) or nil
		if finalThickness < 0.05 then finalThickness = 0.05 end
		local text = ""
		if finalThickness then text = tostring(finalThickness).." studs" end 
		polyFrame.ThicknessBox.Text = text
	end

	polyLabel.CancelButton.Visible = true
end)

polyLabel.CancelButton.Activated:Connect(function()
	polyLabel.CancelButton.Visible = false
	finalShift = nil
	finalThickness = nil
	polyFrame.ShiftButton.Text = "Shift Off"
	polyFrame.ThicknessBox.Text = ""
end)

polyLabel.CancelButton.Visible = false
colorLabel.CancelButton.Visible = false
materialLabel.CancelButton.Visible = false

local function render(delta)
	local result = mouseModule.getMouseHit()
	if result and result.Instance then
		local object = _G.Methods.getObjectFromPart(result.Instance,player)
		if object then script.SelectionBox.Adornee = object else script.SelectionBox.Adornee = nil end
		script.SelectionBox.FillTransparency = 1
		if not mouseModule.isMouseDown() then return end
		script.SelectionBox.FillTransparency = 0.5
		if colorPicking then
			finalColor = result.Instance.Color
			colorSelectorFrame.Preview.BackgroundColor3 = finalColor
			colorPicking = false
			colorSelectorFrame.PickButton.BackgroundColor3 = Color3.new(1,1,1)
			if object then lastPainted = object end
			return
		end
		if lastPainted == object then return end
		lastPainted = object
		if not lastPainted then return end 
		local state = partStateModule.new()
		if finalColor then state.color = finalColor end
		if finalShift then state.look = game.Workspace.CurrentCamera.CFrame.LookVector state.shift = finalShift end
		if finalThickness then state.size = Vector3.new(finalThickness,0,0) end
		if finalMaterial then state.material = finalMaterial end
		_G.Remotes.Apply:FireServer(lastPainted,state:serialise())
	else
		lastPainted = nil
		script.SelectionBox.Adornee = nil
	end
end

paintFrame.Visible = false

local function init(s)
	if renderEvent then renderEvent:Disconnect() end
	s.Parent.Equipped:Connect(function()
		if renderEvent then renderEvent:Disconnect() end
		renderEvent = game:GetService("RunService").RenderStepped:Connect(render)
		paintFrame.Visible = true
	end)

	s.Parent.Unequipped:Connect(function() 
		if renderEvent then renderEvent:Disconnect() end
		paintFrame.Visible = false
		script.SelectionBox.Adornee = nil
	end)
end

return {init = init}