--[[
Author: Jarth
Filename: SummonAssistant:lua
]] --

-------------------------------------------------------------------------------------------------
--  Libraries --
-------------------------------------------------------------------------------------------------
local LAM2 = LibStub:GetLibrary("LibAddonMenu-2.0")

-------------------------------------------------------------------------------------------------
--  VARIABLE --
-------------------------------------------------------------------------------------------------
local ADDON_NAME = "SummonAssistant"
local ADDON_DISPLAY_NAME = "Summon Assistant"
local ADDON_VERSION = 1.3
local ADDON_MINOR_VERSION = 0
local ADDON_AUTHOR = "Jarth"
local ADDON_WEBSITE = ""
local SummonAssistant = {}
SummonAssistant.wm = GetWindowManager()
SummonAssistant.Buttons = {}
SummonAssistant.Fragment = nil
SummonAssistant.Types = {
    Banker = {
        Id = 267,
        Title = "Banker:",
        Name = "Banker",
        name = "banker",
        Tooltip = "When ON the banker button will be visible. When OFF the banker button will not be visible (disabled if locked for the account).",
        EnabledTexture = "/esoui/art/icons/" .. "assistant_banker_01.dds",
        DisabledTexture = "/esoui/art/icons/" .. "assistant_banker_01-empty.dds",
        KeyBinding = "SI_BINDING_NAME_SummonAssistant_Assistant_Banker",
        Disabled = function()
            IsCollectibleUnlocked(267)
        end
    },
    Fence = {
        Id = 300,
        Title = "Fence:",
        Name = "Fence",
        name = "fence",
        Tooltip = "When ON the fence button will be visible. When OFF the fence button will not be visible (disabled if locked for the account).",
        EnabledTexture = "/esoui/art/icons/" .. "assistant_fence_01.dds",
        DisabledTexture = "/esoui/art/icons/" .. "assistant_fence_01-empty.dds",
        KeyBinding = "SI_BINDING_NAME_SummonAssistant_Assistant_Fence",
        Disabled = function()
            IsCollectibleUnlocked(300)
        end
    },
    Vendor = {
        Id = 301,
        Title = "Vendor:",
        Name = "Vendor",
        name = "vendor",
        Tooltip = "When ON the vendor button will be visible. When OFF the vendor button will not be visible (disabled if locked for the account).",
        EnabledTexture = "/esoui/art/icons/" .. "assistant_vendor_01.dds",
        DisabledTexture = "/esoui/art/icons/" .. "assistant_vendor_01-empty.dds",
        KeyBinding = "SI_BINDING_NAME_SummonAssistant_Assistant_Vendor",
        Disabled = function()
            IsCollectibleUnlocked(301)
        end
    }
}
SummonAssistant.OrderedTypes = {
    [1] = SummonAssistant.Types["Banker"],
    [2] = SummonAssistant.Types["Fence"],
    [3] = SummonAssistant.Types["Vendor"]
}

SummonAssistant.Default = {
    Left = CENTER,
    Top = CENTER,
    CenterColor = {r = 0.88, g = 0.88, b = 0.88, a = 0.4},
    EdgeColor = {r = 0.57, g = 0.57, b = 0.57, a = 0.6},
    UseAccountSettings = true,
    Horizontal = true,
    HideBarInMenu = true,
    ShowMoveAssitance = false,
    ShowAssistants = {}
}
--Shows assistants by default, when unlocked.
SummonAssistant.Default.ShowAssistants[267] = IsCollectibleUnlocked(267)
SummonAssistant.Default.ShowAssistants[300] = IsCollectibleUnlocked(300)
SummonAssistant.Default.ShowAssistants[301] = IsCollectibleUnlocked(301)
SummonAssistant.Global = {
    NumberUnlocked = GetTotalCollectiblesByCategoryType(COLLECTIBLE_CATEGORY_TYPE_ASSISTANT),
    LblOffset = 10,
    LblHeight = 60,
    LblWidth = 60
}

-------------------------------------------------------------------------------------------------
--  FUNCTIONS --
-------------------------------------------------------------------------------------------------

function SummonAssistant.OnAddOnLoaded(event, addonName)
    if addonName == ADDON_NAME then
        SummonAssistant.Initialize()
    end
