---  Configuration UI Tools
--
local mtConfigTools = {}
local AddOnName, nsVars = ...
local ss = nsVars.SS

local CreateFrame, UIParent, getglobal, InterfaceOptions_AddCategory = ss.CreateFrame, UIParent, getglobal, InterfaceOptions_AddCategory
local select, strlower, setmetatable, tonumber = select, strlower, setmetatable, tonumber
local CustomDropDownMenu_SetInitializeFunction = CustomDropDownMenu_SetInitializeFunction
local CustomDropDownMenu_JustifyText, CustomDropDownMenu_SetText = CustomDropDownMenu_JustifyText, CustomDropDownMenu_SetText
local GetCursorPosition, CustomDropDownMenu_SetWidth = GetCursorPosition, CustomDropDownMenu_SetWidth

local itemCol = 1
local itemRow = 1

--- Local metatables.
-----------------------
local mtButton = {
  parent = UIParent,
  width = 135,
  height = 25,
  anch = "TOPLEFT",
  x = 0,
  y = 0,
  text = "",
  onClick = function()
  end,
}

local mtCheck = {
  parent = UIParent,
  text = "Show Value",
  checked = false,
  onClick = function()
  end,
}

local mtColorSelect = {
  parent = UIParent,
  width = 185,
  height = 175,
  wheelWidth = 120,
  barWidth = 20,
  thumbWidth = 14,
  anch = "TOPLEFT",
  x = 0,
  y = 0,
}

local mtEdit = {
  parent = UIParent,
  width = 150,
  height = 25,
  anch = "TOPLEFT",
  x = 0,
  y = 0,
  letters = 0,
  text = "",
  autofocus = false,
}

local mtLabel = {
  parent = UIParent,
  width = 150,
  height = 50,
  anch = "TOPLEFT",
  x = 0,
  y = 0,
  text = "",
  justifyV = "CENTER",
  justifyH = "CENTER",
  fontObject = ss.FontObjects.Exo2Medium14,
  color = { r = 1, g = 1, b = 1, a = 1, },
}

--- Returns the next element position for the main config panel.
--
local function getItemPos()
  if itemCol == 1 then
    itemCol = itemCol + 1

    if itemRow == 1 then
      return "TOPLEFT", 25, -131
    elseif itemRow == 2 then
      return "TOPLEFT", 25, -179
    elseif itemRow == 3 then
      return "TOPLEFT", 25, -227
    elseif itemRow == 4 then
      return "TOPLEFT", 25, -275
    elseif itemRow == 5 then
      return "TOPLEFT", 25, -323
    elseif itemRow == 6 then
      return "TOPLEFT", 25, -371
    end
  elseif itemCol == 2 then
    local row = itemRow
    itemCol = itemCol - 1
    itemRow = itemRow + 1

    if row == 1 then
      return "TOP", 0, -131
    elseif row == 2 then
      return "TOP", 0, -179
    elseif row == 3 then
      return "TOP", 0, -227
    elseif row == 4 then
      return "TOP", 0, -275
    elseif row == 5 then
      return "TOP", 0, -323
    elseif row == 6 then
      return "TOP", 0, -371
    end
  end

  return "CENTER", 0, 0
end

--- Creates a CheckButton frame.
--- @param check table The values to use.
--- @return table The CheckButton.
local function createCheckbox(check)
  check = setmetatable(check, { __index = mtCheck });
  local col = ss.ConfigTools.itemColor

  local checkbox = CreateFrame("CheckButton", ss._f .. check.name, check.parent, "BrownCheckButtonTemplate")

  if check.anch and check.x and check.y then
    checkbox:SetPoint(check.anch, check.x, check.y)
  else
    checkbox:SetPoint(getItemPos())
  end

  checkbox:SetChecked(check.checked)
  checkbox.SetLabel = function(self, t)
    getglobal(self:GetName() .. "Text"):SetText(t)
  end

  getglobal(ss._f .. check.name .. "Text"):SetFontObject(ss.FontObjects.Exo2Medium14)
  getglobal(ss._f .. check.name .. "Text"):SetTextColor(col.r, col.g, col.b, col.a)
  getglobal(ss._f .. check.name .. "Text"):SetText(check.text)
  getglobal(ss._f .. check.name .. "Text"):SetWordWrap(check.wordWrap or true)
  getglobal(ss._f .. check.name .. "Text"):SetJustifyH(check.justifyH or "LEFT")
  getglobal(ss._f .. check.name .. "Text"):SetWidth(check.width or 250)

  checkbox:HookScript("OnClick", check.onClick)

  return checkbox
