local C=script.Parent.Parent.Parent local U=C.Parent local Z=require(C.Theme)local b=Z.WithTheme local p=C.Validators local w=require(p.StyleValidator)local m=require(U.Sift)local O=require(U.t)local M=require(U.Roact)local r=M.createElement local W=game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")local V=require(C.App.Effect.DropShadow)local X=require(C.App.Surface.RoundedSurface)local i=script.Parent local l=require(i.TitleBar.TitleBar)local n=M.PureComponent:extend(script.Name)n.defaultProps={AnchorPoint=Vector2.new(.5,.5);BackgroundColor="\099\111\108\111\114\115\047\066\097\099\107\103\114\111\117\110\100\047\070\105\108\108\095\067\111\108\111\114\047\083\111\108\105\100\095\066\097\099\107\103\114\111\117\110\100\047\066\097\115\101";ContentBackgroundColor={Color=Color3.new(),Transparency=1};DropShadowEnabled=true,Draggable=true,FooterHeight=0;Position=UDim2.fromScale(.5,.5),Size=UDim2.fromOffset(300,300),TitleBarProps={}}n.validateProps=O.strictInterface({AnchorPoint=O.optional(O.Vector2);BackgroundColor=O.optional(w);ContentBackgroundColor=O.optional(w);DropShadowEnabled=O.optional(O.boolean),Draggable=O.optional(O.boolean),AutomaticSize=O.optional(O.EnumItem),FooterHeight=O.optional(O.number);FooterContents=O.optional(O.table);Position=O.optional(O.UDim2);Size=O.optional(O.UDim2),TitleBarProps=O.optional(O.table),[M.Children]=O.optional(O.table);Native=O.optional(O.table)})function n.init(C)C.Size,C.SetSize=M.createBinding(C.props.Size)C.TitleBarRef=M.createRef()C.WindowRef=M.createRef()if C.props.Draggable then C.DragConnection=W.InputChanged:Connect(function(U)local Z=C.WindowRef:getValue()if Z and(U==C.DragInput and C.Dragging)then local b=U.Position-C.DragStart Z.Position=UDim2.new(C.StartPos.X.Scale,C.StartPos.X.Offset+b.X,C.StartPos.Y.Scale,C.StartPos.Y.Offset+b.Y)end end)end end function n.willUnmount(C)if C.DragConnection then C.DragConnection:Disconnect()end end function n.didMount(C)local U=C.TitleBarRef:getValue()local Z=C.WindowRef:getValue()if U then(U:GetPropertyChangedSignal("\065\098\115\111\108\117\116\101\083\105\122\101")):Connect(function()local Z=U.AbsoluteSize C.TitleBarHeight=Z.Y end)end if U and(Z and C.props.Draggable)then U.InputBegan:Connect(function(U)if U.UserInputType==Enum.UserInputType.MouseButton1 or U.UserInputType==Enum.UserInputType.Touch then C.Dragging=true C.DragStart=U.Position C.StartPos=Z.Position local b=nil b=U.Changed:Connect(function()if U.UserInputState==Enum.UserInputState.End then C.Dragging=nil b:Disconnect()end end)end end)U.InputChanged:Connect(function(U)if U.UserInputType==Enum.UserInputType.MouseMovement or U.UserInputType==Enum.UserInputType.Touch then C.DragInput=U end end)end end function n.render(C)local U=C.props return b(function(Z)local b=r(l,m.Dictionary.join({LayoutOrder=1,Height=32;CaptionButtonWidth=45,Native={[M.Ref]=C.TitleBarRef}},U.TitleBarProps))local p=Z[U.ContentBackgroundColor]local w=r(X,{AutomaticSize=U.AutomaticSize;BackgroundColor3=p.Color;BackgroundTransparency=p.Transparency,BorderSizePixel=0,CornerRadius=UDim.new(0,Z["\115\116\121\108\101\115\047\067\111\114\110\101\114\082\097\100\105\117\115\047\068\101\102\097\117\108\116\047\079\117\116\101\114"]);ShowBottomLeftCorner=U.FooterHeight<Z["\115\116\121\108\101\115\047\067\111\114\110\101\114\082\097\100\105\117\115\047\068\101\102\097\117\108\116\047\079\117\116\101\114"]/2;ShowBottomRightCorner=U.FooterHeight<Z["\115\116\121\108\101\115\047\067\111\114\110\101\114\082\097\100\105\117\115\047\068\101\102\097\117\108\116\047\079\117\116\101\114"]/2,LayoutOrder=2;Size=U.Size;[M.Change.AbsoluteSize]=function(U)local Z=U.AbsoluteSize C.SetSize(UDim2.fromOffset(Z.X,Z.Y))end},C.props[M.Children])local O=r("\070\114\097\109\101",{BackgroundTransparency=1;LayoutOrder=3,Size=UDim2.new(1,0,0,U.FooterHeight)},U.FooterContents)local W=Z[U.BackgroundColor]local i=Z["\099\111\108\111\114\115\047\083\116\114\111\107\101\095\067\111\108\111\114\047\083\117\114\102\097\099\101\095\083\116\114\111\107\101\047\068\101\102\097\117\108\116"]local n=r("\070\114\097\109\101",m.Dictionary.join({AnchorPoint=U.DropShadowEnabled and Vector2.new(.5,.5)or U.AnchorPoint,Position=U.DropShadowEnabled and UDim2.fromScale(.5,.5)or U.Position;BackgroundColor3=W.Color;BackgroundTransparency=W.Transparency;[M.Ref]=not U.Draggable and C.WindowRef or nil;Size=C.Size:map(function(Z)return Z+UDim2.fromOffset(0,(C.TitleBarHeight or 0)+U.FooterHeight)end)},U.Native),{TitleBar=b;ContentWrapper=w;Footer=O;Stroke=r("\085\073\083\116\114\111\107\101",{Color=i.Color,Transparency=i.Transparency}),Corners=r("\085\073\067\111\114\110\101\114",{CornerRadius=UDim.new(0,Z["\115\116\121\108\101\115\047\067\111\114\110\101\114\082\097\100\105\117\115\047\068\101\102\097\117\108\116\047\079\117\116\101\114"])}),Layout=r("\085\073\076\105\115\116\076\097\121\111\117\116",{SortOrder=Enum.SortOrder.LayoutOrder})})if U.DropShadowEnabled then return r(V,{AnchorPoint=U.AnchorPoint;Position=U.Position;CornerRadius=UDim.new(0,Z["\115\116\121\108\101\115\047\067\111\114\110\101\114\082\097\100\105\117\115\047\068\101\102\097\117\108\116\047\079\117\116\101\114"]);Size=C.Size:map(function(Z)return(Z+UDim2.fromOffset(0,(C.TitleBarHeight or 0)+U.FooterHeight))+UDim2.new(0,50,0,50)end),Native={[M.Ref]=C.WindowRef}},n)else return n end end)end return n
-- Window: A component that is the base structure for a UI Window