end

function SummonAssistant.Initialize()
    -- Load saved values..
    SummonAssistant.Saved = ZO_SavedVars:New("SummonAssistant_Character", ADDON_VERSION, nil, SummonAssistant.Default)
    if SummonAssistant.Saved.UseAccountSettings then
        SummonAssistant.Saved = ZO_SavedVars:NewAccountWide("SummonAssistant_Account", ADDON_VERSION, nil, SummonAssistant.Default)
    end
    SummonAssistant_Frame:SetHandler("OnMoveStop", SummonAssistant.OnMoveStop)

    SummonAssistant:RestorePanel()
    SummonAssistant:CreateHotkeySelections()
    SummonAssistant:CreateSettingsWindow()

    EVENT_MANAGER:UnregisterForEvent(ADDON_NAME, EVENT_ADD_ON_LOADED)
end

function SummonAssistant.OnMoveStop(frame)
    SummonAssistant.Saved.Top = frame:GetTop()
    SummonAssistant.Saved.Left = frame:GetLeft()
end

-------------------------------------------------------------------------------------------------
--  PRIVATE FUNCTIONS --
-------------------------------------------------------------------------------------------------

function SummonAssistant:GetVersion(showMinor)
    if showMinor == false or ADDON_MINOR_VERSION == nil then
        return tostring(ADDON_VERSION)
    end
    return tostring(ADDON_VERSION) .. "." .. tostring(ADDON_MINOR_VERSION)
end

function SummonAssistant:OnClicked(id)
    -- increment the counter by one
    if id > 0 then
        if IsCollectibleUnlocked(id) then
            UseCollectible(id)
        else
            UseCollectible(GetActiveCollectibleByType(COLLECTIBLE_CATEGORY_TYPE_ASSISTANT))
        end
    end
end

function SummonAssistant:addControlToFrame(menuOpen)
    if menuOpen then
        SummonAssistant_Frame:SetHidden(true)
    end

    SCENE_MANAGER:GetScene("hud"):AddFragment(SummonAssistant.Fragment)
    SCENE_MANAGER:GetScene("hudui"):AddFragment(SummonAssistant.Fragment)
end

function SummonAssistant:removeControlToFrame(menuOpen)
    if menuOpen then
        SummonAssistant_Frame:SetHidden(false)
    end

    SCENE_MANAGER:GetScene("hud"):RemoveFragment(SummonAssistant.Fragment)
    SCENE_MANAGER:GetScene("hudui"):RemoveFragment(SummonAssistant.Fragment)
end

function SummonAssistant:SetupButton(key, SummonAssistant_Button, id, enabled)
    local SummonAssistant_ButtonTexture = SummonAssistant.wm:GetControlByName("SummonAssistant_Button" .. key .. "Texture")
    if SummonAssistant_ButtonTexture ~= nil then
        local handler = nil
        local texture = SummonAssistant.Types[key].DisabledTexture
        if enabled then
            handler = function(self)
                SummonAssistant:OnClicked(SummonAssistant_Button:GetId())
            end
            texture = SummonAssistant.Types[key].EnabledTexture
        end
        SummonAssistant_Button:SetHandler("OnClicked", handler)
        SummonAssistant_ButtonTexture:SetTexture(texture)
    end
end

function SummonAssistant:CreateHotkeySelections()
    for _, _value in ipairs(SummonAssistant.OrderedTypes) do
        if IsCollectibleUnlocked(_value.Id) then
            ZO_CreateStringId(_value.KeyBinding, _value.Name)
        end
    end
end

function SummonAssistant:RestorePanel()
    SummonAssistant:SetFragmentBehaviour()

    SummonAssistant:SetButtonFrameWidth()

    SummonAssistant:FrameBackdropColor()

    SummonAssistant:InitializeButtons()

    SummonAssistant:RestorePosition()

    SummonAssistant:ActivateMoveHandlers()
end

function SummonAssistant:SetFragmentBehaviour(menuOpen)
    if SummonAssistant.Fragment == nil then
        SummonAssistant.Fragment = ZO_HUDFadeSceneFragment:New(SummonAssistant_Frame)
    end

    if SummonAssistant.Saved.HideBarInMenu then
        SummonAssistant:addControlToFrame(menuOpen)
    else
        SummonAssistant:removeControlToFrame(menuOpen)
    end
