--[[
Author: Jarth
Filename: CBs_MoveFrame.lua
]] --
-------------------------------------------------------------------------------------------------
-- VARIABLES --
-------------------------------------------------------------------------------------------------
local base = CollectionBars

-------------------------------------------------------------------------------------------------
-- FUNCTIONS --
-------------------------------------------------------------------------------------------------
function base.GetMoveFrameSnapPosition(frame, positionTargetXY, snapSize)
    local left, top = frame:GetLeft(), frame:GetTop()
    local width, height = frame:GetWidth(), frame:GetHeight()
    local x, y = left, top

    -- if positionTargetXY == TOPLEFT or positionTargetXY == TOP or positionTargetXY == TOPRIGHT then y = top
    if positionTargetXY == LEFT or positionTargetXY == CENTER or positionTargetXY == RIGHT then
        y = top + height / 2
    elseif positionTargetXY == BOTTOMLEFT or positionTargetXY == BOTTOM or positionTargetXY == BOTTOMRIGHT then
        y = top + height
    end

    -- if positionTargetXY == TOPLEFT or positionTargetXY == LEFT or positionTargetXY == BOTTOMLEFT then x = left
    if positionTargetXY == TOP or positionTargetXY == CENTER or positionTargetXY == BOTTOM then
        x = left + width / 2
    elseif positionTargetXY == TOPRIGHT or positionTargetXY == RIGHT or positionTargetXY == BOTTOMRIGHT then
        x = left + width
    end

    return (zo_round(x / snapSize) * snapSize), (zo_round(y / snapSize) * snapSize)
end

function base.UpdateMoveFrame(_type)
    local moveFrame = _type.MoveFrame
    local targetFrame = _type.Frame
    local onMouseEnter, onMouseExit, onMouseDown, onMouseUp = nil, nil, nil, nil

    if base.Global.IsMoveEnabled and (_type.Name == "Combine" or not _type.IsEmpty and not _type.Saved.IsCombined) then
        moveFrame = base.GetOrCreateMoveFrame(targetFrame, _type)

        onMouseEnter = function(frame)
            frame.MoveFrameUpdateText(frame, true)
        end
        onMouseExit = function(frame)
            frame.MoveFrameUpdateText(frame, false)
        end
        onMouseDown = function(frame)
            frame:SetHandler("OnUpdate", frame.MoveFrameOnUpdate)
        end
        onMouseUp = function(frame)
            local saved = frame.Type.Saved
            frame.MoveFrameOnUpdate(frame)
            frame.MoveFrameUpdateText(frame, false)
            frame:SetHandler("OnUpdate", nil)
            saved.X, saved.Y = base.GetMoveFrameSnapPosition(frame, _type.Saved.Label.PositionTarget, frame.Saved.SnapSize)
        end
    end

    if moveFrame then
        moveFrame:SetHandler("OnMouseEnter", onMouseEnter)
        moveFrame:SetHandler("OnMouseExit", onMouseExit)
        moveFrame:SetHandler("OnMouseDown", onMouseDown)
        moveFrame:SetHandler("OnMouseUp", onMouseUp)
        moveFrame:SetHidden(not base.Global.IsMoveEnabled)
        moveFrame.overlay:SetHidden(not base.Global.IsMoveEnabled)
        moveFrame.labelCenter:SetHidden(not base.Global.IsMoveEnabled)
        moveFrame.labelTopLeft:SetHidden(not base.Global.IsMoveEnabled)
        moveFrame.MoveFrameUpdateText(moveFrame)
        moveFrame.MoveFrameUpdateColor(moveFrame)
        moveFrame:ClearAnchors()
        moveFrame:SetDimensions(targetFrame:GetWidth(), targetFrame:GetHeight())
        moveFrame:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, targetFrame:GetLeft(), targetFrame:GetTop())
    end
end

function base.GetOrCreateMoveFrame(targetFrame, _type)
    if _type.MoveFrame == nil then
        local moveFrameName = _type.Name .. "_MoveFrame"
        local newMoveFrame = base.WM:CreateControlFromVirtual(moveFrameName, GuiRoot, base.Addon.Abbreviation .. "_MoveFrame")

        -- Variable is used to define what savedVariable the Frame refers to.
        newMoveFrame.TargetFrame = targetFrame
        newMoveFrame.Saved = base.Saved
        newMoveFrame.Type = _type

        newMoveFrame["MoveFrameUpdateText"] = function(frame, position)
            local labelTextTopLeft = ""

            if (position) then
                labelTextTopLeft = string.format("%s,%s", base.GetMoveFrameSnapPosition(frame.TargetFrame, _type.Saved.Label.PositionTarget, frame.Saved.SnapSize))
            end

            frame.labelCenter:SetText(string.format("%s,%s", frame:GetWidth(), frame:GetHeight()))
            frame.labelTopLeft:SetText(labelTextTopLeft)
        end
        newMoveFrame["MoveFrameOnUpdate"] = function(frame)
            local x, y = base.GetMoveFrameSnapPosition(frame, _type.Saved.Label.PositionTarget, frame.Saved.SnapSize)
            frame.TargetFrame:ClearAnchors()
            frame.TargetFrame:SetAnchor(_type.Saved.Label.PositionTarget, GuiRoot, TOPLEFT, x, y)
            frame.MoveFrameUpdateText(frame, true)
        end

        newMoveFrame["MoveFrameUpdateColor"] = function(frame)
            frame.overlay:SetCenterColor(0.88, 0.88, 0.88, 0.4)
            frame.overlay:SetEdgeColor(0.88, 0.88, 0.88, 0)
            frame.labelCenter:SetColor(0.9, 0.9, 0.9, 0.9)
            frame.labelTopLeft:SetColor(0.9, 0.9, 0.9, 0.9)
        end

        newMoveFrame:SetAnchorFill(targetFrame)
        newMoveFrame:SetParent(GuiRoot)

        -- -- overlay
        if newMoveFrame.overlay == nil then
            newMoveFrame.overlay = GetControl(moveFrameName .. "BG")
        end

        -- labels
        if newMoveFrame.labelTopLeft == nil or newMoveFrame.labelCenter == nil then
            newMoveFrame.labelTopLeft = GetControl(moveFrameName .. "LabelTopLeft")
            newMoveFrame.labelTopLeft:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
            newMoveFrame.labelTopLeft:SetVerticalAlignment(TEXT_ALIGN_TOP)

            newMoveFrame.labelCenter = GetControl(moveFrameName .. "LabelCenter")
            newMoveFrame.labelCenter:SetHorizontalAlignment(TEXT_ALIGN_CENTER)
            newMoveFrame.labelCenter:SetVerticalAlignment(TEXT_ALIGN_CENTER)
        end

        _type.MoveFrame = newMoveFrame
    end

    return _type.MoveFrame
end