local MAJOR, MINOR = "LibAddonMenu-1.0", 7
local lam, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not lam then return end	--the same or newer version of this lib is already loaded into memory

--UPVALUES--
lam.lastAddedControl = {}
local lastAddedControl = lam.lastAddedControl
local wm = GetWindowManager()
local strformat = string.format
local tostring = tostring
local round = zo_round
local optionsWindow = ZO_OptionsWindowSettingsScrollChild
local openSubMenu
lam.panels = {}
lam.forceControlName = nil


local lamPanel = {}
lamPanel.__index = lamPanel

setmetatable(lamPanel, {
    __call = function (cls, ...)
        return cls.new(...)
    end,
})

function lamPanel.new(controlPanelID, controlPanelName)
    local self = setmetatable({}, lamPanel)
    self.panelName = controlPanelName
    self.uniqCounter = 1

    if _G[controlPanelID] then
        self.panelID = _G[controlPanelID]
        return self
    end

    ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelName)

    --disables Defaults button because we don't need it, but keybind still works :/ ...
    self.panelID = _G[controlPanelID]

    lam.panels[panelID] = self
    return self
end

function lamPanel:AddHeader(text)
    local isSubMenu = type(self.panelID) == "userdata"
    local controlName = self:getUniqueName()
    --local header = wm:CreateControlFromVirtual(controlName, optionsWindow, lastAddedControl[panelID] and "ZO_Options_SectionTitle_WithDivider" or "ZO_Options_SectionTitle")
    local header = wm:CreateControlFromVirtual(controlName, isSubMenu and self.panelID or optionsWindow, lastAddedControl[self.panelID] and "ZO_Options_SectionTitle_WithDivider" or "ZO_Options_SectionTitle")
    if lastAddedControl[self.panelID] then
        header:SetAnchor(TOPLEFT, lastAddedControl[self.panelID], BOTTOMLEFT, 0, 15)
    else
        header:SetAnchor(TOPLEFT)
        if not isSubMenu then
            header:SetHandler("OnShow", function()
                ZO_OptionsWindowResetToDefaultButton:SetEnabled(false)
                ZO_OptionsWindowResetToDefaultButton:SetKeybindEnabled(false)
                ZO_OptionsWindowResetToDefaultButton:SetHidden(true)
            --ZO_OptionsWindowResetToDefaultButton:SetAlpha(0)
            end)
            header:SetHandler("OnHide", function()
                ZO_OptionsWindowResetToDefaultButton:SetEnabled(true)
                ZO_OptionsWindowResetToDefaultButton:SetKeybindEnabled(true)
                ZO_OptionsWindowResetToDefaultButton:SetHidden(false)
            --ZO_OptionsWindowResetToDefaultButton:SetAlpha(1)
            end)
        end
    end
    header.controlType = OPTIONS_SECTION_TITLE
    header.panel = isSubMenu and self.panelID.panel or self.panelID
    header.text = text

    ZO_OptionsWindow_InitializeControl(header)
    if isSubMenu then header:SetParent(self.panelID) end

    lastAddedControl[self.panelID] = header

    return header
end


--To-Do list:
--extra sub-options window out to the right?? (or maybe addon list?)
--find alternatives to handler hooks