end

function SummonAssistant:SetButtonFrameWidth()
    local saBtnHeight = 60
    local saBtnWidth = 60
    local saCount = 0
    local saShow = 0

    for key, value in pairs(SummonAssistant.Saved.ShowAssistants) do
        if IsCollectibleUnlocked(key) and SummonAssistant.Saved.ShowAssistants[key] then
            saCount = saCount + 1
        end
        if saShow == 0 then
            saShow = 1
        end
    end

    SummonAssistant_Frame:SetHidden(saCount == 0)
    SummonAssistant_Frame:SetHeight(SummonAssistant.Global.LblHeight * (SummonAssistant.Saved.Horizontal and saShow or saCount))
    SummonAssistant_Frame:SetWidth(SummonAssistant.Global.LblWidth * (SummonAssistant.Saved.Horizontal and saCount or saShow))

    SummonAssistant_FrameBackdrop:SetHidden(saCount == 0)
    SummonAssistant_FrameBackdrop:SetHeight(SummonAssistant.Global.LblHeight * (SummonAssistant.Saved.Horizontal and saShow or saCount))
    SummonAssistant_FrameBackdrop:SetWidth(SummonAssistant.Global.LblWidth * (SummonAssistant.Saved.Horizontal and saCount or saShow))
end

function SummonAssistant:FrameBackdropColor(centerColor, edgeColor)
    if not centerColor then
        centerColor = SummonAssistant.Saved.CenterColor
    end
    if not edgeColor then
        edgeColor = SummonAssistant.Saved.EdgeColor
    end
    SummonAssistant_FrameBackdrop:SetCenterColor(centerColor.r, centerColor.g, centerColor.b, centerColor.a)
    SummonAssistant_FrameBackdrop:SetEdgeColor(edgeColor.r, edgeColor.g, edgeColor.b, edgeColor.a)
end

function SummonAssistant:InitializeButtons()
    for index, _value in ipairs(SummonAssistant.OrderedTypes) do
        local id = _value.Id
        local key = _value.Name
        local left, top = SummonAssistant:GetButtonPosition(index)
        if SummonAssistant.Saved.ShowAssistants[id] then
            local enabled = IsCollectibleUnlocked(_value.Id)
            if SummonAssistant.Buttons[key] == nil then
                SummonAssistant.Buttons[key] = WINDOW_MANAGER:CreateControlFromVirtual("SummonAssistant_Button", SummonAssistant_FrameBackdrop, "SummonAssistant_Button", key)
                SummonAssistant.Buttons[key]:SetId(id)
            end
            SummonAssistant:SetupButton(key, SummonAssistant.Buttons[key], id, enabled)
            SummonAssistant.Buttons[key]:ClearAnchors()
            SummonAssistant.Buttons[key]:SetAnchor(TOPLEFT, SummonAssistant_FrameBackdrop, TOPLEFT, left, top)
            SummonAssistant.Buttons[key]:SetHidden(false)
        elseif SummonAssistant.Buttons[key] ~= nil then
            SummonAssistant.Buttons[key]:SetHidden(true)
        end
    end
end

function SummonAssistant:GetButtonPosition(index)
    local left = SummonAssistant.Global.LblOffset
    local top = SummonAssistant.Global.LblOffset + SummonAssistant.Global.LblHeight * (index - 1)
    if SummonAssistant.Saved.Horizontal then
        left = SummonAssistant.Global.LblOffset + SummonAssistant.Global.LblHeight * (index - 1)
        top = SummonAssistant.Global.LblOffset
    end
    return left, top
end

function SummonAssistant:RestorePosition()
    local Top = SummonAssistant.Saved.Top
    local Left = SummonAssistant.Saved.Left
    SummonAssistant_Frame:ClearAnchors()
    SummonAssistant_Frame:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, Left, Top)
end