end

--- Creates a dropdown menu frame.
-- @param menu The values to use.
-- @return The dropdown menu.
--
local function getDropdown(menu)
  local dropdown = CreateFrame("Frame", ss._f .. menu.name, menu.parent, "FlatDropDownMenuTemplate")

  local anch, x, y

  if not menu.anchor then
    anch, x, y = getItemPos()
    x = x + 24
  else
    anch, x, y = menu.anchor, menu.x or 0, menu.y or 0
  end

  dropdown:SetPoint(anch, x, y)

  CustomDropDownMenu_SetInitializeFunction(dropdown, menu.init)
  CustomDropDownMenu_SetWidth(dropdown, menu.width or 55)
  CustomDropDownMenu_JustifyText(dropdown, menu.tAlign or "LEFT")
  CustomDropDownMenu_SetText(dropdown, menu.defaultText or "")

  if menu.label then
    dropdown.label = ss.ConfigTools.addItemLabel(menu.label.name, dropdown, menu.label.text, menu.label.location, menu.label.color, menu.label.leftLabelMargin, menu.label.xOff, menu.label.yOff)
  elseif menu.text then
    local col = ss.ConfigTools.itemColor
    dropdown.label = dropdown:GetParent():CreateFontString(ss._f .. menu.name .. "Label")
    dropdown.label:SetFontObject(ss.FontObjects.Exo2Medium14)
    dropdown.label:SetPoint(anch, x + 110, y + 3)
    dropdown.label:SetHeight(dropdown:GetHeight())
    dropdown.label:SetTextColor(col.r, col.g, col.b, col.a)
    dropdown.label:SetText(menu.text)
    dropdown.label:SetJustifyV("CENTER")
    dropdown.label:SetJustifyH("LEFT")
  end

  dropdown._Show = dropdown.Show
  dropdown._Hide = dropdown.Hide

  dropdown.Show = function(self)
    if self.label then
      self.label:Show()
    end

    self:_Show()
  end

  dropdown.Hide = function(self)
    if self.label then
      self.label:Hide()
    end

    self:_Hide()
  end

  return dropdown
end

mtConfigTools.itemHeight = 30
mtConfigTools.itemPadLeft = 50
mtConfigTools.itemPadCorner = 10
mtConfigTools.itemPadTitle = 15
mtConfigTools.topMargin = -60
mtConfigTools.leftLabelMargin = 165
mtConfigTools.bannerColor = ss.ClassResourceData.classColor(ss.curClass)
mtConfigTools.titleColor = { r = 0.5, g = 1, b = 0.3, a = 1 }
mtConfigTools.headerItemColor = { r = 1.0, g = 0.7, b = 0.5, a = 1 }
mtConfigTools.itemColor = { r = 0, g = 0.5, b = 1, a = 1 }

function mtConfigTools.createButton(btn)
  btn = setmetatable(btn, { __index = mtButton });

  local button = CreateFrame("FlatButton", ss._f .. btn.name, btn.parent)
  --    local button = createButton(btn.parent, ss._f..btn.name)
  button:SetSize(btn.width, btn.height)
  button:SetPoint(btn.anch, btn.x, btn.y)
  button:SetText(btn.text)
  button:HookScript("OnClick", btn.onClick)

  return button
end