function lamPanel:AddSlider(text, tooltip, minValue, maxValue, step, getFunc, setFunc, warning, warningText)
    local panelID = self.panelID
    local controlName = self:getUniqueName()
    local isSubMenu = type(panelID) == "userdata"
    local slider = wm:CreateControlFromVirtual(controlName, isSubMenu and panelID or optionsWindow, "ZO_Options_Slider")
    slider:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
    slider.controlType = OPTIONS_SLIDER
    slider.system = SETTING_TYPE_UI
    slider.panel = isSubMenu and panelID.panel or panelID
    slider.text = text
    slider.tooltipText = tooltip
    slider.showValue = true
    slider.showValueMin = minValue
    slider.showValueMax = maxValue
    local range = maxValue - minValue
    local slidercontrol = slider:GetNamedChild("Slider")
    local slidervalue = slider:GetNamedChild("ValueLabel")
    slidercontrol:SetValueStep(1/range * step)
    slider:SetHandler("OnShow", function()
        local curValue = getFunc()
        slidercontrol:SetValue((curValue - minValue)/range)
        slidervalue:SetText(tostring(curValue))
    end)
    slidercontrol:SetHandler("OnValueChanged", function (self, value)
        self:SetValue(value)
        value = round(value*range + minValue)
        slidervalue:SetText(strformat("%d", value))
    end)
    slidercontrol:SetHandler("OnSliderReleased", function(self, value)
        value = round(value*range + minValue)
        setFunc(value)
    end)

    if warning then
        slider.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", slider, "ZO_Options_WarningIcon")
        slider.warning:SetAnchor(RIGHT, slidercontrol, LEFT, -5, 0)
        slider.warning.tooltipText = warningText
    end

    ZO_OptionsWindow_InitializeControl(slider)
    if isSubMenu then slider:SetParent(panelID) end

    lastAddedControl[panelID] = slider

    return slider
end

function lamPanel:AddDropdown(text, tooltip, validChoices, getFunc, setFunc, warning, warningText)
    local panelID = self.panelID
    local controlName = self:getUniqueName()
    local isSubMenu = type(panelID) == "userdata"
    local dropdown = wm:CreateControlFromVirtual(controlName, isSubMenu and panelID or optionsWindow, "ZO_Options_Dropdown")
    dropdown:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
    dropdown.controlType = OPTIONS_DROPDOWN
    dropdown.system = SETTING_TYPE_UI
    dropdown.panel = isSubMenu and panelID.panel or panelID
    dropdown.text = text
    dropdown.tooltipText = tooltip
    dropdown.valid = validChoices
    local dropmenu = ZO_ComboBox_ObjectFromContainer(GetControl(dropdown, "Dropdown"))
    local setText = dropmenu.m_selectedItemText.SetText
    local selectedName
    ZO_PreHookHandler(dropmenu.m_selectedItemText, "OnTextChanged", function(self)
        if dropmenu.m_selectedItemData then
            selectedName = dropmenu.m_selectedItemData.name
            setText(self, selectedName)
            setFunc(selectedName)
        end
    end)
    dropdown:SetHandler("OnShow", function()
        dropmenu:SetSelectedItem(getFunc())
    end)

    if warning then
        dropdown.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", dropdown, "ZO_Options_WarningIcon")
        dropdown.warning:SetAnchor(RIGHT, dropdown:GetNamedChild("Dropdown"), LEFT, -5, 0)
        dropdown.warning.tooltipText = warningText
    end

    ZO_OptionsWindow_InitializeControl(dropdown)
    if isSubMenu then dropdown:SetParent(panelID) end

    lastAddedControl[panelID] = dropdown

    return dropdown
end

function lamPanel:AddCheckbox(text, tooltip, getFunc, setFunc, warning, warningText)
    local panelID = self.panelID
    local controlName = self:getUniqueName()
    local isSubMenu = type(panelID) == "userdata"
    local checkbox = wm:CreateControlFromVirtual(controlName, isSubMenu and panelID or optionsWindow, "ZO_Options_Checkbox")
    checkbox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
    checkbox.controlType = OPTIONS_CHECKBOX
    checkbox.system = SETTING_TYPE_UI
    checkbox.settingId = _G[strformat("SETTING_%s", controlName)]
    checkbox.panel = isSubMenu and panelID.panel or panelID
    checkbox.text = text
    checkbox.tooltipText = tooltip

    local checkboxButton = checkbox:GetNamedChild("Checkbox")

    ZO_PreHookHandler(checkbox, "OnShow", function()
        checkboxButton:SetState(getFunc() and 1 or 0)
        checkboxButton:toggleFunction(getFunc())
    end)
    ZO_PreHookHandler(checkboxButton, "OnClicked", function() setFunc(not getFunc()) end)

    if warning then
        checkbox.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", checkbox, "ZO_Options_WarningIcon")
        checkbox.warning:SetAnchor(RIGHT, checkboxButton, LEFT, -5, 0)
        checkbox.warning.tooltipText = warningText
    end

    ZO_OptionsWindow_InitializeControl(checkbox)
    if isSubMenu then checkbox:SetParent(panelID) end

    lastAddedControl[panelID] = checkbox

    return checkbox