local Winro = script.Parent.Parent.Parent
local Packages = Winro.Parent

local Theme = require(Winro.Theme)
local WithTheme = Theme.WithTheme

local Validators = Winro.Validators
local StyleValidator = require(Validators.StyleValidator)

local Sift = require(Packages.Sift)
local t = require(Packages.t)
local Roact = require(Packages.Roact)
local new = Roact.createElement

local UserInputService = game:GetService('UserInputService')

local DropShadow = require(Winro.App.Effect.DropShadow)
local RoundedSurface = require(Winro.App.Surface.RoundedSurface)

local WindowRoot = script.Parent
local TitleBar = require(WindowRoot.TitleBar.TitleBar)

local Window = Roact.PureComponent:extend(script.Name)

Window.defaultProps = {
	AnchorPoint = Vector2.new(0.5, 0.5), --- @defaultProp
	BackgroundColor = 'colors/Background/Fill_Color/Solid_Background/Base', --- @defaultProp
	ContentBackgroundColor = {
		Color = Color3.new(),
		Transparency = 1,
	}, --- @defaultProp
	DropShadowEnabled = true, --- @defaultProp
	Draggable = true, --- @defaultProp
	FooterHeight = 0, --- @defaultProp
	Position = UDim2.fromScale(0.5, 0.5), --- @defaultProp
	Size = UDim2.fromOffset(300, 300), --- @defaultProp
	TitleBarProps = {}, --- @defaultProp
}