function mtConfigTools.createInterfaceOption(opt)
  local option = CreateFrame("Frame", AddOnName .. (opt.name or "") .. "InterfaceOption")
  option.name = opt.name and opt.name or AddOnName
  option.parent = opt.parent
  option.refresh = opt.refresh
  InterfaceOptions_AddCategory(option)

  return option
end

function mtConfigTools.createSliderField(sliderConf, sliderEditBoxConf)
  local slider = CreateFrame("Slider", ss._f .. sliderConf.name, sliderConf.parent, "OptionsSliderTemplate")
  slider:SetPoint(sliderConf.anchor, sliderConf.x, sliderConf.y)
  slider:SetSize(sliderConf.len, sliderConf.heigt)
  slider:HookScript("OnHide", function(self)
    self._prevVal = nil
  end)

  slider:HookScript("OnValueChanged", function(self, ...)
    if self._prevVal ~= self:GetValue() then
      self._prevVal = self:GetValue()
      sliderConf.onChanged(self, ...)
    end
  end)

  if sliderConf.values then
    getglobal(slider:GetName() .. "Text"):SetText(sliderConf.values.label)
    getglobal(slider:GetName() .. "High"):SetText(sliderConf.values.high)
    getglobal(slider:GetName() .. "Low"):SetText(sliderConf.values.low)

    slider:SetMinMaxValues(sliderConf.values.low, sliderConf.values.high)
    slider:SetValueStep(sliderConf.values.step)
    slider:SetValue(sliderConf.values.value)
  end

  -- Add the glow scale slider edit box
  local sliderEditBox = ss.ConfigTools.createEditBox {
    parent = slider,
    name = sliderConf.name .. "EditBox",
    width = 50,
    height = 20,
    anch = "BOTTOMRIGHT",
    x = 0,
    y = 30,
    letters = sliderEditBoxConf.maxLetters,
    text = slider:GetValue(),
    onEnterPressed = sliderEditBoxConf.onEnterPressed,
  }

  return slider, sliderEditBox
end

function mtConfigTools.createEditBox(edit)
  edit = setmetatable(edit, { __index = mtEdit });

  local editBox = CreateFrame("EditBox", ss._f .. edit.name, edit.parent, "FlatEditBoxTemplate")
  editBox:SetSize(edit.width, edit.height)
  editBox:SetPoint(edit.anch, edit.x, edit.y)
  editBox:SetMaxLetters(edit.letters)
  editBox:SetText(edit.text or "")
  editBox:SetAutoFocus(edit.autofocus or false)

  if (edit.onEnterPressed) then
    editBox:HookScript("OnEnterPressed", edit.onEnterPressed)
  else
    editBox:HookScript("OnEnterPressed", function(self)
      self:ClearFocus()
    end)
  end

  if (edit.onTabPressed) then
    editBox:HookScript("OnTabPressed", edit.onTabPressed)
  end

  if (edit.OnEditFocusLost) then
    editBox:HookScript("OnEditFocusLost", edit.OnEditFocusLost)
  end

  if (edit.onTextChanged) then
    editBox:HookScript("OnTextChanged", edit.onTextChanged)
  end

  if edit.label then
    editBox.label = ss.ConfigTools.addItemLabel(
        edit.label.name,
        editBox,
        edit.label.text,
        edit.label.location,
        edit.label.color,
        edit.label.leftLabelMargin,
        edit.label.xOff,
        edit.label.yOff
    )
  end

  return editBox
end