end

function lamPanel:AddColorPicker(text, tooltip, getFunc, setFunc, warning, warningText)
    local panelID = self.panelID
    local controlName = self:getUniqueName()
    local isSubMenu = type(panelID) == "userdata"
    local colorpicker = wm:CreateTopLevelWindow(controlName)
    colorpicker:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
    colorpicker:SetParent(isSubMenu and panelID or optionsWindow)
    colorpicker:SetResizeToFitDescendents(true)
    colorpicker:SetWidth(510)
    colorpicker:SetMouseEnabled(true)

    colorpicker.label = wm:CreateControl(controlName.."Label", colorpicker, CT_LABEL)
    local label = colorpicker.label
    label:SetDimensions(300, 26)
    label:SetAnchor(TOPLEFT)
    label:SetFont("ZoFontWinH4")
    label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
    label:SetText(text)

    colorpicker.color = wm:CreateControl(controlName.."Color", colorpicker, CT_CONTROL)
    local color = colorpicker.color
    color:SetDimensions(200,26)
    color:SetAnchor(RIGHT)

    color.thumb = wm:CreateControl(controlName.."ColorThumb", color, CT_TEXTURE)
    local thumb = color.thumb
    thumb:SetDimensions(36, 18)
    thumb:SetAnchor(LEFT, color, LEFT, 4, 0)
    local r, g, b, a = getFunc()
    thumb:SetColor(r, g, b, a or 1)

    color.border = wm:CreateControl(controlName.."ColorBorder", color, CT_TEXTURE)
    local border = color.border
    border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds")
    border:SetTextureCoords(0, .625, 0, .8125)
    border:SetDimensions(40, 22)
    border:SetAnchor(CENTER, thumb, CENTER, 0, 0)

    local ColorPickerCallback
    if not ColorPickerCallback then
        ColorPickerCallback = function(r, g, b, a)
            thumb:SetColor(r, g, b, a or 1)
            setFunc(r, g, b, a)
        end
    end

    colorpicker.controlType = OPTIONS_CUSTOM
    colorpicker.customSetupFunction = function(colorpicker)
        colorpicker:SetHandler("OnMouseUp", function(self, btn, upInside)
            if upInside then
                local r, g, b, a = getFunc()
                COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, text)
            end
        end)
    end
    colorpicker.panel = isSubMenu and panelID.panel or panelID
    colorpicker.tooltipText = tooltip
    colorpicker:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
    colorpicker:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)

    if warning then
        colorpicker.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", colorpicker, "ZO_Options_WarningIcon")
        colorpicker.warning:SetAnchor(RIGHT, colorpicker:GetNamedChild("Color"), LEFT, -5, 0)
        colorpicker.warning.tooltipText = warningText
    end

    ZO_OptionsWindow_InitializeControl(colorpicker)
    if isSubMenu then colorpicker:SetParent(panelID) end

    lastAddedControl[panelID] = colorpicker

    return colorpicker
end

