local D=script:FindFirstAncestor("\084\101\120\116\069\100\105\116\111\114")local o=game:GetService("\067\104\097\110\103\101\072\105\115\116\111\114\121\083\101\114\118\105\099\101")local m=require(D.Packages.Roact)local c=require(D.Packages.RoactRodux)local f=require(D.Packages.Llama)local R=require(D.Plugin.Utilities)local K=m.Component:extend("\084\111\111\108\098\097\114")local C=require(script.Parent.StudioThemeContext)local B=require(script.Parent.ToolbarButton)local t=require(script.Parent.TextBox)local n=require(script.Parent.TypeDropdown)local k=require(D.Plugin.assets)local S={}do for D,o in pairs(Enum.Font:GetEnumItems())do table.insert(S,o.Name)end end local function P(D)return m.createElement("\070\114\097\109\101",{LayoutOrder=D.LayoutOrder;BackgroundTransparency=1;Size=UDim2.new(0,D.Width or 3,1,0)})end function K.toggleTagWrapper(o,D)return function()local m=o.props.inputRef:getValue()local c,f=o.props.cursorPosition:getValue(),o.props.selectionStartPosition:getValue()if c~=-1 and f~=-1 then local o,K,C=R.addTagsAroundSelection(m,c,f,D)m.Text=o m:CaptureFocus()m.SelectionStart=K m.CursorPosition=C else local o,f=m.Text:sub(0,c-1),m.Text:sub(c)o..="\060"..(D.."\062")local R=o:len()+1 o..="\060\047"..(D.."\062")m.Text=o..f m:CaptureFocus()m.CursorPosition=R end end end function K.didUpdate(c,D,m)if c.props.TextXAlignment~=D.TextXAlignment then c.props.TextItem.TextXAlignment=c.props.TextXAlignment o:SetWaypoint("\067\104\097\110\103\101 \084\101\120\116\088\065\108\105\103\110\109\101\110\116")end if c.props.Font~=D.Font then c.props.TextItem.Font=c.props.Font o:SetWaypoint("\067\104\097\110\103\101 \070\111\110\116")end if c.props.TextSize~=D.TextSize then c.props.TextItem.TextSize=c.props.TextSize o:SetWaypoint("\067\104\097\110\103\101 \084\101\120\116\083\105\122\101")end end function K.render(D)return m.createElement(C.Consumer,{render=function(o)return m.createElement("\070\114\097\109\101",{LayoutOrder=1,BorderSizePixel=0;Size=UDim2.new(1,0,0,20);BackgroundColor3=o:GetColor("\084\105\116\108\101\098\097\114")},{Layout=m.createElement("\085\073\076\105\115\116\076\097\121\111\117\116",{SortOrder=Enum.SortOrder.LayoutOrder;FillDirection=Enum.FillDirection.Horizontal}),Font=m.createElement(n,{LayoutOrder=1;Size=UDim2.new(0,0,0,20);currentOption=D.props.Font.Name;options=S;OnOptionSelect=function(o)D.props.setFont(Enum.Font[o])end}),Spacer1=m.createElement(P,{LayoutOrder=2}),TextSize=m.createElement(t,{LayoutOrder=3,BackgroundTransparency=0,TextSize=14,Size=UDim2.new(0,22,1,0);Text=D.props.TextSize,TextXAlignment=Enum.TextXAlignment.Center;ClipsDescendants=true;[m.Event.FocusLost]=function(o)local m=tonumber(o.Text)if m and(m>0 and m<=100)then D.props.setTextSize(m)else o.Text=D.props.TextSize end end});Spacer2=m.createElement(P,{LayoutOrder=4});BoldButton=m.createElement(B,{LayoutOrder=5,Text="\060\098\062\066\060\047\098\062";Tooltip="\060\098\062\066\111\108\100\060\047\098\062\n\077\097\107\101 \121\111\117\114 \116\101\120\116 \098\111\108\100";OnClick=D:toggleTagWrapper("\098")}),ItalicButton=m.createElement(B,{LayoutOrder=6,Text="\060\105\062\073\060\047\105\062";Tooltip="\060\098\062\073\116\097\108\105\099\115\060\047\098\062\n\073\116\097\108\105\099\105\122\101 \121\111\117\114 \116\101\120\116",OnClick=D:toggleTagWrapper("\105")});UnderlineButton=m.createElement(B,{LayoutOrder=7;Text="\060\117\062\085\060\047\117\062",Tooltip="\060\098\062\085\110\100\101\114\108\105\110\101\060\047\098\062\n\085\110\100\101\114\108\105\110\101 \121\111\117\114 \116\101\120\116",OnClick=D:toggleTagWrapper("\117")}),StrikethroughButton=m.createElement(B,{LayoutOrder=8;Text="\060\115\062\083\060\047\115\062";Tooltip="\060\098\062\083\116\114\105\107\101\116\104\114\111\117\103\104\060\047\098\062\n\067\114\111\115\115 \115\111\109\101\116\104\105\110\103 \111\117\116";OnClick=D:toggleTagWrapper("\115")}),XAlignmentLeft=m.createElement(B,{type="\073\109\097\103\101\066\117\116\116\111\110";LayoutOrder=9;Image=k["\112\097\114\097\103\114\097\112\104-\108\101\102\116"],Tooltip="\060\098\062\065\108\105\103\110 \076\101\102\116\060\047\098\062\n\065\108\105\103\110 \121\111\117\114 \099\111\110\116\101\110\116 \119\105\116\104 \116\104\101 \108\101\102\116 \109\097\114\103\105\110";OnClick=function()D.props.setXAlignment(Enum.TextXAlignment.Left)end;IsSelected=D.props.TextXAlignment==Enum.TextXAlignment.Left});XAlignmentCenter=m.createElement(B,{type="\073\109\097\103\101\066\117\116\116\111\110",LayoutOrder=10;Image=k["\112\097\114\097\103\114\097\112\104-\099\101\110\116\101\114"],Tooltip="\060\098\062\065\108\105\103\110 \067\101\110\116\101\114\060\047\098\062\n\067\101\110\116\101\114 \121\111\117\114 \099\111\110\116\101\110\116";OnClick=function()D.props.setXAlignment(Enum.TextXAlignment.Center)end;IsSelected=D.props.TextXAlignment==Enum.TextXAlignment.Center}),XAlignmentRight=m.createElement(B,{type="\073\109\097\103\101\066\117\116\116\111\110";LayoutOrder=11,Image=k["\112\097\114\097\103\114\097\112\104-\114\105\103\104\116"];Tooltip="\060\098\062\065\108\105\103\110 \082\105\103\104\116\060\047\098\062\n\065\108\105\103\110 \121\111\117\114 \099\111\110\116\101\110\116 \119\105\116\104 \116\104\101 \114\105\103\104\116 \109\097\114\103\105\110";OnClick=function()D.props.setXAlignment(Enum.TextXAlignment.Right)end,IsSelected=D.props.TextXAlignment==Enum.TextXAlignment.Right})})end})end return(c.connect(function(D,o)local m=f.Dictionary.copy(o)m.TextItem=D.TextItem m.TextXAlignment=D.TextXAlignment m.Font=D.Font m.TextSize=D.TextSize return m end,function(D)return{setXAlignment=function(o)D({type="\115\101\116\088\065\108\105\103\110\109\101\110\116",alignment=o})end,setFont=function(o)D({type="\115\101\116\070\111\110\116",font=o})end,setTextSize=function(o)D({type="\115\101\116\084\101\120\116\083\105\122\101",textSize=o})end}end))(K)
local TextEditor = script:FindFirstAncestor("TextEditor")
local ChangeHistoryService = game:GetService("ChangeHistoryService")
local Roact = require(TextEditor.Packages.Roact)
local RoactRodux = require(TextEditor.Packages.RoactRodux)
local Llama = require(TextEditor.Packages.Llama)
local Utilities = require(TextEditor.Plugin.Utilities)