Window.validateProps = t.strictInterface({

	--- @prop @optional AnchorPoint Vector2 The Window's anchor point
	AnchorPoint = t.optional(t.Vector2),

	--- @prop @optional @style BackgroundColor string|table The Window's background color
	BackgroundColor = t.optional(StyleValidator),

	--- @prop @optional @style ContentBackgroundColor string|table The Content's background color
	ContentBackgroundColor = t.optional(StyleValidator),

	--- @prop @optional DropShadowEnabled boolean Determines if a drop shadow is shown
	DropShadowEnabled = t.optional(t.boolean),

	--- @prop @optional Draggable boolean Determines if the window can be dragged via the TopBar
	Draggable = t.optional(t.boolean),

	--- @prop @optional AutomaticSize Enum.AutomaticSize Auto sizing
	AutomaticSize = t.optional(t.EnumItem),

	--- @prop @optional FooterHeight number The Footer's height, in pixels
	FooterHeight = t.optional(t.number),

	--- @prop @optional FooterContents table The contents to display in the footer
	FooterContents = t.optional(t.table),

	--- @prop @optional Position UDim2 The Window's position
	Position = t.optional(t.UDim2),

	--- @prop @optional Size UDim2 The Window's size
	Size = t.optional(t.UDim2),

	--- @prop @optional TitleBarProps table The props to be provided to the Title Bar
	TitleBarProps = t.optional(t.table),

	--- @prop @optional [Roact.Children] table The contents to display in the window area
	[Roact.Children] = t.optional(t.table),

	--- @prop @optional Native table Native props
	Native = t.optional(t.table),
})

function Window:init()
	
	-- Size binding, for FitContents
	self.Size, self.SetSize = Roact.createBinding(self.props.Size)

	-- TitleBar ref, for dragging and for height sizing
	self.TitleBarRef = Roact.createRef()

	-- Window ref, for dragging
	self.WindowRef = Roact.createRef()
	
	-- Connection, for dragging
	if self.props.Draggable then
		
		self.DragConnection = UserInputService.InputChanged:Connect(function(Input)

			-- Get the window
			local Window = self.WindowRef:getValue()

			-- Validate that this is drag input
			if Window and Input == self.DragInput and self.Dragging then

				local Delta = Input.Position - self.DragStart

				-- Set the position
				Window.Position = UDim2.new(self.StartPos.X.Scale, self.StartPos.X.Offset + Delta.X, self.StartPos.Y.Scale, self.StartPos.Y.Offset + Delta.Y)
			end
		end)
	end
end

function Window:willUnmount()
	
	if self.DragConnection then
		self.DragConnection:Disconnect()
	end
end

function Window:didMount()
	
	local TitleBar = self.TitleBarRef:getValue()
	local Window = self.WindowRef:getValue()

	-- Sizing
	if TitleBar then
		TitleBar:GetPropertyChangedSignal('AbsoluteSize'):Connect(function()
			local AbsoluteSize = TitleBar.AbsoluteSize
			self.TitleBarHeight = AbsoluteSize.Y
		end)
	end
	
	if TitleBar and Window and self.props.Draggable then
		TitleBar.InputBegan:Connect(function(Input)
			if Input.UserInputType == Enum.UserInputType.MouseButton1 or Input.UserInputType == Enum.UserInputType.Touch then
				self.Dragging = true
				self.DragStart = Input.Position
				self.StartPos = Window.Position
				
				local Connection = nil
				Connection = Input.Changed:Connect(function()
					if Input.UserInputState == Enum.UserInputState.End then
						self.Dragging = nil
						Connection:Disconnect()
					end
				end)
			end
		end)
		
		TitleBar.InputChanged:Connect(function(Input)
			if Input.UserInputType == Enum.UserInputType.MouseMovement or Input.UserInputType == Enum.UserInputType.Touch then
				self.DragInput = Input
			end
		end)
	end