function SummonAssistant:ActivateMoveHandlers()
    if not SummonAssistant_Frame.LabelTopLeft and SummonAssistant.Saved.ShowMoveAssitance then
        SummonAssistant_Frame.LabelTopLeft = SummonAssistant.wm:CreateControl(nil, SummonAssistant_Frame, CT_LABEL)
        SummonAssistant_Frame.LabelTopLeft:SetDrawLevel(3)
        SummonAssistant_Frame.LabelTopLeft:SetAnchorFill(SummonAssistant_Frame)
        SummonAssistant_Frame.LabelTopLeft:SetFont("ZoFontWinH5")
        SummonAssistant_Frame.LabelTopLeft:SetHorizontalAlignment(0)
        SummonAssistant_Frame.LabelTopLeft:SetVerticalAlignment(0)
        SummonAssistant_Frame["UpdateText"] = SummonAssistant.UpdateText
        SummonAssistant_Frame:SetHandler("OnMouseEnter", SummonAssistant.OnMouseEnter)
        SummonAssistant_Frame:SetHandler("OnMouseDown", SummonAssistant.OnMouseDown)
        SummonAssistant_Frame:SetHandler("OnMouseUp", SummonAssistant.OnMouseUp)
        SummonAssistant_Frame:SetHandler("OnMouseExit", SummonAssistant.OnMouseExit)
    elseif SummonAssistant_Frame.LabelTopLeft and not SummonAssistant.Saved.ShowMoveAssitance then
        SummonAssistant_Frame.LabelTopLeft = nil
        SummonAssistant_Frame["UpdateText"] = nil
        SummonAssistant_Frame:SetHandler("OnMouseEnter", nil)
        SummonAssistant_Frame:SetHandler("OnMouseDown", nil)
        SummonAssistant_Frame:SetHandler("OnMouseUp", nil)
        SummonAssistant_Frame:SetHandler("OnMouseExit", nil)
    end
end

-------------------------------------------------------------------------------------------------
-- FUNCTIONS --
-- Move handlers --
-------------------------------------------------------------------------------------------------

function SummonAssistant.OnMouseEnter(frame)
    frame.UpdateText(frame, true)
end

function SummonAssistant.OnMouseDown(frame)
    frame:SetHandler("OnUpdate", SummonAssistant.OnMouseEnter)
end

function SummonAssistant.OnMouseExit(frame)
    frame.UpdateText(frame, false)
end

function SummonAssistant.OnMouseUp(frame)
    frame:SetHandler("OnUpdate", nil)
end

function SummonAssistant.UpdateText(frame, position)
    if position then
        frame.labelTextTopLeft = frame:GetLeft() .. "," .. frame:GetTop()
    else
        frame.labelTextTopLeft = ""
    end
    frame.LabelTopLeft:SetText(frame.labelTextTopLeft)
end