function mtConfigTools.createColorPicker(colorSelect)
  colorSelect = setmetatable(colorSelect, { __index = mtColorSelect });

  -- Create the ColorSelect frame.
  local colorFields = CreateFrame("ColorSelect", colorSelect.name or ss._f .. "ColorFieldContainer", colorSelect.parent)
  colorFields:SetPoint(colorSelect.anch, colorSelect.x, colorSelect.y)
  colorFields:SetSize(colorSelect.width, colorSelect.height)

  -- Create colorpicker wheel.
  colorFields.cWheelTexture = colorFields:CreateTexture()
  colorFields.cWheelTexture:SetWidth(colorSelect.wheelWidth)
  colorFields.cWheelTexture:SetHeight(colorSelect.wheelWidth)
  colorFields.cWheelTexture:SetPoint("TOPLEFT", 0, 0)
  colorFields:SetColorWheelTexture(colorFields.cWheelTexture)

  colorFields.cWheelThumbTexture = colorFields:CreateTexture()
  colorFields.cWheelThumbTexture:SetTexture("Interface\\Buttons\\UI-ColorPicker-Buttons")
  colorFields.cWheelThumbTexture:SetWidth(colorSelect.thumbWidth)
  colorFields.cWheelThumbTexture:SetHeight(colorSelect.thumbWidth)
  colorFields.cWheelThumbTexture:SetTexCoord(0, 0.15625, 0, 0.625)
  colorFields:SetColorWheelThumbTexture(colorFields.cWheelThumbTexture)

  -- Create the colorpicker slider.
  colorFields.valueTexture = colorFields:CreateTexture()
  colorFields.valueTexture:SetWidth(colorSelect.barWidth)
  colorFields.valueTexture:SetHeight(colorSelect.wheelWidth)
  colorFields.valueTexture:SetPoint("TOPRIGHT", (colorSelect.barWidth * -1) - 10, 0)
  colorFields:SetColorValueTexture(colorFields.valueTexture)

  colorFields.valueThumbTexture = colorFields:CreateTexture()
  colorFields.valueThumbTexture:SetTexture("Interface\\Buttons\\UI-ColorPicker-Buttons")
  colorFields.valueThumbTexture:SetWidth(colorSelect.barWidth)
  colorFields.valueThumbTexture:SetHeight(colorSelect.thumbWidth)
  colorFields.valueThumbTexture:SetTexCoord(0.25, 1, 0.875, 0)
  colorFields:SetColorValueThumbTexture(colorFields.valueThumbTexture)

  -- Create the alpha widget.
  colorFields.alphaTextureContainer = CreateFrame("Frame", ss._f .. "ColorFieldAlphaContainer", colorFields)
  colorFields.alphaTextureContainer:SetHeight(colorSelect.wheelWidth)
  colorFields.alphaTextureContainer:SetWidth(colorSelect.barWidth)
  colorFields.alphaTextureContainer:SetPoint("TOPRIGHT", 0, 0)
  colorFields.alphaTextureContainer:RegisterForDrag("LeftButton")
  colorFields.alphaTextureContainer:EnableMouse(true)

  -- TODO: Set a background that is visible for transparent colors.
  -- Set the default hook for the text fields.
  ss.Extensions:Hook(colorFields, "OnColorSelect", function(self)
    -- Ensure custom fields are updated.
    local r, g, b, a = self:GetColorRGBA()
    self.colorFieldA:SetText(100 * a)
    self.colorFieldR:SetText(r * 255)
    self.colorFieldG:SetText(g * 255)
    self.colorFieldB:SetText(b * 255)
    self.alphaTexture:SetGradientAlpha("VERTICAL", 0, 0, 0, 1, r, g, b, 1)
  end, "__")

  ss.Extensions:Hook(colorFields, "OnColorSelect", colorSelect.onColorSelect)

  function colorFields:SetColorRGBA(r, g, b, a)
    self:SetColorAlpha(a)
    self:SetColorRGB(r, g, b)
  end

  function colorFields:GetColorRGBA()
    local r, g, b = self:GetColorRGB()
    return r, g, b, self:GetColorAlpha()
  end

  function colorFields:SetColorAlpha(a)
    a = a < 0 and 0 or a
    a = a > 1 and 1 or a

    -- Update Alpha slider and trigger OnColorSelect.
    self.alphaThumbTexture:SetPoint("TOP", 0, 7 - (120 - 120 * a))
    self.colorFieldA:SetText(100 * a)
    self:SetColorRGB(self:GetColorRGB())
  end

  function colorFields:GetColorAlpha()
    local a = tonumber(self.colorFieldA:GetText()) or 100
    return a / 100
  end

  colorFields.alphaTextureContainer:HookScript("OnDragStart", function(self)
    colorFields.alphaThumbContainer.minY = self:GetBottom()
  end)

  colorFields.alphaTextureContainer:HookScript("OnDragStop", function(_)
    colorFields.alphaThumbContainer.minY = nil
  end)

  -- I broke this with new tabs
  colorFields.alphaThumbTexture = colorFields.alphaTextureContainer:CreateTexture()
  colorFields.alphaThumbTexture:SetTexture("Interface\\Buttons\\UI-ColorPicker-Buttons")
  colorFields.alphaThumbTexture:SetWidth(colorSelect.barWidth)
  colorFields.alphaThumbTexture:SetHeight(colorSelect.thumbWidth)
  colorFields.alphaThumbTexture:SetPoint("TOP", 0, colorSelect.thumbWidth / 2)
  colorFields.alphaThumbTexture:SetTexCoord(0.25, 1, 0.875, 0)

  colorFields.alphaTexture = colorFields.alphaTextureContainer:CreateTexture()
  colorFields.alphaTexture:SetAllPoints(colorFields.alphaTextureContainer)
  colorFields.alphaTexture:SetColorTexture(1, 1, 1, 1)
  colorFields.alphaTexture:SetGradientAlpha("VERTICAL", 0, 0, 0, 0, 1, 1, 1, 1)

  -- Add the alpha slider.
  colorFields.alphaThumbContainer = CreateFrame("Frame", ss._f .. "AlphaDragFrame", colorFields)

  colorFields.alphaThumbContainer:HookScript("OnUpdate", function(self)
    if self.minY then
      -- Calculate yPos relative to container bottom.
      local _, yPos = GetCursorPosition()
      yPos = yPos / UIParent:GetScale() - self.minY

      -- Ensure movement is within the container boundaries.
      yPos = (yPos < 0) and 0 or yPos
      yPos = (yPos > 120) and 120 or yPos
      yPos = yPos + colorSelect.thumbWidth / 2

      -- Drag the slider.
      -- TODO: Review positioning during drag with different scaling.
      colorFields.alphaThumbTexture:SetPoint("TOP", 0, yPos - colorSelect.wheelWidth)

      -- Update the alpha value.
      yPos = (yPos - colorSelect.thumbWidth / 2) / 120
      colorFields:SetColorAlpha(yPos)
    end
  end)

  -- Create the edit fields
  local height = 20
  local width = 30
  local xPos = -width - 10
  local yPos = height + 5

  -- Create the R color field
  colorFields.colorFieldR = ss.ConfigTools.createEditBox {
    parent = colorFields,
    name = "ColorFieldR",
    width = width,
    height = height,
    anch = "BOTTOMRIGHT",
    x = (xPos * 3),
    y = 0,
    letters = 3,
    onTextChanged = function(self)
      local val = self:GetText()
      if tonumber(val) then
        local _, g, b = colorFields:GetColorRGB()
        colorFields:SetColorRGB(val / 255, g, b)
      end

      if colorSelect.onTextChanged then
        colorSelect.onTextChanged(self)
      end
    end,
    onTabPressed = function(self)
      if colorFields.colorFieldG then
        colorFields.colorFieldG:SetFocus()
      else
        self:ClearFocus()
      end
    end,
  }

  -- Create the R color label
  colorFields.colorFieldR.label = ss.ConfigTools.createLabel {
    parent = colorFields,
    name = "ColorFieldRLabel",
    width = width,
    height = height,
    anch = "BOTTOMRIGHT",
    x = (xPos * 3) - 10,
    y = yPos,
    color = ss.ConfigTools.itemColor,
    text = "R",
  }

  -- Create the G color field
  colorFields.colorFieldG = ss.ConfigTools.createEditBox {
    parent = colorFields,
    name = "ColorFieldG",
    width = width,
    height = height,
    anch = "BOTTOMRIGHT",
    x = (xPos * 2),
    y = 0,
    letters = 3,
    onTextChanged = function(self)
      local val = self:GetText()
      if tonumber(val) then
        local r, _, b = colorFields:GetColorRGB()
        colorFields:SetColorRGB(r, val / 255, b)
      end

      if colorSelect.onTextChanged then
        colorSelect.onTextChanged(self)
      end
    end,
    onTabPressed = function(self)
      if colorFields.colorFieldB then
        colorFields.colorFieldB:SetFocus()
      else
        self:ClearFocus()
      end
    end,
  }

  -- Create the G color label
  colorFields.colorFieldG.label = ss.ConfigTools.createLabel {
    parent = colorFields,
    name = "ColorFieldGLabel",
    width = width,
    height = height,
    anch = "BOTTOMRIGHT",
    x = (xPos * 2) - 10,
    y = yPos,
    color = ss.ConfigTools.itemColor,
    text = "G",
  }

  -- Create the B color field
  colorFields.colorFieldB = ss.ConfigTools.createEditBox {
    parent = colorFields,
    name = "ColorFieldB",
    width = width,
    height = height,
    anch = "BOTTOMRIGHT",
    x = xPos,
    y = 0,
    letters = 3,
    onTextChanged = function(self)
      local val = self:GetText()
      if tonumber(val) then
        local r, g, _ = colorFields:GetColorRGB()
        colorFields:SetColorRGB(r, g, val / 255)
      end

      if colorSelect.onTextChanged then
        colorSelect.onTextChanged(self)
      end
    end,
    onTabPressed = function(self)
      if colorFields.colorFieldA then
        colorFields.colorFieldA:SetFocus()
      else
        self:ClearFocus()
      end
    end,
  }

  -- Create the B color label
  colorFields.colorFieldB.label = ss.ConfigTools.createLabel {
    parent = colorFields,
    name = "ColorFieldBLabel",
    width = width,
    height = height,
    anch = "BOTTOMRIGHT",
    x = xPos - 10,
    y = yPos,
    color = ss.ConfigTools.itemColor,
    text = "B",
  }

  -- Create the Alpha field
  colorFields.colorFieldA = ss.ConfigTools.createEditBox {
    parent = colorFields,
    name = "ColorFieldA",
    width = width,
    height = height,
    anch = "BOTTOMRIGHT",
    x = 0,
    y = 0,
    letters = 3,
    onTextChanged = function(self)
      local val = self:GetText()
      if tonumber(val) then
        colorFields:SetColorAlpha(val / 100)
      end

      if colorSelect.onTextChanged then
        colorSelect.onTextChanged(self)
      end
    end,
    onTabPressed = function(self)
      self:ClearFocus()
    end,
  }

  -- Create the Alpha label
  colorFields.colorFieldA.label = ss.ConfigTools.createLabel {
    parent = colorFields,
    name = "ColorFieldALabel",
    width = width,
    height = height,
    anch = "BOTTOMRIGHT",
    x = -10,
    y = yPos,
    color = ss.ConfigTools.itemColor,
    text = "A",
  }

  -- Add the class button
  colorFields.classButton = ss.ConfigTools.createButton {
    parent = colorFields,
    name = "ColorFieldClassButton",
    width = 45,
    height = height,
    anch = "BOTTOMLEFT",
    x = -20,
    y = 0,
    text = ss.T["btn_class"],
    onClick = function()
      colorFields:SetColorRGBA(ss.ConfigTools.bannerColor.r, ss.ConfigTools.bannerColor.g, ss.ConfigTools.bannerColor.b, ss.ConfigTools.bannerColor.a)
    end,
  }

  return colorFields