local Toolbar = Roact.Component:extend("Toolbar")
local StudioThemeContext = require(script.Parent.StudioThemeContext)
local ToolbarButton = require(script.Parent.ToolbarButton)
local ThemedTextBox = require(script.Parent.TextBox)
local TypeDropdown = require(script.Parent.TypeDropdown)
local assets = require(TextEditor.Plugin.assets)

local FONT_NAMES = {}
do
  for _, font in pairs(Enum.Font:GetEnumItems()) do
    table.insert(FONT_NAMES, font.Name)
  end
end

local function ToolbarSpacer(props)
  return Roact.createElement("Frame", {
    LayoutOrder = props.LayoutOrder,
    BackgroundTransparency = 1,
    Size = UDim2.new(0, props.Width or 3, 1, 0),
  })
end

function Toolbar:toggleTagWrapper(tag)
  return function()
    local textBox = self.props.inputRef:getValue()
    local cursorPosition, selectionStart = self.props.cursorPosition:getValue(), self.props.selectionStartPosition:getValue()
    if cursorPosition ~= -1 and selectionStart ~= -1 then
      local text, startPosition, endPosition = Utilities.addTagsAroundSelection(textBox, cursorPosition, selectionStart, tag)
      textBox.Text = text
      textBox:CaptureFocus()
      textBox.SelectionStart = startPosition
      textBox.CursorPosition = endPosition
    else
      -- Add tags at cursor position and then set the cursor in between them
      local startText, endText = textBox.Text:sub(0, cursorPosition - 1), textBox.Text:sub(cursorPosition)
      startText ..= "<" .. tag .. ">"
      local newCursorPosition = startText:len() + 1
      startText ..= "</" .. tag .. ">"
      textBox.Text = startText .. endText
      textBox:CaptureFocus()
      textBox.CursorPosition = newCursorPosition 
    end
  end
