--[[
Author: Jarth
Filename: CBs_MoveFrame.lua
]] --

-------------------------------------------------------------------------------------------------
-- VARIABLES --
-------------------------------------------------------------------------------------------------
local base = CollectionBars

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

function base.GetMoveFrameSnapPosition(frame, anchorXY)
    local snapSize = frame.Saved.SnapSize
    local x = frame:GetLeft()
    local y = frame:GetTop()

    if anchorXY == BOTTOMRIGHT or anchorXY == TOPRIGHT then
        x = frame:GetRight()
    end
    if anchorXY == BOTTOMRIGHT or anchorXY == BOTTOMLEFT then
        y = frame:GetBottom()
    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.Combine) 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, saved.AnchorXY)
        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 newMoveFrame = base.WM:CreateControlFromVirtual(nil, 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", frame.TargetFrame:GetLeft(), frame.TargetFrame:GetTop())
            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, TOPLEFT)
            frame.TargetFrame:ClearAnchors()
            frame.TargetFrame:SetAnchor(TOPLEFT, 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:SetDimensions(targetFrame:GetWidth(), targetFrame:GetHeight())
        newMoveFrame:SetDrawLayer(4)
        newMoveFrame:SetParent(GuiRoot)
        newMoveFrame:SetMouseEnabled(true)
        newMoveFrame:SetMovable(true)
        newMoveFrame:SetClampedToScreen(true)

        -- overlay
        if newMoveFrame.overlay == nil then
            newMoveFrame.overlay = base.WM:CreateControl(nil, newMoveFrame, CT_BACKDROP)
        end
        newMoveFrame.overlay:SetDrawLevel(2)
        newMoveFrame.overlay:SetAnchorFill(targetFrame)
        newMoveFrame.overlay:SetEdgeTexture("", 8, 1, 0)

        -- label
        local function GetLabel(frameType, alignment)
            local frame = newMoveFrame[frameType]
            if frame == nil then
                frame = base.WM:CreateControl(nil, newMoveFrame, CT_LABEL)
            end
            frame:SetDrawLevel(3)
            frame:SetAnchorFill(targetFrame)
            frame:SetFont("ZoFontWinH5")
            frame:SetHorizontalAlignment(alignment)
            frame:SetVerticalAlignment(alignment)
            return frame
        end
        newMoveFrame.labelCenter = GetLabel("labelCenter", TEXT_ALIGN_CENTER)
        newMoveFrame.labelTopLeft = GetLabel(TEXT_ALIGN_LEFT)
        _type.MoveFrame = newMoveFrame
    end

    return _type.MoveFrame
end