local IRF2 = InvenRaidFrames2

local _G = _G
local abs = _G.math.abs
local min = _G.math.min
local max = _G.math.max
local UnitIsPlayer = _G.UnitIsPlayer
local UnitExists = _G.UnitExists
local UnitGUID = _G.UnitGUID
local UnitName = _G.UnitName
local UnitInVehicle = _G.UnitInVehicle
local IsAltKeyDown = _G.IsAltKeyDown
local IsMouseButtonDown = _G.IsMouseButtonDown

local offset = 5
local startPoint = { ["좌측 상단"] = { "TOPLEFT", -offset, offset }, ["우측 상단"] = { "TOPRIGHT", offset, offset }, ["좌측 하단"] = { "BOTTOMLEFT", -offset, -offset }, ["우측 하단"] = { "BOTTOMRIGHT", offset, -offset } }
local widthPoint = { ["좌측 상단"] = "GetLeft", ["우측 상단"] = "GetRight", ["좌측 하단"] = "GetLeft", ["우측 하단"] = "GetRight" }
local heightPoint = { ["좌측 상단"] = "GetTop", ["우측 상단"] = "GetTop", ["좌측 하단"] = "GetBottom", ["우측 하단"] = "GetBottom" }
local rWidthPoint = { ["좌측 상단"] = "GetRight", ["우측 상단"] = "GetLeft", ["좌측 하단"] = "GetRight", ["우측 하단"] = "GetLeft" }
local rHeightPoint = { ["좌측 상단"] = "GetBottom", ["우측 상단"] = "GetBottom", ["좌측 하단"] = "GetTop", ["우측 하단"] = "GetTop" }
local minMaxFunction = { ["좌측 상단"] = { max, min }, ["우측 상단"] = { min, min }, ["좌측 하단"] = { max, max }, ["우측 하단"] = { min, max } }

function IRF2:CreatePetGroup()
	-- 소환수 유니트 그룹 생성
	if not self.group.pet then
		self.petAnchor = CreateFrame("Frame", "InvenRaidFrames2PetAnchor", UIParent)
		self.petAnchor:SetFrameStrata(self.db.strata)
		self.petAnchor:SetFrameLevel(1)
		self.petAnchor:EnableMouse(true)
		self.petAnchor:SetMovable(true)
		self.petAnchor:SetUserPlaced(nil)
		self.petAnchor:SetClampedToScreen(true)
		self.petAnchor:RegisterForDrag("LeftButton")
		self.petAnchor:SetWidth(0.1)
		self.petAnchor:SetHeight(0.1)
		self.petAnchor:SetScale(self.db.pet.scale)
		self.petAnchor:ClearAllPoints()
		if self.db.pet.pos then
			self.petAnchor:SetPoint(self.db.pet.pos[1], UIParent, self.db.pet.pos[1], self.db.pet.pos[2], self.db.pet.pos[3])
		else
			self.petAnchor:SetPoint("CENTER", UIParent, "CENTER")
		end
		self.petAnchor:SetScript("OnDragStart", function()
			if not IRF2.db.lock then
				IRF2.petAnchor.isMoving = true
				IRF2.petAnchor:StartMoving()
				IRF2.petAnchor.MouseUpCheck:Show()
			end
		end)
		self.petAnchor:SetScript("OnDragStop", function()
			if IRF2.petAnchor.isMoving then
				IRF2.petAnchor.MouseUpCheck:Hide()
				IRF2.petAnchor:StopMovingOrSizing()
				IRF2.db.pet.pos = IRF2.db.pet.pos or {}
				IRF2.db.pet.pos[1], _, _, IRF2.db.pet.pos[2], IRF2.db.pet.pos[3] = IRF2.petAnchor:GetPoint()
				IRF2.petAnchor:SetUserPlaced(nil)
			end
		end)
		self.petAnchor.MouseUpCheck = CreateFrame("Frame", nil, self.petAnchor)
		self.petAnchor.MouseUpCheck:Hide()
		self.petAnchor.MouseUpCheck:SetScript("OnShow", function(self)
			self.buttonDown = IsMouseButtonDown()
		end)
		self.petAnchor.MouseUpCheck:SetScript("OnUpdate", function(self)
			if self.buttonDown ~= IsMouseButtonDown() then
				self.buttonDown = IsMouseButtonDown()
				if not self.buttonDown then
					self:Hide()
					self:GetParent():GetScript("OnDragStop")()
				end
			end
		end)
		self.group.pet = CreateFrame("Frame", "InvenRaidFrames2GroupPet", UIParent, "SecureGroupPetHeaderTemplate")
		self.group.pet:SetFrameStrata(self.db.strata)
		self.group.pet:SetFrameLevel(2)
		self.group.pet:Hide()
		self.group.pet:ClearAllPoints()
		self.group.pet.initialConfigFunction = self.group[0].initialConfigFunction
		self.group.pet.SetManyAttributes = self.group[0].SetManyAttributes
		self.group.pet.SetSafeAttribute = self.group[0].SetSafeAttribute
		self.group.pet.GetNumChild = self.group[0].GetNumChild
		self.group.pet.PreCreateChildren = self.group[0].PreCreateChildren
		self.group.pet.RosterUpdate = petRosterUpdate
		self.group.pet:SetScale(self.db.pet.scale)
		self.group.pet:SetManyAttributes("template", "SecureUnitButtonTemplate", "sortMethod", "INDEX", "maxColumns", 25)
		self.group.pet:PreCreateChildren(25)
		self:SetPetGroupOrder()
		self:UpdatePetClampRectInsets()
		self:RegisterEvent("UNIT_PET")
	end