function lamPanel:AddEditBox(tooltip, isMultiLine, getFunc, setFunc, warning, warningText)
    local panelID = self.panelID
    local controlName = self:getUniqueName()
    local isSubMenu = type(panelID) == "userdata"
    local editbox = wm:CreateTopLevelWindow(controlName)
    editbox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
    editbox:SetResizeToFitDescendents(true)
    editbox:SetWidth(510)
    editbox:SetMouseEnabled(true)

    editbox.label = wm:CreateControl(controlName.."Label", editbox, CT_LABEL)
    local label = editbox.label
    label:SetDimensions(300, 26)
    label:SetAnchor(TOPLEFT)
    label:SetFont("ZoFontWinH4")
    label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
    label:SetText(text)

    editbox.bg = wm:CreateControlFromVirtual(controlName.."BG", editbox, "ZO_EditBackdrop")
    local bg = editbox.bg
    bg:SetDimensions(200,isMultiLine and 100 or 24)
    bg:SetAnchor(RIGHT)
    editbox.edit = wm:CreateControlFromVirtual(controlName.."Edit", bg, isMultiLine and "ZO_DefaultEditMultiLineForBackdrop" or "ZO_DefaultEditForBackdrop")
    editbox.edit:SetText(getFunc())
    editbox.edit:SetHandler("OnFocusLost", function(self) setFunc(self:GetText()) end)
    editbox.edit:SetHandler("OnEscape", function(self) self:LoseFocus() end)
    editbox.edit:SetMaxInputChars(1040)

    editbox.panel = isSubMenu and panelID.panel or panelID
    editbox.tooltipText = tooltip
    editbox:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
    editbox:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)

    if warning then
        editbox.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", editbox, "ZO_Options_WarningIcon")
        editbox.warning:SetAnchor(TOPRIGHT, editbox:GetNamedChild("BG"), TOPLEFT, -5, 0)
        editbox.warning.tooltipText = warningText
    end

    ZO_OptionsWindow_InitializeControl(editbox)
    editbox:SetParent(isSubMenu and panelID or optionsWindow)

    lastAddedControl[panelID] = editbox

    return editbox
end

function lamPanel:AddButton(text, tooltip, onClick, warning, warningText)
    local panelID = self.panelID
    local controlName = self:getUniqueName()
    local controlName = self:getUniqueName()
    local isSubMenu = type(panelID) == "userdata"
    local button = wm:CreateTopLevelWindow(controlName)
    button:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
    button:SetDimensions(510, 28)
    button:SetMouseEnabled(true)

    button.btn = wm:CreateControlFromVirtual(controlName.."Button", button, "ZO_DefaultButton")
    local btn = button.btn
    btn:SetAnchor(TOPRIGHT)
    btn:SetWidth(200)
    btn:SetText(text)
    btn:SetHandler("OnClicked", onClick)

    button.controlType = OPTIONS_CUSTOM
    button.customSetupFunction = function() end	--move handlers into this function? (since I created a function...)
    button.panel = isSubMenu and panelID.panel or panelID
    btn.tooltipText = tooltip
    btn:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
    btn:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)

    if warning then
        button.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", button, "ZO_Options_WarningIcon")
        button.warning:SetAnchor(RIGHT, btn, LEFT, -5, 0)
        button.warning.tooltipText = warningText
    end

    ZO_OptionsWindow_InitializeControl(button)
    button:SetParent(isSubMenu and panelID or optionsWindow)

    lastAddedControl[panelID] = button
    return button
end

function lamPanel:AddDescription(text, titleText)
    local panelID = self.panelID
    local controlName = self:getUniqueName()
    local isSubMenu = type(panelID) == "userdata"
    local textBox = wm:CreateTopLevelWindow(controlName)
    textBox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
    textBox:SetResizeToFitDescendents(true)
    textBox:SetWidth(510)

    if titleText then
        textBox.title = wm:CreateControl(controlName.."Title", textBox, CT_LABEL)
        local title = textBox.title
        title:SetWidth(510)
        title:SetAnchor(TOPLEFT, textBox, TOPLEFT)
        title:SetFont("ZoFontWinH4")
        title:SetText(titleText)
    end

    textBox.desc = wm:CreateControl(controlName.."Text", textBox, CT_LABEL)
    local desc = textBox.desc
    desc:SetWidth(510)
    if titleText then
        desc:SetAnchor(TOPLEFT, textBox.title, BOTTOMLEFT)
    else
        desc:SetAnchor(TOPLEFT)
    end
    desc:SetVerticalAlignment(TEXT_ALIGN_TOP)
    desc:SetFont("ZoFontGame")
    desc:SetText(text)

    textBox.controlType = OPTIONS_CUSTOM
    textBox.panel = isSubMenu and panelID.panel or panelID

    ZO_OptionsWindow_InitializeControl(textBox)
    textBox:SetParent(isSubMenu and panelID or optionsWindow)

    lastAddedControl[panelID] = textBox

    return textBox
