-------------------------------------------------------------------------------------
-- Title: MSBT Options Control Templates
-- Author: Mik
-------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------
-- Private constants.
-------------------------------------------------------------------------------------

local OPTIONS_FRAME_NAME = "MSBTFrameOptions";

-------------------------------------------------------------------------------------
-- Control template setup functions.
-------------------------------------------------------------------------------------

-- **********************************************************************************
-- Sets up a tab with the passed information.
-- **********************************************************************************
function MikSBTOpt.SetupTab(frameName, label, tooltip, clickFunc)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  associatedFrame.tooltipText = tooltip;
  associatedFrame.clickFunction = clickFunc;

  -- Set the text for the tab and resize it.
  if (label) then
   associatedFrame:SetText(label);
   PanelTemplates_TabResize(1, associatedFrame);
  end
 end
end


-- **********************************************************************************
-- Sets up a checkbox with the passed information.
-- **********************************************************************************
function MikSBTOpt.SetupCheckbox(frameName, label, tooltip, clickFunc)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  associatedFrame.tooltipText = tooltip;
  associatedFrame.clickFunction = clickFunc;

  -- Set the text for the checkbox.
  if (label) then
   getglobal(frameName .. "Text"):SetText(label);
  end
 end
end


-- **********************************************************************************
-- Sets up a dropdown with the passed information.
-- **********************************************************************************
function MikSBTOpt.SetupDropdown(frameName, label, tooltip, clickFunc, options)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  associatedFrame.tooltipText = tooltip;
  associatedFrame.clickFunction = clickFunc;
  associatedFrame.menuOptions = options;

  -- Set the label for the dropdown.
  if (label) then
   getglobal(frameName .. "Label"):SetText(label);
  end

  -- Initialize the dropdown.
  UIDropDownMenu_Initialize(associatedFrame, MikSBTOpt.TemplateDropdownInit);
 end
end


-- **********************************************************************************
-- Sets up a button with the passed information.
-- **********************************************************************************
function MikSBTOpt.SetupButton(frameName, label, tooltip, clickFunc)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  associatedFrame.tooltipText = tooltip;
  associatedFrame.clickFunction = clickFunc;

  -- Set the label for the button.
  if (label) then
   associatedFrame:SetText(label);
   associatedFrame:SetWidth(associatedFrame:GetTextWidth() + 40);
  end
 end
end


-- **********************************************************************************
-- Sets up an editbox with the passed information.
-- **********************************************************************************
function MikSBTOpt.SetupEditbox(frameName, label, tooltip, textChangedFunc)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  associatedFrame.tooltipText = tooltip;
  associatedFrame.textChangedFunc = textChangedFunc;

  -- Set the label for the editbox.
  if (label) then
   getglobal(frameName .. "Label"):SetText(label);
  end
 end
end


-- **********************************************************************************
-- Sets up a color swatch with the passed information.
-- **********************************************************************************
function MikSBTOpt.SetupColorSwatch(frameName, tooltip, swatchFunc)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  associatedFrame.tooltipText = tooltip;
  associatedFrame.swatchFunc = swatchFunc;
 end 
end


-- **********************************************************************************
-- Sets up a slider with the passed information.
-- **********************************************************************************
function MikSBTOpt.SetupSlider(frameName, label, tooltip, minValue, maxValue, step, changeFunc)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  associatedFrame.savedLabel = label;
  associatedFrame.tooltipText = tooltip;
  associatedFrame.changeFunc = changeFunc;

  -- Set the label for the slider.
  if (label) then
   getglobal(frameName .. "Text"):SetText(label);
  end

  -- Set the min, max, and step values for the slider.
  associatedFrame:SetMinMaxValues(minValue, maxValue);
  associatedFrame:SetValueStep(step);
 end 
end


-------------------------------------------------------------------------------------
-- Control template populate functions.
-------------------------------------------------------------------------------------