end

local a_columnAnchorPoint, a_point, a_xoffset, a_yoffset

local isParty, showSolo, showParty, showRaid

function IRF2:SetPetGroupOrder()
	if InvenRaidFrames2CharDB.usePet and self:RaidFrameIsShown() then
		self.group.pet:Hide()
		isParty = GetNumPartyMembers() > 0
		isRaid = GetNumRaidMembers() > 0
		if self.db.shown == "항상" then
			if isRaid then
				showSolo, showParty, showRaid = true, false, true
			elseif isParty then
				showSolo, showParty, showRaid = true, true, false
			else
				showSolo, showParty, showRaid = true, true, false
			end
		elseif self.db.shown == "파티" then
			if isRaid then
				showSolo, showParty, showRaid = false, false, true
			elseif isParty then
				showSolo, showParty, showRaid = false, true, false
			else
				showSolo, showParty, showRaid = false, false, false
			end
		elseif self.db.shown == "공격대" then
			if isRaid then
				showSolo, showParty, showRaid = false, false, true
			elseif isParty then
				showSolo, showParty, showRaid = false, false, false
			else
				showSolo, showParty, showRaid = false, false, false
			end
		end
		self.group.pet:SetManyAttributes("showSolo", showSolo, "showPlayer", showParty, "showParty", showParty, "showRaid", showRaid, "groupFilter", showRaid and "1,2,3,4,5,6,7,8" or nil)
		self.group.pet:ClearAllPoints()
		if self.db.pet.anchor == "좌측 상단" then
			self.group.pet:SetPoint("TOPLEFT", self.petAnchor, "TOPLEFT")
			if self.db.pet.point == "가로" then
				a_columnAnchorPoint, a_point, a_xoffset, a_yoffset = "TOP", "LEFT", self.db.layout.offset, -self.db.layout.offset
			else
				a_columnAnchorPoint, a_point, a_xoffset, a_yoffset = "LEFT", "TOP", self.db.layout.offset, -self.db.layout.offset
			end
		elseif self.db.pet.anchor == "우측 상단" then
			self.group.pet:SetPoint("TOPRIGHT", self.petAnchor, "TOPRIGHT")
			if self.db.pet.point == "가로" then
				a_columnAnchorPoint, a_point, a_xoffset, a_yoffset = "TOP", "RIGHT", -self.db.layout.offset, -self.db.layout.offset
			else
				a_columnAnchorPoint, a_point, a_xoffset, a_yoffset = "RIGHT", "TOP", -self.db.layout.offset, -self.db.layout.offset
			end
		elseif self.db.pet.anchor == "좌측 하단" then
			self.group.pet:SetPoint("BOTTOMLEFT", self.petAnchor, "BOTTOMLEFT")
			if self.db.pet.point == "가로" then
				a_columnAnchorPoint, a_point, a_xoffset, a_yoffset = "BOTTOM", "LEFT", self.db.layout.offset, self.db.layout.offset
			else
				a_columnAnchorPoint, a_point, a_xoffset, a_yoffset = "LEFT", "BOTTOM", self.db.layout.offset, self.db.layout.offset
			end
		elseif self.db.pet.anchor == "우측 하단" then
			self.group.pet:SetPoint("BOTTOMRIGHT", self.petAnchor, "BOTTOMRIGHT")
			if self.db.pet.point == "가로" then
				a_columnAnchorPoint, a_point, a_xoffset, a_yoffset = "BOTTOM", "RIGHT", -self.db.layout.offset, self.db.layout.offset
			else
				a_columnAnchorPoint, a_point, a_xoffset, a_yoffset = "RIGHT", "BOTTOM", -self.db.layout.offset, self.db.layout.offset
			end
		end
		self.group.pet:SetManyAttributes("unitsPerColumn", self.db.pet.column, "point", a_point, "columnAnchorPoint", a_columnAnchorPoint, "columnSpacing", self.db.layout.offset, "xOffset", a_xoffset, "yOffset", a_yoffset)
		self.group.pet:Show()
		if self.borderFramePet then
			self:CallbackTimer("PetUpdate", 0.1, self, "PetRosterUpdate")
		end
	elseif self.group.pet then
		self.group.pet:Hide()
		if self.borderFramePet then
			self.borderFramePet:Hide()
		end
	end
end