end

function mtConfigTools.createLabel(label)
  label = setmetatable(label, { __index = mtLabel });

  local fontString = label.parent:CreateFontString(label.name)
  fontString:SetFontObject(label.fontObject)
  fontString:SetPoint(label.anch, label.x, label.y)
  fontString:SetSize(label.width, label.height)
  fontString:SetTextColor(label.color.r, label.color.g, label.color.b, label.color.a)
  fontString:SetText(label.text)
  fontString:SetJustifyV(label.justifyV)
  fontString:SetJustifyH(label.justifyH)

  return fontString
end

function mtConfigTools.createTitle(text, parent)
  local title = parent:CreateFontString(nil, "BossEmoteNormalHuge")
  title:SetFontObject(ss.FontObjects.Exo2Medium18)
  title:SetPoint("TOPRIGHT", -ss.ConfigTools.itemPadTitle * 2, -ss.ConfigTools.itemPadTitle - 35)
  title:SetSize(400, 39)
  title:SetTextColor(ss.ConfigTools.titleColor.r, ss.ConfigTools.titleColor.g, ss.ConfigTools.titleColor.b, ss.ConfigTools.titleColor.a)
  title:SetText(text)
  title:SetJustifyV("TOP")
  title:SetJustifyH("RIGHT")

  return title