end

function Toolbar:didUpdate(prevProps, _prevState)
  if self.props.TextXAlignment ~= prevProps.TextXAlignment then
    -- Update the TextItem TextXAlignment when a button is pressed
    self.props.TextItem.TextXAlignment = self.props.TextXAlignment
    ChangeHistoryService:SetWaypoint("Change TextXAlignment")
  end

  if self.props.Font ~= prevProps.Font then
    self.props.TextItem.Font = self.props.Font
    ChangeHistoryService:SetWaypoint("Change Font")
  end

  if self.props.TextSize ~= prevProps.TextSize then
    self.props.TextItem.TextSize = self.props.TextSize
    ChangeHistoryService:SetWaypoint("Change TextSize")
  end
end

function Toolbar:render()
  return Roact.createElement(StudioThemeContext.Consumer, {
    render = function(theme)
      return Roact.createElement("Frame", {
        LayoutOrder = 1,
        BorderSizePixel = 0,
        Size = UDim2.new(1, 0, 0, 20),
        BackgroundColor3 = theme:GetColor("Titlebar"),
      }, {
        Layout = Roact.createElement("UIListLayout", {
          SortOrder = Enum.SortOrder.LayoutOrder,
          FillDirection = Enum.FillDirection.Horizontal,
        }),
        
        Font = Roact.createElement(TypeDropdown, {
          LayoutOrder = 1,
          Size = UDim2.new(0, 0, 0, 20),
          currentOption = self.props.Font.Name,
          options = FONT_NAMES,
          OnOptionSelect = function(option)
            self.props.setFont(Enum.Font[option])
          end,
        }),

        Spacer1 = Roact.createElement(ToolbarSpacer, {
          LayoutOrder = 2,
        }),

        TextSize = Roact.createElement(ThemedTextBox, {
          LayoutOrder = 3,
          BackgroundTransparency = 0,
          TextSize = 14,
          Size = UDim2.new(0, 22, 1, 0),
          Text = self.props.TextSize,
          TextXAlignment = Enum.TextXAlignment.Center,
          ClipsDescendants = true,
          [Roact.Event.FocusLost] = function(rbx)
            local newTextSize = tonumber(rbx.Text)
            if newTextSize and newTextSize > 0 and newTextSize <= 100 then
              self.props.setTextSize(newTextSize)
            else
              rbx.Text = self.props.TextSize
            end
          end,
        }),

        Spacer2 = Roact.createElement(ToolbarSpacer, {
          LayoutOrder = 4,
        }),

        BoldButton = Roact.createElement(ToolbarButton, {
          LayoutOrder = 5,
          Text = "<b>B</b>",
          Tooltip = "<b>Bold</b>\nMake your text bold",
          OnClick = self:toggleTagWrapper("b")
        }),

        ItalicButton = Roact.createElement(ToolbarButton, {
          LayoutOrder = 6,
          Text = "<i>I</i>",
          Tooltip = "<b>Italics</b>\nItalicize your text",
          OnClick = self:toggleTagWrapper("i")
        }),
  
        UnderlineButton = Roact.createElement(ToolbarButton, {
          LayoutOrder = 7,
          Text = "<u>U</u>",
          Tooltip = "<b>Underline</b>\nUnderline your text",
          OnClick = self:toggleTagWrapper("u")
        }),
  
        StrikethroughButton = Roact.createElement(ToolbarButton, {
          LayoutOrder = 8,
          Text = "<s>S</s>",
          Tooltip = "<b>Strikethrough</b>\nCross something out",
          OnClick = self:toggleTagWrapper("s")
        }),

        XAlignmentLeft = Roact.createElement(ToolbarButton, {
          type = "ImageButton",
          LayoutOrder = 9,
          Image = assets["paragraph-left"],
          Tooltip = "<b>Align Left</b>\nAlign your content with the left margin",
          OnClick = function()
            self.props.setXAlignment(Enum.TextXAlignment.Left)
          end,
          IsSelected = self.props.TextXAlignment == Enum.TextXAlignment.Left,
        }),

        XAlignmentCenter = Roact.createElement(ToolbarButton, {
          type = "ImageButton",
          LayoutOrder = 10,
          Image = assets["paragraph-center"],
          Tooltip = "<b>Align Center</b>\nCenter your content",
          OnClick = function()
            self.props.setXAlignment(Enum.TextXAlignment.Center)
          end,
          IsSelected = self.props.TextXAlignment == Enum.TextXAlignment.Center,
        }),

        XAlignmentRight = Roact.createElement(ToolbarButton, {
          type = "ImageButton",
          LayoutOrder = 11,
          Image = assets["paragraph-right"],
          Tooltip = "<b>Align Right</b>\nAlign your content with the right margin",
          OnClick = function()
            self.props.setXAlignment(Enum.TextXAlignment.Right)
          end,
          IsSelected = self.props.TextXAlignment == Enum.TextXAlignment.Right,
        }),
      })
    end
  })
end

return RoactRodux.connect(
  function(state, props)
    local newProps = Llama.Dictionary.copy(props)
    newProps.TextItem = state.TextItem
    newProps.TextXAlignment = state.TextXAlignment
    newProps.Font = state.Font
    newProps.TextSize = state.TextSize
    return newProps
  end,
  function(dispatch)
    return {
      setXAlignment = function(alignment)
        dispatch({ type = "setXAlignment", alignment = alignment })
      end,
      setFont = function(font)
        dispatch({ type = "setFont", font = font })
      end,
      setTextSize = function(textSize)
        dispatch({ type = "setTextSize", textSize = textSize })
      end,
    }
  end
)(Toolbar)