-------------------------------------------------------------------------------------------------
--  Menu Functions --
-------------------------------------------------------------------------------------------------
function SummonAssistant:CreateSettingsWindow()
    local panelData = {
        type = "panel",
        name = ADDON_DISPLAY_NAME,
        displayName = ADDON_DISPLAY_NAME,
        author = "Jarth",
        version = SummonAssistant:GetVersion(true),
        slashCommand = "/sa",
        registerForRefresh = true,
        registerForDefaults = true
    }
    local cntrlOptionsPanel = LAM2:RegisterAddonPanel(ADDON_NAME, panelData)

    local optionsData = {
        [1] = {
            type = "header",
            name = ADDON_DISPLAY_NAME .. " Settings"
        },
        [2] = {
            type = "description",
            text = "Here you can adjust how the summon assistant works."
        },
        [3] = {
            type = "checkbox",
            name = "Use account settings",
            tooltip = "When ON the account settings will be used. When OFF character settings will be used.",
            default = SummonAssistant.Default.UseAccountSettings,
            getFunc = function()
                return SummonAssistant.Saved.UseAccountSettings
            end,
            setFunc = function(newValue)
                --Apply value to existing variable
                SummonAssistant.Saved.UseAccountSettings = newValue
                if newValue then
                    SummonAssistant.Saved = ZO_SavedVars:NewAccountWide("SummonAssistant_Account", ADDON_VERSION, nil, SummonAssistant.Default)
                else
                    SummonAssistant.Saved = ZO_SavedVars:New("SummonAssistant_Character", ADDON_VERSION, nil, SummonAssistant.Default)
                end
                --Apply value to new variable
                SummonAssistant.Saved.UseAccountSettings = newValue
                SummonAssistant:RestorePanel()
            end
        },
        [4] = {
            type = "checkbox",
            name = "Bar orientation horizontal",
            tooltip = "When ON the bar will orientate horizontally.",
            default = SummonAssistant.Default.Horizontal,
            getFunc = function()
                return SummonAssistant.Saved.Horizontal
            end,
            setFunc = function(newValue)
                --Apply value to existing variable
                SummonAssistant.Saved.Horizontal = newValue
                SummonAssistant:RestorePanel()
            end
        },
        [5] = {
            type = "checkbox",
            name = "Hide bar in menu",
            tooltip = "When ON the bar will hide when a menu is opened.",
            default = SummonAssistant.Default.HideBarInMenu,
            getFunc = function()
                return SummonAssistant.Saved.HideBarInMenu
            end,
            setFunc = function(newValue)
                SummonAssistant.Saved.HideBarInMenu = newValue
                SummonAssistant:SetFragmentBehaviour(true)
            end
        },
        [6] = {
            type = "checkbox",
            name = "Show bar position",
            tooltip = "When ON the bar will show the X,Y position of the top left corner, when the mouse enters and drags the panel around.",
            default = function()
                return SummonAssistant.Default.ShowMoveAssitance
            end,
            getFunc = function()
                return SummonAssistant.Saved.ShowMoveAssitance
            end,
            setFunc = function(newValue)
                SummonAssistant.Saved.ShowMoveAssitance = newValue
                SummonAssistant:RestorePanel()
            end
        },
        [7] = {
            type = "submenu",
            name = "Colors",
            tooltip = "Allows you to change colors.",
            controls = {
                [1] = {
                    type = "description",
                    text = "Here you can adjust the colors."
                },
                [2] = {
                    type = "colorpicker",
                    name = "Backdrop Color",
                    default = function()
                        return SummonAssistant.Default.CenterColor
                    end,
                    tooltip = "Changes the color of the background.",
                    getFunc = function()
                        return SummonAssistant.Saved.CenterColor.r, SummonAssistant.Saved.CenterColor.g, SummonAssistant.Saved.CenterColor.b, SummonAssistant.Saved.CenterColor.a
                    end,
                    setFunc = function(r, g, b, a)
                        SummonAssistant.Saved.CenterColor = {r = r, g = g, b = b, a = a}
                        SummonAssistant:FrameBackdropColor()
                    end,
                    width = "half"
                },
                [3] = {
                    type = "colorpicker",
                    name = "Frame Color",
                    default = function()
                        return SummonAssistant.Default.EdgeColor
                    end,
                    tooltip = "Changes the color of the frame.",
                    getFunc = function()
                        return SummonAssistant.Saved.EdgeColor.r, SummonAssistant.Saved.EdgeColor.g, SummonAssistant.Saved.EdgeColor.b, SummonAssistant.Saved.EdgeColor.a
                    end,
                    setFunc = function(r, g, b, a)
                        SummonAssistant.Saved.EdgeColor = {r = r, g = g, b = b, a = a}
                        SummonAssistant:FrameBackdropColor()
                    end,
                    width = "half"
                }
            }
        },
        [8] = {
            type = "submenu",
            name = "Visibility",
            tooltip = "Allows you to choose what assistant buttons you wants to see.",
            controls = {
                [1] = {
                    type = "description",
                    text = "Select assistant buttons you want enabled."
                }
            }
        }
    }

    for index, _type in ipairs(SummonAssistant.OrderedTypes) do
        local line = {
            type = "checkbox",
            name = "Show " .. _type.name,
            tooltip = _type.Tooltip,
            default = not _type.Disabled,
            disabled = _type.Disabled,
            getFunc = function()
                return SummonAssistant.Saved.ShowAssistants[_type.Id]
            end,
            setFunc = function(newValue)
                SummonAssistant.Saved.ShowAssistants[_type.Id] = newValue
                SummonAssistant:RestorePanel()
            end
        }
        table.insert(optionsData[8].controls, index + 1, line)
    end
    LAM2:RegisterOptionControls(ADDON_NAME, optionsData)
end

EVENT_MANAGER:RegisterForEvent(ADDON_NAME, EVENT_ADD_ON_LOADED, SummonAssistant.OnAddOnLoaded)