end

function Window:render()
	local props = self.props

	return WithTheme(function(Theme)
	
		-- ////////// Title Bar

		local TitleBar = new(TitleBar, Sift.Dictionary.join({
			LayoutOrder = 1,
			Height = 32,--28,
			CaptionButtonWidth = 45,
			Native = {
				[Roact.Ref] = self.TitleBarRef,
			}
		}, props.TitleBarProps))

		-- ////////// Content Wrapper

		local ContentWrapperFillStyle = Theme[props.ContentBackgroundColor]

		local ContentWrapper = new(RoundedSurface, {
			AutomaticSize = props.AutomaticSize,
			BackgroundColor3 = ContentWrapperFillStyle.Color,
			BackgroundTransparency = ContentWrapperFillStyle.Transparency,
			BorderSizePixel = 0,
			CornerRadius = UDim.new(0, Theme['styles/CornerRadius/Default/Outer']),
			ShowBottomLeftCorner = props.FooterHeight < Theme['styles/CornerRadius/Default/Outer'] / 2,
			ShowBottomRightCorner = props.FooterHeight < Theme['styles/CornerRadius/Default/Outer'] / 2,
			LayoutOrder = 2,
			Size = props.Size,

			[Roact.Change.AbsoluteSize] = function (rbx)
				local AbsoluteSize = rbx.AbsoluteSize
				self.SetSize(UDim2.fromOffset(AbsoluteSize.X, AbsoluteSize.Y))
			end
		}, self.props[Roact.Children])

		-- ////////// Footer

		local Footer = new('Frame', {
			BackgroundTransparency = 1,
			LayoutOrder = 3,
			Size = UDim2.new(1, 0, 0, props.FooterHeight),
		}, props.FooterContents)

		-- ////////// Window

		local WindowFillStyle = Theme[props.BackgroundColor]
		local StrokeStyle = Theme['colors/Stroke_Color/Surface_Stroke/Default']

		local Window = new('Frame', Sift.Dictionary.join({
			AnchorPoint = props.DropShadowEnabled and Vector2.new(0.5, 0.5) or props.AnchorPoint,
			Position = props.DropShadowEnabled and UDim2.fromScale(0.5, 0.5) or props.Position,
			BackgroundColor3 = WindowFillStyle.Color,
			BackgroundTransparency = WindowFillStyle.Transparency,

			[Roact.Ref] = (not props.Draggable) and self.WindowRef or nil,

			Size = self.Size:map(function(Size)
				return Size + UDim2.fromOffset(0, (self.TitleBarHeight or 0) + props.FooterHeight)
			end),
		}, props.Native), {
			TitleBar = TitleBar,
			ContentWrapper = ContentWrapper,
			Footer = Footer,
			
			Stroke = new('UIStroke', {
				Color = StrokeStyle.Color,
				Transparency = StrokeStyle.Transparency,
			}),
			Corners = new('UICorner', {
				CornerRadius = UDim.new(0, Theme['styles/CornerRadius/Default/Outer']),
			}),
			Layout = new('UIListLayout', {
				SortOrder = Enum.SortOrder.LayoutOrder,
			})
		})

		if props.DropShadowEnabled then
			
			-- ////////// Drop Shadow

			return new(DropShadow, {
				AnchorPoint = props.AnchorPoint,
				Position = props.Position,
				CornerRadius = UDim.new(0, Theme['styles/CornerRadius/Default/Outer']),

				Size = self.Size:map(function(Size)
					return Size + UDim2.fromOffset(0, (self.TitleBarHeight or 0) + props.FooterHeight) + UDim2.new(0, 50, 0, 50)
				end),

				Native = {
					[Roact.Ref] = self.WindowRef,
				},
			}, Window)
		else
			return Window
		end
	end)
end

return Window