-- **********************************************************************************
-- Sets the checkbox's checked state for the passed frame name.
-- **********************************************************************************
function MikSBTOpt.PopulateCheckbox(frameName, isChecked)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  -- Check the box based on the passed value.
  associatedFrame:SetChecked(isChecked);
 end 
end


-- **********************************************************************************
-- Sets the dropdown's selected value for the passed frame name.
-- **********************************************************************************
function MikSBTOpt.PopulateDropdown(frameName, selectValue)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  -- Make sure there is a value to be selected.
  if (selectValue ~= nil) then
   -- Set the default selected value.
   UIDropDownMenu_SetSelectedValue(associatedFrame, selectValue);

   -- Set the text for the default selected value.
   for _, option in ipairs(associatedFrame.menuOptions) do
    -- If the option is a table extract the name and value from it.
    local tempName = option;
    local tempValue = option;
    if (type(option) == "table") then
     tempName = option.Name;
     tempValue = option.Value;
    end

    if (tempValue == associatedFrame.selectedValue) then
     UIDropDownMenu_SetText(tempName, associatedFrame);
    end
   end

  end
 end
end


-- **********************************************************************************
-- Sets the text for the passed frame name.
-- **********************************************************************************
function MikSBTOpt.PopulateEditbox(frameName, newText)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists and there was text passed.
 if (associatedFrame and newText) then
  -- Set the text to the passed value.
  associatedFrame:SetText(newText);
 end 
end


-- **********************************************************************************
-- Sets the color for the passed color swatch frame.
-- **********************************************************************************
function MikSBTOpt.PopulateColorSwatch(frameName, r, g, b)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  associatedFrame.r = r;
  associatedFrame.g = g;
  associatedFrame.b = b;

  getglobal(associatedFrame:GetName() .. "NormalTexture"):SetVertexColor(r, g, b);
 end
end


-- **********************************************************************************
-- Sets the value for the passed slider frame.
-- **********************************************************************************
function MikSBTOpt.PopulateSlider(frameName, value)
 local associatedFrame = getglobal(frameName);

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  associatedFrame:SetValue(value);
 end
end


-------------------------------------------------------------------------------------
-- Control template action functions.
-------------------------------------------------------------------------------------

-- **********************************************************************************
-- Called when a tab is clicked.
-- **********************************************************************************
function MikSBTOpt.TemplateTabOnClick()
 -- Get the clicked tab number.
 local tabNumber = this:GetID();

 -- Call the tab's click function if it has one.
 if (this.clickFunction) then
  this.clickFunction(tabNumber);
 end
end


-- **********************************************************************************
-- Called when a checkbox is clicked.
-- **********************************************************************************
function MikSBTOpt.TemplateCheckboxOnClick()
 -- Call the checkbox's click function if it has one.
 if (this.clickFunction) then
  this.clickFunction();
 end
end


-- **********************************************************************************
-- Called when a drop down menu is initialized (shown).
-- **********************************************************************************
function MikSBTOpt.TemplateDropdownInit()
 local info = {};

 -- Get the dropdown frame.
 local dropdownFrame = this;

 -- Check if dropdownFrame is a button and not the actual dropdown itself.
 if (not dropdownFrame.menuOptions) then
  dropdownFrame = this:GetParent();
 end

 -- Make sure there is dropdown data.
 if (dropdownFrame.menuOptions) then
  -- Loop through all of the options for dropdown.
  for _, option in ipairs(dropdownFrame.menuOptions) do
   -- Check if the option is a table and extract the values from it.
   local tempName = option;
   local tempValue = option;
   if (type(option) == "table") then
    tempName = option.Name;
    tempValue = option.Value;
   end

   -- Add the option to the dropdown list.
   info = {};
   info.text = tempName;
   info.value = tempValue;
   info.func = MikSBTOpt.TemplateDropdownOnClick;
   info.arg1 = dropdownFrame:GetName();
   UIDropDownMenu_AddButton(info);
  end
 end
end