end

--window doesn't hide when escape is pressed
--color-picker is hidden for some reason
function lamPanel:AddSubMenu(text, tooltip)
    local panelID = self.panelID
    local controlName = self:getUniqueName()
    local menubtn = wm:CreateTopLevelWindow(controlName)
    menubtn:SetParent(optionsWindow)
    menubtn:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
    menubtn:SetDimensions(510, 28)
    menubtn:SetMouseEnabled(true)

    menubtn.label = wm:CreateControl(controlName.."Text", menubtn, CT_LABEL)
    local label = menubtn.label
    label:SetAnchor(TOPLEFT, textBox, TOPLEFT)
    label:SetDimensions(300, 28)
    label:SetFont("ZoFontWinH4")
    label:SetText(text)

    menubtn.btn = wm:CreateControlFromVirtual(controlName.."Button", menubtn, "ZO_DefaultButton")
    local btn = menubtn.btn
    btn:SetAnchor(TOPRIGHT)
    btn:SetWidth(200)
    btn:SetText(GetString("SI_GAMECAMERAACTIONTYPE", 13).." |t32:32:esoui\\art\\crafting\\smithing_rightarrow_up.dds|t")
    --btn:SetText("Open -->")

    menubtn.window = wm:CreateTopLevelWindow(controlName.."Window")
    local window = menubtn.window
    --window:SetParent(menubtn)
    window:SetAnchor(TOPLEFT, menubtn, TOPRIGHT)
    window:SetDimensions(555, 300)
    window:SetClampedToScreen(true)
    window:SetClampedToScreenInsets(-5, -20, 5, 5)
    window.bg = wm:CreateControlFromVirtual(controlName.."WindowBG", window, "ZO_DefaultBackdrop")
    window:SetHidden(true)

    window.settings = wm:CreateControlFromVirtual(controlName.."WindowSettings", window, "ZO_ScrollContainer")
    local settings = window.settings
    settings:SetAnchor(TOPLEFT, window, TOPLEFT, 10, 10)
    settings:SetAnchor(BOTTOMRIGHT, window, BOTTOMRIGHT, -5, -5)
    local scroll = settings:GetNamedChild("ScrollChild")
    scroll.panel = panelID

    btn:SetHandler("OnClicked", function()
        if window:IsHidden() then	--if this submenu isn't open yet, then...
            if openSubMenu then openSubMenu:SetHidden(true) end	--if a submenu was already open, then close it
            window:SetHidden(false)	--show this submenu
            openSubMenu = window	--this submenu is now our open menu
        else
            window:SetHidden(true)
            openSubMenu = nil	--no more open submenus
        end
    end)
    menubtn:SetHandler("OnHide", function()
        if openSubMenu then
            openSubMenu:SetHidden(true)
        end
    end)
    ZO_OptionsWindow:SetHandler("OnHide", function()
        if openSubMenu then
            openSubMenu:SetHidden(true)
        end
    end)

    menubtn.controlType = OPTIONS_CUSTOM
    menubtn.customSetupFunction = function() end	--move handlers into this function? (since I created a function...)
    menubtn.panel = panelID
    btn.tooltipText = tooltip
    btn:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
    btn:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)

    ZO_OptionsWindow_InitializeControl(menubtn)

    lastAddedControl[panelID] = menubtn

    lam:AddHeader(scroll, controlName.."MenuHeader", text)	--create the header for our menu


    local panel = setmetatable({}, lamPanel)
    panel.panelName = controlName
    panel.panelID = panelID
    self.panels[panelID] = panel
    return panel, scroll
end