end

function mtConfigTools.addItemLabel(name, target, text, location, color, leftLabelMargin, xOff, yOff)
  leftLabelMargin = leftLabelMargin or ss.ConfigTools.leftLabelMargin
  location = location or "left"
  color = color or ss.ConfigTools.itemColor
  xOff = xOff or 0
  yOff = yOff or 0

  -- Determine relative location
  local anch, x, y = select(3, target:GetPoint())
  local topAdjustY = string.match(strlower(anch), "top") and 22 or 17

  x = (strlower(location) == "left") and (x - leftLabelMargin) or ((strlower(location) == "top") and (x + 20) or x)
  y = (strlower(location) == "left") and (y - 3) or ((strlower(location) == "top") and (y + topAdjustY) or y)

  local fontString = target:GetParent():CreateFontString(name)
  fontString:SetFontObject(ss.FontObjects.Exo2Medium14)
  fontString:SetPoint(anch, x + xOff, y + yOff)
  fontString:SetSize(leftLabelMargin, 39)
  fontString:SetTextColor(color.r, color.g, color.b, color.a)
  fontString:SetText(text)
  fontString:SetJustifyV("TOP")
  fontString:SetJustifyH("Left")

  return fontString
end

function mtConfigTools.addWidget(widget)
  if widget.type == "Checkbox" then
    widget.parent[widget.name] = createCheckbox(widget)
  elseif widget.type == "DropDown" then
    widget.parent[widget.name] = getDropdown(widget)
  end
end

function mtConfigTools.getWidgetContainer(parent, name)
  -- Add the widget container
  local widgetFrame = CreateFrame("Frame", ss._f .. name, parent)
  widgetFrame:SetAllPoints(parent)

  -- Add the banner.
  widgetFrame.banner = widgetFrame:CreateFontString(name .. "Banner", "ARTWORK", "NumberFontNormalHuge")
  widgetFrame.banner:SetFontObject(ss.FontObjects.Exo2SemiBold30)
  widgetFrame.banner:SetPoint("TOPRIGHT", -ss.ConfigTools.itemPadTitle, -ss.ConfigTools.itemPadTitle)
  widgetFrame.banner:SetSize(262, 35)
  widgetFrame.banner:SetTextColor(ss.ConfigTools.bannerColor.r, ss.ConfigTools.bannerColor.g, ss.ConfigTools.bannerColor.b, ss.ConfigTools.bannerColor.a)
  widgetFrame.banner:SetText("Seamore Spheres")
  widgetFrame.banner:SetJustifyV("TOP")
  widgetFrame.banner:SetJustifyH("RIGHT")

  return widgetFrame
end

ss.Utils.addModule("ConfigTools", mtConfigTools)