-- **********************************************************************************
-- Called when a drop down menu item is selected.
-- **********************************************************************************
function MikSBTOpt.TemplateDropdownOnClick(frameName)
 -- Set the selected dropdown option to the appropriate value.
 UIDropDownMenu_SetSelectedValue(getglobal(frameName), this.value);

 -- Call the dropdown's click function if it has one.
 if (getglobal(frameName).clickFunction) then
  getglobal(frameName).clickFunction(frameName);
 end
end


-- **********************************************************************************
-- Called when a button is clicked.
-- **********************************************************************************
function MikSBTOpt.TemplateButtonOnClick()
 -- Call the button's click function if it has one.
 if (this.clickFunction) then
  this.clickFunction();
 end
end


-- **********************************************************************************
-- Called when the text in an editbox changes.
-- **********************************************************************************
function MikSBTOpt.TemplateEditboxOnTextChanged()
 -- Call the editbox's text changed function if it has one.
 if (this.textChangedFunc) then
  this.textChangedFunc();
 end
end


-- **********************************************************************************
-- Called when a color swatch is clicked.
-- **********************************************************************************
function MikSBTOpt.TemplateColorSwatchOnClick()
 local tempR = this.r or 1;
 local tempG = this.g or 1;
 local tempB = this.b or 1;

 ColorPickerFrame.associatedColorSwatch = this;
 ColorPickerFrame.hasOpacity = false;
 ColorPickerFrame.opacity = 1;
 ColorPickerFrame.previousValues = {r = tempR, g = tempG, b = tempB};
 ColorPickerFrame.func = MikSBTOpt.TemplateColorSwatchOnChange;
 ColorPickerFrame.cancelFunc = MikSBTOpt.TemplateColorSwatchOnCancel;
 ColorPickerFrame:SetColorRGB(tempR, tempG, tempB);
 ColorPickerFrame:ClearAllPoints();
 ColorPickerFrame:SetPoint("CENTER", getglobal(OPTIONS_FRAME_NAME), "CENTER");
 ColorPickerFrame:Show();
end


-- **********************************************************************************
-- Called when a color swatch changes.
-- **********************************************************************************
function MikSBTOpt.TemplateColorSwatchOnChange()
 local associatedFrame = ColorPickerFrame.associatedColorSwatch;

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  local r, g, b = ColorPickerFrame:GetColorRGB();
  MikSBTOpt.PopulateColorSwatch(associatedFrame:GetName(), r, g, b);

  -- Call the color swatch's function if it has one.
  if (associatedFrame.swatchFunc) then
   associatedFrame.swatchFunc(associatedFrame);
  end
 end
end


-- **********************************************************************************
-- Called when a color swatch change is cancelled.
-- **********************************************************************************
function MikSBTOpt.TemplateColorSwatchOnCancel(previousValues)
 local associatedFrame = ColorPickerFrame.associatedColorSwatch;

 -- Make sure the associated frame exists.
 if (associatedFrame) then
  MikSBTOpt.PopulateColorSwatch(associatedFrame:GetName(), previousValues.r, previousValues.g, previousValues.b);

  -- Call the color swatch's function if it has one.
  if (associatedFrame.swatchFunc) then
   associatedFrame.swatchFunc(associatedFrame);
  end  
 end 
end


-- **********************************************************************************
-- Called when a slider value is changed.
-- **********************************************************************************
function MikSBTOpt.TemplateSliderOnValueChanged()
 -- Set the new value into the label.
 if (this.savedLabel) then
  getglobal(this:GetName() .. "Text"):SetText(this.savedLabel .. ": " .. this:GetValue());
 else
  getglobal(this:GetName() .. "Text"):SetText(this:GetValue());
 end

 -- Call the slider change function if there is one.
 if (this.changeFunc) then
  this.changeFunc();
 end
end


-------------------------------------------------------------------------------------
-- Control template utility functions.
-------------------------------------------------------------------------------------

-- **********************************************************************************
-- Compares two dropdown option name/value tables.
-- **********************************************************************************
function MikSBTOpt.DropdownOptionsNameCompareFunc(optionOne, optionTwo)
 return optionOne.Name < optionTwo.Name;
end