function IRF2:UpdatePetClampRectInsets()
	if self.db.pet.anchor == "좌측 상단" then
		self.petAnchor:SetClampRectInsets(-2, 2 + self.db.layout.width, 2, -2 - self.db.layout.height)
	elseif self.db.pet.anchor == "좌측 하단" then
		self.petAnchor:SetClampRectInsets(-2, 2 + self.db.layout.width, 2 + self.db.layout.height, 2)
	elseif self.db.pet.anchor == "우측 상단" then
		self.petAnchor:SetClampRectInsets(-2 - self.db.layout.width, 2, 2, -2 - self.db.layout.height)
	elseif self.db.pet.anchor == "우측 하단" then
		self.petAnchor:SetClampRectInsets(-2 - self.db.layout.width, 2, 2 + self.db.layout.height, 2)
	end
end

function IRF2:UpdateAllPetUnits()
	for _, object in pairs(self.units) do
		if object:GetParent() == self.group.pet then
			object:PLAYER_ENTERING_WORLD()
		end
	end
end

function IRF2:UNIT_PET()
	if self.group.pet then
		self:CallbackTimer("PetUpdate", 0.25, self, "PetRosterUpdate")
	end
end

local partyMembers, groupMembers, petNum, prevNum, wp, hp, width, height, frame

local function CreateBorder()
	IRF2.borderFramePet = CreateFrame("Frame", nil, UIParent)
	IRF2.borderFramePet:SetFrameStrata(IRF2.db.strata)
	IRF2.borderFramePet:SetFrameLevel(1)
	IRF2.borderFramePet:SetBackdrop({
		bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
		edgeFile = "Interface\\Addons\\InvenRaidFrames2\\Texture\\Border",
		tile = true, tileSize = 16, edgeSize = 16,
		insets = { left = 2, right = 2, top = 2, bottom = 2 }
	})
	IRF2.borderFramePet:SetScale(IRF2.db.pet.scale)
	IRF2.borderFramePet:EnableMouse(true)
	IRF2.borderFramePet:RegisterForDrag("LeftButton")
	IRF2.borderFramePet:SetBackdropColor(unpack(IRF2.db.border.backdrop))
	IRF2.borderFramePet:SetBackdropBorderColor(unpack(IRF2.db.border.border))
	IRF2.borderFramePet:EnableMouse(true)
	IRF2.borderFramePet:RegisterForDrag("LeftButton")
	IRF2.borderFramePet:SetScript("OnDragStart", IRF2.petAnchor:GetScript("OnDragStart"))
	IRF2.borderFramePet:SetScript("OnDragStop", IRF2.petAnchor:GetScript("OnDragStop"))
end

function IRF2:BorderPet()
	if not self:RaidFrameIsShown() or not self.db.run or not InvenRaidFrames2CharDB.usePet then
		if self.borderFramePet then
			self.borderFramePet:Hide()
		end
		return
	end
	if not self.borderFramePet then
		CreateBorder()
	end
	if self.db.border.show then
		self.borderFramePet:SetAlpha(1)
	else
		self.borderFramePet:SetAlpha(0)
	end
	petNum = self.group.pet:GetNumChild()
	if petNum > 0 then
		self.borderFramePet:ClearAllPoints()
		self.borderFramePet:SetPoint(startPoint[self.db.pet.anchor][1], self.group.pet, startPoint[self.db.pet.anchor][1], startPoint[self.db.pet.anchor][2], startPoint[self.db.pet.anchor][3])
		wp, hp = self.group.pet[widthPoint[self.db.pet.anchor]](self.group.pet), self.group.pet[heightPoint[self.db.pet.anchor]](self.group.pet)
		for i =1, petNum do
			frame = self.group.pet.children[i]
			if frame:GetTop() then
				wp = minMaxFunction[self.db.pet.anchor][1](wp, frame[rWidthPoint[self.db.pet.anchor]](frame))
				hp = minMaxFunction[self.db.pet.anchor][2](hp, frame[rHeightPoint[self.db.pet.anchor]](frame))
			else
				self:CallbackTimer("PetBorder", 0.1, self, "BorderPet")
				return
			end
		end
		width = ceil(abs(wp - self.group.pet[widthPoint[self.db.pet.anchor]](self.group.pet)) + offset * 2)
		height = ceil(abs(hp - self.group.pet[heightPoint[self.db.pet.anchor]](self.group.pet)) + offset * 2)
		if width > 10 and height > 22 then
			self.borderFramePet:SetWidth(width)
			self.borderFramePet:SetHeight(height)
			self.borderFramePet:Show()
		else
			self.borderFramePet:Hide()
			self:CallbackTimer("PetBorder", 0.1, self, "BorderPet")
		end
	elseif self.borderFramePet then
		self.borderFramePet:Hide()
	end
end

function IRF2:PetRosterUpdate()
	if InvenRaidFrames2CharDB.usePet then
		self:UpdateAllPetUnits()
		self:BorderPet()
	end
end