local h=game:GetService("\083\101\108\101\099\116\105\111\110")local z=script.Parent.Parent local r=require(z.Constants)local k=require(z.Layers)local P=require(z.Vendor.Roact)local x=require(z.Vendor.StudioComponents)local w=x.Button local D=x.MainButton local t=require(script.Parent.List)local X=require(script.Parent.Move)local O=require(script.Parent.CreateLayerWidget)local Z=require(script.Parent.DeleteLayerWidget)local b=require(script.Parent.EditLayerWidget)local a=P.Component:extend("\065\112\112")function a.init(z)z:setState({Layers=k.Stack,SelectedLayerId=1,Enabled=true,CreatingLayer=false,EditingLayer=false,DeletingLayer=false;MaxLayers=false})z.Connections={}z.batchSetLayer=function(h,r)k:AddChildren(r,h)z:update(r)z:setState({Layers=k.Stack})end z.setLayer=function(h,r)k:AddChild(r,h)z:update(r)z:setState({Layers=k.Stack})end z.removeFromLayer=function(h,r)k:RemoveChild(r,h)z:update(r)z:setState({Layers=k.Stack})end z.createLayer=function(h)local P=k:New(h)if P then z:update(P)z:setState({Layers=k.Stack})if P==r.MaxLayers then z:setState({MaxLayers=true})end else warn(("\082\101\097\099\104\101\100 \109\097\120\105\109\117\109 \110\117\109\098\101\114 \111\102 \108\097\121\101\114\115 \040\037\115\041\046"):format(r.MaxLayers))end end z.editLayer=function(h,z)if z.transparency then z.transparency=nil end k:Edit(h,z)end z.deleteLayer=function(h)local r=k:Remove(h)if r then z:update(r)z:setState({MaxLayers=false,Layers=k.Stack})else warn(("\073\100 \037\115 \100\111\101\115 \110\111\116 \101\120\105\115\116\046"):format(h))end end z.toggleVisibility=function(h)k:ToggleProperty(h,"\086\105\115\105\098\108\101")z:setState({Layers=k.Stack})end z.toggleLock=function(h)k:ToggleProperty(h,"\076\111\099\107\101\100")z:setState({Layers=k.Stack})end z.updateSelection=function()local r={}for h,z in pairs(k.Stack[z.state.SelectedLayerId].Children)do if h.Parent~=nil then table.insert(r,h)end end h:Set(r)z:setState({Layers=k.Stack})end z.moveLayerUp=function(h)if h~=1 and k.Stack[h+1]then k:Move(h,1)z:update(h+1)z:setState({Layers=k.Stack})end end z.moveLayerDown=function(h)if h~=1 and h-1>1 then k:Move(h,-1)z:update(h-1)z:setState({Layers=k.Stack})end end table.insert(z.Connections,z.props.Actions.NewLayer.Triggered:Connect(function()if not z.state.CreatingLayer or z.state.DeletingLayer then z:setState({CreatingLayer=true})end end))table.insert(z.Connections,z.props.Actions.RemoveLayer.Triggered:Connect(function()if not z.state.CreatingLayer or z.state.DeletingLayer then z:setState({DeletingLayer=true})end end))table.insert(z.Connections,z.props.Actions.MoveLayerUp.Triggered:Connect(function()z.moveLayerUp(z.state.SelectedLayerId)end))table.insert(z.Connections,z.props.Actions.MoveLayerDown.Triggered:Connect(function()z.moveLayerDown(z.state.SelectedLayerId)end))table.insert(z.Connections,z.props.Actions.MoveActiveUp.Triggered:Connect(function()local h=z.state.SelectedLayerId+1 if h<=#k.Stack then z:update(h)end end))table.insert(z.Connections,z.props.Actions.MoveActiveDown.Triggered:Connect(function()local h=z.state.SelectedLayerId-1 if h>0 then z:update(h)end end))table.insert(z.Connections,z.props.Actions.GetSelection.Triggered:Connect(function()z.updateSelection()end))table.insert(z.Connections,z.props.Actions.MoveSelection.Triggered:Connect(function()local r={}for h,z in pairs(h:Get())do if z:IsA("\066\097\115\101\080\097\114\116")and z.Parent~=nil then table.insert(r,z)end end z.batchSetLayer(r,z.state.SelectedLayerId)end))table.insert(z.Connections,z.props.Actions.ToggleVisibility.Triggered:Connect(function()z.toggleVisibility(z.state.SelectedLayerId)end))table.insert(z.Connections,z.props.Actions.ToggleLocked.Triggered:Connect(function()z.toggleLock(z.state.SelectedLayerId)end))end function a.willUnmount(h)for h,z in pairs(h.Connections)do z:Disconnect()end end function a.update(z,h)z:setState({SelectedLayerId=h})k:SetCurrentLayer(h)end function a.render(h)local z=h.state.CreatingLayer or h.state.DeletingLayer or not h.state.Enabled local r=k.Stack[h.state.SelectedLayerId].Name local x=k.Stack[h.state.SelectedLayerId].Properties.Transparency return P.createFragment({CreateWidget=h.state.CreatingLayer and P.createElement(O,{Title="\067\114\101\097\116\101 \076\097\121\101\114";Layers=h.state.Layers,OnClosed=function()h:setState({CreatingLayer=false})end,OnSubmitted=function(z)h.createLayer(z)h:setState({CreatingLayer=false})end});DeleteWidget=h.state.DeletingLayer and P.createElement(Z,{Title=("\068\101\108\101\116\101 \076\097\121\101\114 \040\037\115"):format(r),LayerName=r;OnClosed=function()h:setState({DeletingLayer=false})end,OnActivated=function()h.deleteLayer(h.state.SelectedLayerId)h:setState({DeletingLayer=false})end});EditWidget=h.state.EditingLayer and P.createElement(b,{Title=("\069\100\105\116 \076\097\121\101\114 \040\037\115\041"):format(r);Layers=h.state.Layers;LayerName=r,Transparency=x,OnClosed=function()h:setState({EditingLayer=false})h:update()end,OnUpdate=function(z)h.editLayer(h.state.SelectedLayerId,z)h:update()end;OnReset=function() end,OnSubmitted=function(z)h.editLayer(h.state.SelectedLayerId,z)h:setState({EditingLayer=false})h:update()end});UI=P.createElement("\070\114\097\109\101",{AnchorPoint=Vector2.new(0,1);BackgroundTransparency=1;Position=UDim2.fromScale(0,1);Size=UDim2.new(1,0,1,-5)},{Padding=P.createElement("\085\073\080\097\100\100\105\110\103",{PaddingLeft=UDim.new(0,4);PaddingRight=UDim.new(0,4),PaddingTop=UDim.new(0,4),PaddingBottom=UDim.new(0,4)});List=P.createElement(t,{Layers=h.state.Layers;SelectedLayerId=h.state.SelectedLayerId;Disabled=z;Size=UDim2.new(1,0,1,-35),SetSelectedLayerId=function(z)h:update(z)if h.state.EditingLayer then h:setState({EditingLayer=false})h:setState({EditingLayer=true})end end,ToggleVisibility=function(z)h.toggleVisibility(z)end;ToggleLock=function(z)h.toggleLock(z)end;MoveLayerUp=function(z)h.moveLayerUp(z)end;MoveLayerDown=function(z)h.moveLayerDown(z)end});Bar=P.createElement("\070\114\097\109\101",{AnchorPoint=Vector2.new(0,1),Position=UDim2.fromScale(0,1);Size=UDim2.new(1,0,0,28);BackgroundTransparency=1},{Layout=P.createElement("\085\073\076\105\115\116\076\097\121\111\117\116",{SortOrder=Enum.SortOrder.LayoutOrder,FillDirection=Enum.FillDirection.Horizontal;Padding=UDim.new(0,6)}),ActiveToggle=P.createElement(w,{LayoutOrder=0;Size=UDim2.new(0,28,1,0);Text="",OnActivated=function()h:setState({Enabled=not h.state.Enabled})k:SetEnabled(h.state.Enabled)end},{Icon=P.createElement("\073\109\097\103\101\076\097\098\101\108",{AnchorPoint=Vector2.new(.5,.5);Position=UDim2.fromScale(.5,.5);Size=UDim2.fromOffset(16,16);BackgroundTransparency=1,Image="\114\098\120\097\115\115\101\116\105\100\058\047\047\056\054\053\054\056\057\055\051\055\052";ImageColor3=(settings()).Studio.theme:GetColor(Enum.StudioStyleGuideColor.MainText)})});Create=P.createElement(D,{LayoutOrder=1;Size=UDim2.new(0,28,1,0);Text="",OnActivated=function()h:setState({CreatingLayer=true})end;Disabled=z or h.state.MaxLayers},{Icon=P.createElement("\073\109\097\103\101\076\097\098\101\108",{AnchorPoint=Vector2.new(.5,.5),Position=UDim2.fromScale(.5,.5);Size=UDim2.fromOffset(16,16);BackgroundTransparency=1,Image="\114\098\120\097\115\115\101\116\105\100\058\047\047\054\054\056\056\056\051\057\051\052\051";ImageTransparency=(z or h.state.MaxLayers)and.75 or 0})});Delete=P.createElement(w,{LayoutOrder=2;Size=UDim2.new(0,28,1,0);Text="";OnActivated=function()h:setState({DeletingLayer=true})end;Disabled=h.state.SelectedLayerId==1 or z},{Icon=P.createElement("\073\109\097\103\101\076\097\098\101\108",{AnchorPoint=Vector2.new(.5,.5);Position=UDim2.fromScale(.5,.5);Size=UDim2.fromOffset(32,32),BackgroundTransparency=1;Image="\114\098\120\097\115\115\101\116\105\100\058\047\047\055\050\048\051\049\048\056\057\052\048",ImageColor3=(settings()).Studio.Theme:GetColor(Enum.StudioStyleGuideColor.MainText),ImageTransparency=(h.state.SelectedLayerId==1 or z)and.75 or 0})}),Edit=P.createElement(w,{LayoutOrder=3;Size=UDim2.new(.3,-28,1,0),Text="\069\100\105\116";OnActivated=function()h:setState({EditingLayer=true})end;Disabled=z}),Move=P.createElement(X,{LayoutOrder=4,Size=UDim2.new(.3,-28,1,0);Disabled=not h.state.Enabled;BatchSetLayer=function(z)h.batchSetLayer(z,h.state.SelectedLayerId)end});Select=P.createElement(w,{LayoutOrder=5,Size=UDim2.new(.3,-28,1,0);Text="\083\101\108\101\099\116 \065\108\108",OnActivated=h.updateSelection;Disabled=z})})})})end return a
local Selection = game:GetService("Selection")

local Plugin = script.Parent.Parent
local Constants = require(Plugin.Constants)
local Layers = require(Plugin.Layers)

local Roact = require(Plugin.Vendor.Roact)
local StudioComponents = require(Plugin.Vendor.StudioComponents)

local Button = StudioComponents.Button
local MainButton = StudioComponents.MainButton
local List = require(script.Parent.List)
local Move = require(script.Parent.Move)
local CreateLayerWidget = require(script.Parent.CreateLayerWidget)
local DeleteLayerWidget = require(script.Parent.DeleteLayerWidget)
local EditLayerWidget = require(script.Parent.EditLayerWidget)

local App = Roact.Component:extend("App")

function App:init()

	self:setState({
		Layers = Layers.Stack,
		SelectedLayerId = 1,
		Enabled = true,
		CreatingLayer = false,
		EditingLayer = false,
		DeletingLayer = false,
		MaxLayers = false
	})

	self.Connections = {}

	self.batchSetLayer = function(instances, id)
		Layers:AddChildren(id, instances)
		self:update(id)
		self:setState({ Layers = Layers.Stack })
	end

	self.setLayer = function(instance, id)
		Layers:AddChild(id, instance)
		self:update(id)
		self:setState({ Layers = Layers.Stack })
	end

	self.removeFromLayer = function(instance, id)
		Layers:RemoveChild(id, instance)
		self:update(id)
		self:setState({ Layers = Layers.Stack})
	end

	self.createLayer = function(name)
		local res = Layers:New(name)
		if res then
			self:update(res)
			self:setState({ Layers = Layers.Stack })
			if res == Constants.MaxLayers then
				self:setState({ MaxLayers = true })
			end
		else
			warn(("Reached maximum number of layers (%s)."):format(Constants.MaxLayers))
		end
	end

	self.editLayer = function(id, newProperties)
		if newProperties.transparency then
			newProperties.transparency = nil
		end
		Layers:Edit(id, newProperties)
	end

	self.deleteLayer = function(id)
		local res = Layers:Remove(id)
		if res then
			self:update(res)
			self:setState({
				MaxLayers = false,
				Layers = Layers.Stack
			})
		else
			warn(("Id %s does not exist."):format(id)) -- this should never happen anyway
		end
	end

	self.toggleVisibility = function(id)
		Layers:ToggleProperty(id, "Visible")
		self:setState({ Layers = Layers.Stack })
	end

	self.toggleLock = function(id)
		Layers:ToggleProperty(id, "Locked")
		self:setState({ Layers = Layers.Stack })
	end

	self.updateSelection = function()
		--Layers.updateSelection(self.state.SelectedLayerId)
		local objects = {}
		for instance, _ in pairs(Layers.Stack[self.state.SelectedLayerId].Children) do
			if instance.Parent ~= nil then
				table.insert(objects, instance)
			end
		end
		Selection:Set(objects)
		self:setState({ Layers = Layers.Stack })
	end

	self.moveLayerUp = function(id)
		if id ~= 1 and Layers.Stack[id + 1] then
			Layers:Move(id, 1)
			self:update(id + 1)
			self:setState({ Layers = Layers.Stack })
		end
	end

	self.moveLayerDown = function(id)
		if id ~= 1 and id - 1 > 1 then
			Layers:Move(id, -1)
			self:update(id - 1)
			self:setState({ Layers = Layers.Stack })
		end
	end

	-- keybinds
	table.insert(self.Connections, self.props.Actions["NewLayer"].Triggered:Connect(function()
		if not self.state.CreatingLayer or self.state.DeletingLayer then
			self:setState({ CreatingLayer = true })
		end
	end))

	table.insert(self.Connections, self.props.Actions["RemoveLayer"].Triggered:Connect(function()
		if not self.state.CreatingLayer or self.state.DeletingLayer then
			self:setState({ DeletingLayer = true })
		end
	end))

	table.insert(self.Connections, self.props.Actions["MoveLayerUp"].Triggered:Connect(function()
		self.moveLayerUp(self.state.SelectedLayerId)
	end))

	table.insert(self.Connections, self.props.Actions["MoveLayerDown"].Triggered:Connect(function()
		self.moveLayerDown(self.state.SelectedLayerId)
	end))

	table.insert(self.Connections, self.props.Actions["MoveActiveUp"].Triggered:Connect(function()
		local newId = self.state.SelectedLayerId + 1
		if newId <= #Layers.Stack then
			self:update(newId)
		end
	end))

	table.insert(self.Connections, self.props.Actions["MoveActiveDown"].Triggered:Connect(function()
		local newId = self.state.SelectedLayerId - 1
		if newId > 0 then
			self:update(newId)
		end
	end))

	table.insert(self.Connections, self.props.Actions["GetSelection"].Triggered:Connect(function()
		self.updateSelection()
	end))

	table.insert(self.Connections, self.props.Actions["MoveSelection"].Triggered:Connect(function()
		local targets = {}

		for _, obj in pairs(Selection:Get()) do
			if obj:IsA("BasePart") and obj.Parent ~= nil then
				table.insert(targets, obj)
			end
		end

		self.batchSetLayer(targets, self.state.SelectedLayerId)
	end))

	table.insert(self.Connections, self.props.Actions["ToggleVisibility"].Triggered:Connect(function()
		self.toggleVisibility(self.state.SelectedLayerId)
	end))

	table.insert(self.Connections, self.props.Actions["ToggleLocked"].Triggered:Connect(function()
		self.toggleLock(self.state.SelectedLayerId)
	end))

end

function App:willUnmount()
	for _, conn in pairs(self.Connections) do
		conn:Disconnect()
	end
end

function App:update(id)
	self:setState({SelectedLayerId = id})
	Layers:SetCurrentLayer(id)
end

function App:render()
	local isModalActive = self.state.CreatingLayer or self.state.DeletingLayer or (not self.state.Enabled)
	local selectedLayerName = Layers.Stack[self.state.SelectedLayerId].Name
	local selectedLayerTransparency = Layers.Stack[self.state.SelectedLayerId].Properties.Transparency

	return Roact.createFragment({
		CreateWidget = self.state.CreatingLayer and Roact.createElement(CreateLayerWidget, {
			Title = "Create Layer",
			Layers = self.state.Layers,
			OnClosed = function()
				self:setState({ CreatingLayer = false })
			end,
			OnSubmitted = function(name)
				self.createLayer(name)
				self:setState({ CreatingLayer = false })
			end
		}),
		DeleteWidget = self.state.DeletingLayer and Roact.createElement(DeleteLayerWidget, {
			Title = ("Delete Layer (%s"):format(selectedLayerName),
			LayerName = selectedLayerName,
			OnClosed = function()
				self:setState({ DeletingLayer = false })
			end,
			OnActivated = function()
				self.deleteLayer(self.state.SelectedLayerId)
				self:setState({ DeletingLayer = false })
			end
		}),
		EditWidget = self.state.EditingLayer and Roact.createElement(EditLayerWidget, {
			Title = ("Edit Layer (%s)"):format(selectedLayerName),
			Layers = self.state.Layers,
			LayerName = selectedLayerName,
			Transparency = selectedLayerTransparency,
			OnClosed = function()
				self:setState({ EditingLayer = false })
				--Layers.resetTransparency(self.state.SelectedLayerId)
				self:update()
			end,
			OnUpdate = function(properties)
				self.editLayer(self.state.SelectedLayerId, properties)
				self:update()
			end,
			OnReset = function()
				--Layers.resetTransparency(self.state.SelectedLayerId)
			end,
			OnSubmitted = function(properties)
				self.editLayer(self.state.SelectedLayerId, properties)
				self:setState({ EditingLayer = false })
				self:update()
			end
		}),
		UI = Roact.createElement("Frame", {
			AnchorPoint = Vector2.new(0, 1),
			BackgroundTransparency = 1,
			Position = UDim2.fromScale(0, 1),
			Size = UDim2.new(1, 0, 1, -5)
		}, {
			Padding = Roact.createElement("UIPadding", {
				PaddingLeft = UDim.new(0, 4),
				PaddingRight = UDim.new(0, 4),
				PaddingTop = UDim.new(0, 4),
				PaddingBottom = UDim.new(0, 4),
			}),
			List = Roact.createElement(List, {
				Layers = self.state.Layers,
				SelectedLayerId = self.state.SelectedLayerId,
				Disabled = isModalActive,
				Size = UDim2.new(1, 0, 1, -35),
				SetSelectedLayerId = function(id)
					self:update(id)
					if self.state.EditingLayer then
						self:setState({ EditingLayer = false })
						self:setState({ EditingLayer = true })
					end
				end,
				ToggleVisibility = function(id)
					self.toggleVisibility(id)
				end,
				ToggleLock = function(id)
					self.toggleLock(id)
				end,
				MoveLayerUp = function(id)
					self.moveLayerUp(id)
				end,
				MoveLayerDown = function(id)
					self.moveLayerDown(id)
				end
			}),
			Bar = Roact.createElement("Frame", {
				AnchorPoint = Vector2.new(0, 1),
				Position = UDim2.fromScale(0, 1),
				Size = UDim2.new(1, 0, 0, 28),
				BackgroundTransparency = 1
			}, {
				Layout = Roact.createElement("UIListLayout", {
					SortOrder = Enum.SortOrder.LayoutOrder,
					FillDirection = Enum.FillDirection.Horizontal,
					Padding = UDim.new(0, 6),
				}),
				ActiveToggle = Roact.createElement(Button, {
					LayoutOrder = 0,
					Size = UDim2.new(0, 28, 1, 0),
					Text = "",
					OnActivated = function()
						self:setState({ Enabled = not self.state.Enabled })
						Layers:SetEnabled(self.state.Enabled)
					end,
				}, {
					Icon = Roact.createElement("ImageLabel", {
						AnchorPoint = Vector2.new(0.5, 0.5),
						Position = UDim2.fromScale(0.5, 0.5),
						Size = UDim2.fromOffset(16, 16),
						BackgroundTransparency = 1,
						Image = "rbxassetid://8656897374",
						ImageColor3 = settings().Studio.theme:GetColor(Enum.StudioStyleGuideColor.MainText)
					}),
				}),
				Create = Roact.createElement(MainButton, {
					LayoutOrder = 1,
					Size = UDim2.new(0, 28, 1, 0),
					Text = "",
					OnActivated = function()
						self:setState({ CreatingLayer = true })
					end,
					Disabled = isModalActive or self.state.MaxLayers,
				}, {
					Icon = Roact.createElement("ImageLabel", {
						AnchorPoint = Vector2.new(0.5, 0.5),
						Position = UDim2.fromScale(0.5, 0.5),
						Size = UDim2.fromOffset(16, 16),
						BackgroundTransparency = 1,
						Image = "rbxassetid://6688839343",
						ImageTransparency = (isModalActive or self.state.MaxLayers) and 0.75 or 0,
					}),
				}),
				Delete = Roact.createElement(Button, {
					LayoutOrder = 2,
					Size = UDim2.new(0, 28, 1, 0),
					Text = "",
					OnActivated = function()
						self:setState({ DeletingLayer = true })
					end,
					Disabled = self.state.SelectedLayerId == 1 or isModalActive
				}, {
					Icon = Roact.createElement("ImageLabel", {
						AnchorPoint = Vector2.new(0.5, 0.5),
						Position = UDim2.fromScale(0.5, 0.5),
						Size = UDim2.fromOffset(32, 32),
						BackgroundTransparency = 1,
						Image = "rbxassetid://7203108940",
						ImageColor3 = settings().Studio.Theme:GetColor(Enum.StudioStyleGuideColor.MainText),
						ImageTransparency = (self.state.SelectedLayerId == 1 or isModalActive) and 0.75 or 0,
					}),
				}),
				Edit = Roact.createElement(Button, {
					LayoutOrder = 3,
					Size = UDim2.new(0.3, -28, 1, 0),
					Text = "Edit",
					OnActivated = function()
						--Layers.saveTransparency(self.state.SelectedLayerId)
						self:setState({ EditingLayer = true })
					end,
					Disabled = isModalActive
				}),
				Move = Roact.createElement(Move, {
					LayoutOrder = 4,
					Size = UDim2.new(0.3, -28, 1, 0),
					Disabled = not self.state.Enabled,
					BatchSetLayer = function(targets)
						self.batchSetLayer(targets, self.state.SelectedLayerId)
					end
				}),
				Select = Roact.createElement(Button, {
					LayoutOrder = 5,
					Size = UDim2.new(0.3, -28, 1, 0),
					Text = "Select All",
					OnActivated = self.updateSelection,
					Disabled = isModalActive
				})
			})
		})
	})
end

return App