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

-------------------------------------------------------------------------------------------------
-- FUNCTIONS --
-------------------------------------------------------------------------------------------------
function base:GetMoveFrameSnapPosition(frame, positionTargetXY, snapSize)
	base:Verbose("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 == 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 == 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(category)
	base:Debug("UpdateMoveFrame", category)
	local moveFrame = category.Frames.Move
	local targetFrame = category.Frames.Frame
	local onMouseEnter, onMouseExit, onMouseDown, onMouseUp = nil, nil, nil, nil

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

		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.category.Saved
			frame.MoveFrameOnUpdate(frame)
			frame.MoveFrameUpdateText(frame, false)
			frame:SetHandler("OnUpdate", nil)
			saved.Bar.Offset.X, saved.Bar.Offset.Y = base:GetMoveFrameSnapPosition(frame, category.Saved.Label.PositionTarget, frame.Saved.Bar.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, category)
	base:Debug("GetOrCreateMoveFrame", targetFrame, category)
	if category.Frames.Move == nil then
		local moveFrameName = string.format("%s_MoveFrame", category.Name)
		local newMoveFrame = base.WM:CreateControlFromVirtual(moveFrameName, GuiRoot, string.format(texts.FormatAbbreviationLowDash, "MoveFrame"))

		-- Variable is used to define what savedVariable the Frame refers to.
		newMoveFrame.TargetFrame = targetFrame
		newMoveFrame.Saved = base.Saved
		newMoveFrame.category = category
		newMoveFrame["MoveFrameUpdateText"] = function(frame, position)
			local labelTextTopLeft = ""

			if (position) then
				labelTextTopLeft = string.format(texts.Format.Comma, base:GetMoveFrameSnapPosition(frame.TargetFrame, category.Saved.Label.PositionTarget, frame.Saved.Bar.SnapSize))
			end

			frame.labelCenter:SetText(string.format(texts.Format.Comma, frame:GetWidth(), frame:GetHeight()))
			frame.labelTopLeft:SetText(labelTextTopLeft)
		end
		newMoveFrame["MoveFrameOnUpdate"] = function(frame)
			local x, y = base:GetMoveFrameSnapPosition(frame, category.Saved.Label.PositionTarget, frame.Saved.Bar.SnapSize)
			frame.TargetFrame:ClearAnchors()
			frame.TargetFrame:SetAnchor(category.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(string.format("%sBG", moveFrameName))
		end

		-- labels
		if newMoveFrame.labelTopLeft == nil or newMoveFrame.labelCenter == nil then
			newMoveFrame.labelTopLeft = GetControl(string.format("%sLabelTopLeft", moveFrameName))
			newMoveFrame.labelTopLeft:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
			newMoveFrame.labelTopLeft:SetVerticalAlignment(TEXT_ALIGN_TOP)

			newMoveFrame.labelCenter = GetControl(string.format("%sLabelCenter", moveFrameName))
			newMoveFrame.labelCenter:SetHorizontalAlignment(TEXT_ALIGN_CENTER)
			newMoveFrame.labelCenter:SetVerticalAlignment(TEXT_ALIGN_CENTER)
		end

		category.Frames.Move = newMoveFrame
	end

	return category.Frames.Move
end