local addonName, addon = ...



--[[-----------------------------------------------------------------------------
Header
-------------------------------------------------------------------------------]]
local partyHeader = CreateFrame('Frame', nil, UIParent, 'SecureHandlerStateTemplate')

partyHeader:SetAttribute('_onstate-group', [[
	self[newstate](self, true)
]])
 
--[[-----------------------------------------------------------------------------
Party Frames
-------------------------------------------------------------------------------]]
local function showPartyMenu(self)
	ToggleDropDownMenu(1, nil, _G['PartyMemberFrame' .. self.id .. 'DropDown'], "cursor", 0, 0)
end

local function showPartyTargetMenu(self)
	ToggleDropDownMenu(1, nil, TargetFrameDropDown, "cursor", 0, 0)
end
 
 
local function CreateUnitButton(name, parent, unit, menufunc)
	local frame = CreateFrame('Button', name, parent, 'SecureUnitButtonTemplate')
	SecureUnitButton_OnLoad(frame, unit, menufunc)
	frame:RegisterForClicks('AnyUp')
	frame:SetScript('OnEnter', UnitFrame_OnEnter)
	frame:SetScript('OnLeave', UnitFrame_OnLeave)

	partyHeader:WrapScript(frame, 'OnAttributeChanged', [[
		if name ~= 'state-exists' then return end
		self[value](self, true)
	]])
	RegisterStateDriver(frame, 'exists', ("[@%s, exists] Show; Hide"):format(unit))

	frame.unit = unit
	return frame
end
 
for id = 1, 4 do
	local unit = 'party' .. id
	local frame = CreateUnitButton(addonName .. "PartyFrame" .. id, partyHeader, unit, showPartyMenu)
	frame.id = id

	-- Pedestal Frame
	frame.PedestalFrame = CreateFrame('Frame', "PartyPedestalFrame" .. id, frame)

	-- Health Bar
	frame.HealthBorder = CreateFrame('Button', nil, frame)
	frame.HealthBar = CreateFrame('StatusBar', "GrimUIPartyFrame" .. id .. "HealthBar", frame)
	frame.HealthNumTxtFrame = CreateFrame('Frame', nil, frame)

	-- Mana Bar
	frame.ManaBorder = CreateFrame('Button', nil, frame)
	frame.ManaBar = CreateFrame('StatusBar', "GrimUIPartyFrame" .. id .. "ManaBar", frame)
	frame.ManaNumTxtFrame = CreateFrame('Frame', nil, frame)

	-- Misc Frames
	frame.InfoTextFrame = CreateFrame('Button', "GrimUIPartyFrame" .. id .. "InfoFrame", frame)
	frame.LetterFrame = CreateFrame('Frame', nil, frame)
	frame.LeaderFrame = CreateFrame('Frame', nil, frame)
	frame.pvpIconFrame = CreateFrame('Frame', nil, frame)
	frame.QTypeIconFrame = CreateFrame('Frame', nil, frame)
	frame.offDeadGhostTxtFrame = CreateFrame('Frame', nil, frame)
	frame.Debuffs = CreateFrame('Frame', "GrimUIPartyFrame" .. id .. "Debuffs", frame)
	
	-- Target Bar
	frame.targetOfFrame = CreateUnitButton(frame:GetName() .. "TargetFrame", frame, unit .. 'target', showPartyTargetMenu)
	frame.targetOfFrame.unitOf = unit

	-- texture creation
	frame.PedestalFrame.texture = frame.PedestalFrame:CreateTexture()
	frame.LeaderFrame.texture = frame.LeaderFrame:CreateTexture()
	frame.pvpIconFrame.texture = frame.pvpIconFrame:CreateTexture()
	frame.QTypeIconFrame.texture = frame.QTypeIconFrame:CreateTexture()
	frame.targetOfFrame.texture = frame:CreateTexture(nil, 'BACKGROUND')

	-- texture SetAllPoints that remain the same for both party styles
	frame.PedestalFrame.texture:SetAllPoints()
	frame.targetOfFrame.texture:SetAllPoints(frame.targetOfFrame)
	frame.LeaderFrame.texture:SetAllPoints()
	frame.pvpIconFrame.texture:SetAllPoints()
	frame.QTypeIconFrame.texture:SetAllPoints()
	
	-- font creation
	frame.HealthBorder.percentHText = frame.HealthBorder:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.ManaBorder.percentMText = frame.ManaBorder:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.InfoTextFrame.NameText = frame.InfoTextFrame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.LetterFrame.LetterHText = frame.LetterFrame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.LetterFrame.LetterMText = frame.LetterFrame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.HealthNumTxtFrame.chnumtxt = frame.HealthNumTxtFrame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.HealthNumTxtFrame.mhnumtxt = frame.HealthNumTxtFrame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.ManaNumTxtFrame.CMNumTxt = frame.ManaNumTxtFrame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.ManaNumTxtFrame.MMNumTxt = frame.ManaNumTxtFrame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.InfoTextFrame.LvlClassText = frame.InfoTextFrame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.DeadOfflineTxt = frame.offDeadGhostTxtFrame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
	frame.targetOfFrame.text = frame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
end

local function Init3DModel(self)

	for pid = 1,4 do
		local unit = 'party' .. pid
		local PartyModelFrame = CreateFrame('PlayerModel', _G["PartyModelFrame" .. pid], _G["PartyPedestalFrame" .. pid])
		PartyModelFrame:RegisterEvent("PARTY_MEMBERS_CHANGED")
		PartyModelFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
		PartyModelFrame:RegisterEvent("UNIT_MODEL_CHANGED", unit)
		PartyModelFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
		PartyModelFrame:RegisterEvent("CINEMATIC_STOP")
		PartyModelFrame:RegisterEvent("PARTY_LEADER_CHANGED")
		
		PartyModelFrame:SetHeight(125)
		PartyModelFrame:SetWidth(85)
		PartyModelFrame:SetPoint("BOTTOM", "PartyPedestalFrame" .. pid, "BOTTOM", 0, -16)
		PartyModelFrame:SetFrameStrata("HIGH")
		PartyModelFrame:SetFrameLevel(8)

		PartyModelFrame:SetScript("OnEvent", function(self)
			PartyModelFrame:SetUnit(unit)
			self:RefreshUnit()
		end)
	end
end
Init3DModel()


--[[-----------------------------------------------------------------------------
Event Handlers
-------------------------------------------------------------------------------]]
local match = string.match

local function UpdateDeadOffline(self, event, unit)
	if match(event, '^UNIT_') then
		if self.unit ~= unit then return end
	else
		unit = self.unit
	end
	if not UnitIsConnected(unit) then
		if UnitIsGhost(unit) then
			self.DeadOfflineTxt:SetText("Ghost\n Offline")
		elseif UnitIsDead(unit) then
			self.DeadOfflineTxt:SetText("Dead\n Offline")
		else
			self.DeadOfflineTxt:SetText("Offline")
		end
	elseif UnitIsGhost(unit) then
		self.DeadOfflineTxt:SetText("Ghost")
	elseif UnitIsDead(unit) then
		self.DeadOfflineTxt:SetText("Dead")
	else
		self.DeadOfflineTxt:SetText("")
	end
end

local function UpdateHealth(self, event, unit)
	if match(event, '^UNIT_') then
		if self.unit ~= unit then return end
	else
		unit = self.unit
	end
	local curHealth, maxHealth = UnitHealth(unit), UnitHealthMax(unit)
	if curHealth and maxHealth and UnitIsConnected(unit) then
		self.HealthBorder.percentHText:SetFormattedText("%s%%", floor(curHealth / maxHealth * 100))
		self.HealthBar:SetMinMaxValues(min(0, curHealth), maxHealth)
		self.HealthBar:SetValue(curHealth) 
		if addon.settings.stylePartyFrames == 2 then 
			self.HealthNumTxtFrame.chnumtxt:SetFormattedText("%s/%s", curHealth, maxHealth)
		else
			self.HealthNumTxtFrame.chnumtxt:SetText(curHealth) 
			self.HealthNumTxtFrame.mhnumtxt:SetText(maxHealth)
		end
	else
		self.HealthBorder.percentHText:SetText("0%")
	end
end

local function UpdateLeader(self)
	--if UnitIsPartyLeader(self.unit) then
		--self.LeaderFrame:Show()
	--else
		--self.LeaderFrame:Hide()
	--end
end

local function UpdateQType(self, unit)
	if UnitGroupRolesAssigned(self.unit) then
		if UnitGroupRolesAssigned(self.unit) == "TANK" then 
			self.QTypeIconFrame.texture:SetTexture([[Interface\AddOns\]] .. addonName .. [[\Media\Tank.png]])
		elseif UnitGroupRolesAssigned(self.unit) == "HEALER" then
			self.QTypeIconFrame.texture:SetTexture([[Interface\AddOns\]] .. addonName .. [[\Media\Heal.png]])
		else 
			self.QTypeIconFrame.texture:SetTexture([[Interface\AddOns\]] .. addonName .. [[\Media\DPS.png]])
		end
		self.QTypeIconFrame:Show()
	else
		self.QTypeIconFrame:Hide()
	end
end

local function UpdateLevelClass(self, event, unit)
	local class = UnitClass(self.unit)
	if class then
		self.InfoTextFrame.LvlClassText:SetFormattedText("%s %s", UnitLevel(self.unit), class)
	else
		self.InfoTextFrame.LvlClassText:SetText("")
	end
end

local function UpdateName(self, event, unit)
	if match(event, '^UNIT_') then
		if self.unit ~= unit then return end
	else
		unit = self.unit
	end
	local name = UnitName(unit)
	if name then
		self = self.InfoTextFrame.NameText
		self:SetText(name)
		if UnitThreatSituation(unit) or UnitAffectingCombat(unit) then
			self:SetTextColor(1, 0, 0, 1)
		else
			self:SetTextColor(1, 1, 1, 1)
		end
	end
end

local function UpdatePower(self, event, unit)
	if match(event, '^UNIT_') then
		if self.unit ~= unit then return end
	else
		unit = self.unit
	end
	local powerType, curPower, maxPower = UnitPowerType(unit)
	if powerType == 0 then
		curPower, maxPower = UnitMana(unit), UnitManaMax(unit)
		self.ManaBar:SetStatusBarColor(0.556, 0.556, 0.921, 1)
	elseif powerType == 1 or powerType == 3 or powerType == 6 or powerType == 2 then
		curPower, maxPower = UnitPower(unit), UnitPowerMax(unit)
		self.ManaBar:SetStatusBarColor(0.656, 0.456, 0.456, 1)
	else
		return
	end

	self.ManaBar:SetMinMaxValues(min(0, curPower), maxPower)
	self.ManaBar:SetValue(curPower)
	if maxPower > 0 then
		self.ManaBorder.percentMText:SetFormattedText("%s%%", floor(curPower / maxPower * 100))
	else
		self.ManaBorder.percentMText:SetText("0%")
	end

	if addon.settings.stylePartyFrames == 2 then 
		self.ManaNumTxtFrame.CMNumTxt:SetFormattedText("%s/%s", curPower, maxPower) 
	else
		self.ManaNumTxtFrame.CMNumTxt:SetText(curPower)
		self.ManaNumTxtFrame.MMNumTxt:SetText(maxPower)
	end
end

local function UpdatePvp(self, event, unit)
	if match(event, '^UNIT_') and self.unit ~= unit then return end
	if UnitIsPVP(self.unit) then
		self.pvpIconFrame:Show()
	else
		self.pvpIconFrame:Hide()
	end
end

local function UpdateTarget(self, event, unit)
	if match(event, '^UNIT_') and self.unitOf ~= unit then return end
	unit = self.unit
	if UnitIsUnit(unit, 'player') then
		self.text:SetText("** YOU **")
	elseif UnitIsUnit(unit, 'target') then
		self.text:SetText("** YOUR TARGET **")
	else
		self.text:SetText(UnitName(unit))
	end
	if UnitIsFriend(unit, 'player') then
		self.texture:SetTexture(0.10, 0.40, 0.10, 1)
	else
		self.texture:SetTexture(0.40, 0.10, 0.10, 1)
	end
end

-- Party Debuff setup 
local function Party1DebuffSetup(self)
	local debuff, debuffCaster, debuffName, _
	local mydeBuffsCount, mydeBuffsPrev, mydeBuffsPrevRow = 0
	local otherdeBuffsCount, otherdeBuffsPrev, otherdeBuffsPrevRow = 0
		for index = 1, 40 do
			debuff = _G['PartyMemberFrame1Debuff' .. index]
			debuffName, _, _, _, _, _, _, debuffCaster = UnitDebuff('party1', index)
			if debuff and debuffName then
				debuff:SetParent(GrimUIPartyFrame1Debuffs)
				debuff:SetScale(1.5)
					if otherdeBuffsCount % 10 ~= 0 then
						debuff:ClearAllPoints()
					debuff:SetPoint('LEFT', otherdeBuffsPrev, 'RIGHT', 1, 0)
				else
					if otherdeBuffsPrevRow then
						debuff:ClearAllPoints()
						debuff:SetPoint('BOTTOM', otherdeBuffsPrevRow, 'TOP', 0, 1)
					else
						debuff:ClearAllPoints()
						debuff:SetPoint('TOPLEFT', 0, 100)
					end
					otherdeBuffsPrevRow = debuff
				end
				otherdeBuffsCount, otherdeBuffsPrev = otherdeBuffsCount + 1, debuff
			else
				break
			end
		end
end

local function Party2DebuffSetup(self)
	local debuff, debuffCaster, debuffName, _
	local mydeBuffsCount, mydeBuffsPrev, mydeBuffsPrevRow = 0
	local otherdeBuffsCount, otherdeBuffsPrev, otherdeBuffsPrevRow = 0
		for index = 1, 40 do
			debuff = _G['PartyMemberFrame2Debuff' .. index]
			debuffName, _, _, _, _, _, _, debuffCaster = UnitDebuff('party2', index)
			if debuff and debuffName then
				debuff:SetParent(GrimUIPartyFrame2Debuffs)
				debuff:SetScale(1.5)
					if otherdeBuffsCount % 10 ~= 0 then
						debuff:ClearAllPoints()
					debuff:SetPoint('LEFT', otherdeBuffsPrev, 'RIGHT', 1, 0)
				else
					if otherdeBuffsPrevRow then
						debuff:ClearAllPoints()
						debuff:SetPoint('BOTTOM', otherdeBuffsPrevRow, 'TOP', 0, 1)
					else
						debuff:ClearAllPoints()
						debuff:SetPoint('TOPLEFT', 0, 100)
					end
					otherdeBuffsPrevRow = debuff
				end
				otherdeBuffsCount, otherdeBuffsPrev = otherdeBuffsCount + 1, debuff
			else
				break
			end
		end
end

local function Party3DebuffSetup(self)
	local debuff, debuffCaster, debuffName, _
	local mydeBuffsCount, mydeBuffsPrev, mydeBuffsPrevRow = 0
	local otherdeBuffsCount, otherdeBuffsPrev, otherdeBuffsPrevRow = 0
		for index = 1, 40 do
			debuff = _G['PartyMemberFrame3Debuff' .. index]
			debuffName, _, _, _, _, _, _, debuffCaster = UnitDebuff('party3', index)
			if debuff and debuffName then
				debuff:SetParent(GrimUIPartyFrame3Debuffs)
				debuff:SetScale(1.5)
					if otherdeBuffsCount % 10 ~= 0 then
						debuff:ClearAllPoints()
					debuff:SetPoint('LEFT', otherdeBuffsPrev, 'RIGHT', 1, 0)
				else
					if otherdeBuffsPrevRow then
						debuff:ClearAllPoints()
						debuff:SetPoint('BOTTOM', otherdeBuffsPrevRow, 'TOP', 0, 1)
					else
						debuff:ClearAllPoints()
						debuff:SetPoint('TOPLEFT', 0, 100)
					end
					otherdeBuffsPrevRow = debuff
				end
				otherdeBuffsCount, otherdeBuffsPrev = otherdeBuffsCount + 1, debuff
			else
				break
			end
		end
end

local function Party4DebuffSetup(self)
	local debuff, debuffCaster, debuffName, _
	local mydeBuffsCount, mydeBuffsPrev, mydeBuffsPrevRow = 0
	local otherdeBuffsCount, otherdeBuffsPrev, otherdeBuffsPrevRow = 0
		for index = 1, 40 do
			debuff = _G['PartyMemberFrame4Debuff' .. index]
			debuffName, _, _, _, _, _, _, debuffCaster = UnitDebuff('party4', index)
			if debuff and debuffName then
				debuff:SetParent(GrimUIPartyFrame4Debuffs)
				debuff:SetScale(1.5)
					if otherdeBuffsCount % 10 ~= 0 then
						debuff:ClearAllPoints()
					debuff:SetPoint('LEFT', otherdeBuffsPrev, 'RIGHT', 1, 0)
				else
					if otherdeBuffsPrevRow then
						debuff:ClearAllPoints()
						debuff:SetPoint('BOTTOM', otherdeBuffsPrevRow, 'TOP', 0, 1)
					else
						debuff:ClearAllPoints()
						debuff:SetPoint('TOPLEFT', 0, 100)
					end
					otherdeBuffsPrevRow = debuff
				end
				otherdeBuffsCount, otherdeBuffsPrev = otherdeBuffsCount + 1, debuff
			else
				break
			end
		end
end

local function UpdateUnit(self, event, unit)
	if match(event, '^UNIT_') then
		if self.unit ~= unit then return end
	else
		unit = self.unit
	end
	if event == 'UNIT_AURA' then
		UpdateHealth(self, "", unit)
		UpdatePower(self, "", unit)
	
	elseif event == 'UNIT_HEALTH' then
		UpdateDeadOffline(self, "", unit)
		UpdateHealth(self, "", unit)
	elseif event == 'UNIT_LEVEL' then
		UpdateHealth(self, "", unit)
		UpdateLevelClass(self, "", unit)
		UpdatePower(self, "", unit)
	else
		UpdateDeadOffline(self, "", unit)
		UpdateHealth(self, "", unit)
		UpdateLeader(self, "", unit)
		UpdateLevelClass(self, "", unit)
		UpdateName(self, "", unit)
		UpdatePower(self, "", unit)
		UpdatePvp(self, "", unit)
		UpdateQType(self, "", unit)
		Party1DebuffSetup(self, "", unit)
		Party2DebuffSetup(self, "", unit)
		Party3DebuffSetup(self, "", unit)
		Party4DebuffSetup(self, "", unit)
	end
end



--[[-----------------------------------------------------------------------------
Position Party Frames
-------------------------------------------------------------------------------]]
function addon:ResetPartyFrames()
	for id = 1, 4 do
			_G[addonName .. "PartyFrame" .. id]:ClearAllPoints()
	end
	
	_G[addonName .. "PartyFrame1"]:SetPoint('BOTTOMRIGHT', addonName .. "PartyFrame2", 'BOTTOMLEFT')
	_G[addonName .. "PartyFrame2"]:SetPoint('BOTTOMRIGHT', GUI_TargetFrame, 'BOTTOMLEFT', -8, 10)
	_G[addonName .. "PartyFrame3"]:SetPoint('BOTTOMLEFT', GUI_TargetFrame, 'BOTTOMRIGHT', 8, 10)
	_G[addonName .. "PartyFrame4"]:SetPoint('BOTTOMLEFT', addonName .. "PartyFrame3", 'BOTTOMRIGHT')
end

function addon:PositionPartyFrames(self)
		addon:UnlockFrame(self)
		self:ClearAllPoints()
		self:SetPoint(unpack(position))
		addon:LockFrame(self)
end

--[[-----------------------------------------------------------------------------
Register/Unregister events on Show/Hide
-------------------------------------------------------------------------------]]
local function OnShow(self)
	local register = addon.RegisterEvents
	register(self, UpdateDeadOffline, 'PARTY_MEMBER_DISABLE', 'PARTY_MEMBER_ENABLE')
	register(self, UpdateLeader, 'PARTY_LEADER_CHANGED', 'ZONE_CHANGED_NEW_AREA')
	register(self, UpdateName, 'UNIT_COMBAT', 'UNIT_FLAGS', 'UNIT_NAME_UPDATE', 'UNIT_THREAT_LIST_UPDATE', 'UNIT_THREAT_SITUATION_UPDATE')
	register(self, UpdatePower, 'UNIT_DISPLAYPOWER', 'UNIT_ENERGY', 'UNIT_MANA', 'UNIT_MAXENERGY', 'UNIT_MAXMANA', 'UNIT_MAXRUNICPOWER', 'UNIT_RAGE', 'UNIT_RUNIC_POWER', 'UNIT_POWER')
	register(self, UpdatePvp, 'UNIT_DYNAMIC_FLAGS', 'UNIT_FACTION')
	register(self, UpdateQType, 'ACTIVE_TALENT_GROUP_CHANGED', 'PARTY_MEMBERS_CHANGED', 'LFG_ROLE_CHECK_UPDATE', 'LFG_ROLE_UPDATE', 'PLAYER_ROLES_ASSIGNED', 'LFG_ROLE_CHECK_ROLE_CHOSEN', 'LFG_UPDATE_RANDOM_INFO')
	register(self, UpdateUnit, 'PARTY_MEMBERS_CHANGED', 'UNIT_AURA', 'UNIT_HEALTH', 'UNIT_LEVEL')
	register(self, Party1DebuffSetup, 'UNIT_AURA')
	register(self, Party2DebuffSetup, 'UNIT_AURA')
	register(self, Party3DebuffSetup, 'UNIT_AURA')
	register(self, Party4DebuffSetup, 'UNIT_AURA')
	addon.RegisterEvent(self, 'UNIT_MAXHEALTH', UpdateHealth)
	if UnitFactionGroup(self.unit) == "Alliance" then    
		self.pvpIconFrame.texture:SetTexture("Interface\\GroupFrame\\UI-Group-PVP-Alliance.blp")
	elseif UnitFactionGroup(self.unit) == "Horde" then
		self.pvpIconFrame.texture:SetTexture("Interface\\GroupFrame\\UI-Group-PVP-Horde.blp")
	end
	UpdateUnit(self, "")
	if not addon.settings.movedFrames.GrimUIPartyFrame1 then
		addon:SafeCall("ResetPartyFrames")
	else
		local position = addon.settings.movedFrames[self:GetName()]
		if position then
			--addon:SafeCall("PositionPartyFrames")
			addon:UnlockFrame(self)
			self:ClearAllPoints()
			self:SetPoint(unpack(position))
			addon:LockFrame(self)
		end
	end
end

local function OnHideTarget(self)
	addon.UnregisterAllEvents(self)
	self.text:SetText("-No Target-")
	self.texture:SetTexture(0, 0, 0, 1)
end

local function OnShowTarget(self)
	addon.RegisterEvents(self, UpdateTarget, 'PLAYER_ENTERING_WORLD', 'PARTY_MEMBERS_CHANGED', 'UNIT_TARGET', 'PLAYER_TARGET_CHANGED')
	UpdateTarget(self, "")
end

for id = 1, 4 do
	local frame = _G[addonName .. "PartyFrame" .. id]
	frame:SetScript('OnHide', addon.UnregisterAllEvents)
	frame:SetScript('OnShow', OnShow)
	frame.targetOfFrame:SetScript('OnHide', OnHideTarget)
	frame.targetOfFrame:SetScript('OnShow', OnShowTarget)
	OnHideTarget(frame.targetOfFrame)
end

--[[-----------------------------------------------------------------------------
ConfigureBlizPartyFrames
-------------------------------------------------------------------------------]]
function addon:ConfigureBlizPartyFrames()
	if addon.settings.hideBlizPartyFrames then
		for id = 1, MAX_PARTY_MEMBERS do
			local frame = _G['PartyMemberFrame' .. id]
			frame:UnregisterAllEvents()
			frame:RegisterEvent('UNIT_AURA')
			addon:HideFrame(frame)
		end
	else
		for id = 1, MAX_PARTY_MEMBERS do
			local frame = _G['PartyMemberFrame' .. id]
			frame:RegisterEvent('IGNORELIST_UPDATE')
			frame:RegisterEvent('MUTELIST_UPDATE')
			frame:RegisterEvent('PARTY_LEADER_CHANGED')
			frame:RegisterEvent('PARTY_LOOT_METHOD_CHANGED')
			frame:RegisterEvent('PARTY_MEMBER_DISABLE')
			frame:RegisterEvent('PARTY_MEMBER_ENABLE')
			frame:RegisterEvent('PARTY_MEMBERS_CHANGED')
			frame:RegisterEvent('READY_CHECK')
			frame:RegisterEvent('READY_CHECK_CONFIRM')
			frame:RegisterEvent('READY_CHECK_FINISHED')
			frame:RegisterEvent('UNIT_AURA')
			frame:RegisterEvent('UNIT_DISPLAYPOWER')
			frame:RegisterEvent('UNIT_ENTERED_VEHICLE')
			frame:RegisterEvent('UNIT_EXITED_VEHICLE')
			frame:RegisterEvent('UNIT_NAME_UPDATE')
			frame:RegisterEvent('UNIT_PET')
			frame:RegisterEvent('UNIT_PORTRAIT_UPDATE')
			frame:RegisterEvent('UNIT_PVP_UPDATE')
			frame:RegisterEvent('VARIABLES_LOADED')
			frame:RegisterEvent('VOICE_START')
			frame:RegisterEvent('VOICE_STATUS_UPDATE')
			frame:RegisterEvent('VOICE_STOP')
			frame.Show = nil
			if UnitExists('party' .. id) then
				frame:Show()
				UnitFrame_OnEvent(frame, 'PARTY_MEMBERS_CHANGED')
			end
		end
	end
end

--[[-----------------------------------------------------------------------------
ConfigurePartyFrames
-------------------------------------------------------------------------------]]
function addon:ConfigurePartyFrames()
	if addon.settings.showPartyFrames then
		local _, instanceType = IsInInstance()
		if not addon.settings.hideGrimPartyInRaid or instanceType == 'arena' then
			RegisterStateDriver(partyHeader, 'group', "[group] Show; Hide")
		else
			RegisterStateDriver(partyHeader, 'group', "[group:raid] Hide; [group:party] Show; Hide")
		end
	else
		RegisterStateDriver(partyHeader, 'group', "Hide")
	end
end

--
--[[-----------------------------------------------------------------------------
Initialize
-------------------------------------------------------------------------------]]

addon.RegisterEvent("PartyFrames-1stInitialize", 'PLAYER_LOGIN', function(self, event)
	addon.UnregisterEvent(self, event)
	
	addon:ConfigureBlizPartyFrames()
	addon:ConfigurePartyFrames()
	addon:StylePartyFrames()
	--addon:StylePartyFrames()

end)

addon.RegisterEvent("PartyFrames-2ndInitialize", 'PLAYER_ENTERING_WORLD', function(self, event)
	addon.UnregisterEvent(self, event)
	--addon:ConfigureBlizPartyFrames()

	--addon:ConfigurePartyFrames()
	
end)

function addon:Init2SafeCallMethod()
	if addon.settings.showPartyFrames then
			if UnitExists("party1") then
				GrimUIPartyFrame1:Hide()
				GrimUIPartyFrame1:Show()
			end
			if UnitExists("party2") then
				GrimUIPartyFrame2:Hide()
				GrimUIPartyFrame2:Show()
			end
			if UnitExists("party3") then
				GrimUIPartyFrame3:Hide()
				GrimUIPartyFrame3:Show()
			end
			if UnitExists("party4") then
				GrimUIPartyFrame4:Hide()
				GrimUIPartyFrame4:Show()
			end
		end
end

addon.RegisterEvent("PartyFrames-3rdInitialize", 'PARTY_MEMBERS_CHANGED', function(self, event) -- for /reload purposes this needs to be here or party frames dont update after a reload.
	addon.UnregisterEvent(self, event)
	
	addon:ConfigurePartyFrames()
	addon:SafeCall("Init2SafeCallMethod")
	
end)

--addon.RegisterEvent("PartyFrames-ArenaInitialize", 'PARTY_MEMBERS_CHANGED', function(self, event) -- HideShow for arenas.
	
	

--end)

--[[-----------------------------------------------------------------------------
Monitor for cvar changes and arena matches
-------------------------------------------------------------------------------]]
local function monitorCVar(self, event, cvar, value)
	if event == 'CVAR_UPDATE' and cvar ~= 'hidePartyInRaid' then return end
	addon:SafeCall("ConfigurePartyFrames")
end
addon.RegisterEvents("PartyFrames-MonitorCVar", monitorCVar, 'CVAR_UPDATE')

-------------------------------------------------------------------------------------------------------------
--######## Party Frame Drop Down Menu Clique Ultimate setup.
-----------------------------------------------------------------------------------------------------
-- Party Frame 1
local showPartyMenu1 = function() 
    ToggleDropDownMenu(1, nil, PartyMemberFrame1DropDown, "cursor", 0, 0) 
end

local function PartyBuffOnEnter1(self)
    UnitFrame_OnEnter(self)
    PartyMemberBuffTooltip:ClearAllPoints()
	PartyMemberBuffTooltip:SetPoint("TOPLEFT", GrimUIPartyFrame1, "TOPLEFT", -10, 20);
    PartyMemberBuffTooltip_Update(self);
    PartyMemberBuffTooltip:SetBackdrop(nil)
end

local function PartyBuffOnEnter2(self)
    UnitFrame_OnEnter(self)
    PartyMemberBuffTooltip:ClearAllPoints()
	PartyMemberBuffTooltip:SetPoint("TOPLEFT", GrimUIPartyFrame2, "TOPLEFT", 0, 20);
    PartyMemberBuffTooltip_Update(self);
    PartyMemberBuffTooltip:SetBackdrop(nil)
end

local function PartyBuffOnEnter3(self)
    UnitFrame_OnEnter(self)
    PartyMemberBuffTooltip:ClearAllPoints()
	PartyMemberBuffTooltip:SetPoint("TOPLEFT", GrimUIPartyFrame3, "TOPLEFT", 0, 20);
    PartyMemberBuffTooltip_Update(self);
    PartyMemberBuffTooltip:SetBackdrop(nil)
end

local function PartyBuffOnEnter4(self)
    UnitFrame_OnEnter(self)
    PartyMemberBuffTooltip:ClearAllPoints()
	PartyMemberBuffTooltip:SetPoint("TOPLEFT", GrimUIPartyFrame4, "TOPLEFT", 0, 20);
    PartyMemberBuffTooltip_Update(self);
    PartyMemberBuffTooltip:SetBackdrop(nil)
end

local function PartyBuffOnLeave(self)
    UnitFrame_OnLeave(self)
    PartyMemberBuffTooltip:Hide();
end

local GUI_Party1Health = CreateFrame('Button', "GUI_Party1Health", GrimUIPartyFrame1, "SecureUnitButtonTemplate")
GUI_Party1Health:SetAllPoints("GrimUIPartyFrame1HealthBar")
GUI_Party1Health:SetFrameStrata("HIGH")
GUI_Party1Health:SetFrameLevel("6")
GUI_Party1Health:RegisterForClicks("AnyUp")
GUI_Party1Health:SetAttribute("unit", "party1")
GUI_Party1Health:SetAttribute("*type1", "target")
GUI_Party1Health.menu = showPartyMenu1
GUI_Party1Health.unit = "party1"
GUI_Party1Health:SetAttribute("*type2", "menu")
GUI_Party1Health:SetScript("OnEnter", PartyBuffOnEnter1)
GUI_Party1Health:SetScript("OnLeave", PartyBuffOnLeave)

local GUI_Party1Mana = CreateFrame('Button', "GUI_Party1Mana", GrimUIPartyFrame1, "SecureUnitButtonTemplate")
GUI_Party1Mana:SetAllPoints("GrimUIPartyFrame1ManaBar")
GUI_Party1Mana:SetFrameStrata("HIGH")
GUI_Party1Mana:SetFrameLevel("6")
GUI_Party1Mana:RegisterForClicks("AnyUp")
GUI_Party1Mana:SetAttribute("unit", "party1")
GUI_Party1Mana:SetAttribute("*type1", "target")
GUI_Party1Mana.menu = showPartyMenu1
GUI_Party1Mana.unit = "party1"
GUI_Party1Mana:SetAttribute("*type2", "menu")
GUI_Party1Mana:SetScript("OnEnter", PartyBuffOnEnter1)
GUI_Party1Mana:SetScript("OnLeave", PartyBuffOnLeave)

local GUI_Party1InfoFrame = CreateFrame('Button', "GUI_Party1InfoFrame", GrimUIPartyFrame1, "SecureUnitButtonTemplate")
GUI_Party1InfoFrame:SetAllPoints("GrimUIPartyFrame1InfoFrame")
GUI_Party1InfoFrame:SetFrameStrata("HIGH")
GUI_Party1InfoFrame:SetFrameLevel("6")
GUI_Party1InfoFrame:RegisterForClicks("AnyUp")
GUI_Party1InfoFrame:SetAttribute("unit", "party1")
GUI_Party1InfoFrame:SetAttribute("*type1", "target")
GUI_Party1InfoFrame.menu = showPartyMenu1
GUI_Party1InfoFrame.unit = "party1"
GUI_Party1InfoFrame:SetAttribute("*type2", "menu")
GUI_Party1InfoFrame:SetScript("OnEnter", PartyBuffOnEnte1)
GUI_Party1InfoFrame:SetScript("OnLeave", PartyBuffOnLeave)


-- Party Frame 2
local showPartyMenu2 = function() 
    ToggleDropDownMenu(1, nil, PartyMemberFrame2DropDown, "cursor", 0, 0) 
end

local GUI_Party2Health = CreateFrame('Button', "GUI_Party2Health", GrimUIPartyFrame2, "SecureUnitButtonTemplate")
GUI_Party2Health:SetAllPoints("GrimUIPartyFrame2HealthBar")
GUI_Party2Health:SetFrameStrata("HIGH")
GUI_Party2Health:SetFrameLevel("6")
GUI_Party2Health:RegisterForClicks("AnyUp")
GUI_Party2Health:SetAttribute("unit", "party2")
GUI_Party2Health:SetAttribute("*type1", "target")
GUI_Party2Health.menu = showPartyMenu2
GUI_Party2Health.unit = "party2"
GUI_Party2Health:SetAttribute("*type2", "menu")
GUI_Party2Health:SetScript("OnEnter", PartyBuffOnEnter2)
GUI_Party2Health:SetScript("OnLeave", PartyBuffOnLeave)

local GUI_Party2Mana = CreateFrame('Button', "GUI_Party2Mana", GrimUIPartyFrame2, "SecureUnitButtonTemplate")
GUI_Party2Mana:SetAllPoints("GrimUIPartyFrame2ManaBar")
GUI_Party2Mana:SetFrameStrata("HIGH")
GUI_Party2Mana:SetFrameLevel("6")
GUI_Party2Mana:RegisterForClicks("AnyUp")
GUI_Party2Mana:SetAttribute("unit", "party2")
GUI_Party2Mana:SetAttribute("*type1", "target")
GUI_Party2Mana.menu = showPartyMenu2
GUI_Party2Mana.unit = "party2"
GUI_Party2Mana:SetAttribute("*type2", "menu")
GUI_Party2Mana:SetScript("OnEnter", PartyBuffOnEnter2)
GUI_Party2Mana:SetScript("OnLeave", PartyBuffOnLeave)

local GUI_Party2InfoFrame = CreateFrame('Button', "GUI_Party2InfoFrame", GrimUIPartyFrame2, "SecureUnitButtonTemplate")
GUI_Party2InfoFrame:SetAllPoints("GrimUIPartyFrame2InfoFrame")
GUI_Party2InfoFrame:SetFrameStrata("HIGH")
GUI_Party2InfoFrame:SetFrameLevel("6")
GUI_Party2InfoFrame:RegisterForClicks("AnyUp")
GUI_Party2InfoFrame:SetAttribute("unit", "party2")
GUI_Party2InfoFrame:SetAttribute("*type1", "target")
GUI_Party2InfoFrame.menu = showPartyMenu2
GUI_Party2InfoFrame.unit = "party2"
GUI_Party2InfoFrame:SetAttribute("*type2", "menu")
GUI_Party2InfoFrame:SetScript("OnEnter", PartyBuffOnEnter2)
GUI_Party2InfoFrame:SetScript("OnLeave", PartyBuffOnLeave)


-- Party Frame 3
local showPartyMenu3 = function() 
    ToggleDropDownMenu(1, nil, PartyMemberFrame3DropDown, "cursor", 0, 0) 
end

local GUI_Party3Health = CreateFrame('Button', "GUI_Party3Health", GrimUIPartyFrame3, "SecureUnitButtonTemplate")
GUI_Party3Health:SetAllPoints("GrimUIPartyFrame3HealthBar")
GUI_Party3Health:SetFrameStrata("HIGH")
GUI_Party3Health:SetFrameLevel("6")
GUI_Party3Health:RegisterForClicks("AnyUp")
GUI_Party3Health:SetAttribute("unit", "party3")
GUI_Party3Health:SetAttribute("*type1", "target")
GUI_Party3Health.menu = showPartyMenu3
GUI_Party3Health.unit = "party3"
GUI_Party3Health:SetAttribute("*type2", "menu")
GUI_Party3Health:SetScript("OnEnter", PartyBuffOnEnter3)
GUI_Party3Health:SetScript("OnLeave", PartyBuffOnLeave)

local GUI_Party3Mana = CreateFrame('Button', "GUI_Party3Mana", GrimUIPartyFrame3, "SecureUnitButtonTemplate")
GUI_Party3Mana:SetAllPoints("GrimUIPartyFrame3ManaBar")
GUI_Party3Mana:SetFrameStrata("HIGH")
GUI_Party3Mana:SetFrameLevel("6")
GUI_Party3Mana:RegisterForClicks("AnyUp")
GUI_Party3Mana:SetAttribute("unit", "party3")
GUI_Party3Mana:SetAttribute("*type1", "target")
GUI_Party3Mana.menu = showPartyMenu3
GUI_Party3Mana.unit = "party3"
GUI_Party3Mana:SetAttribute("*type2", "menu")
GUI_Party3Mana:SetScript("OnEnter", PartyBuffOnEnter3)
GUI_Party3Mana:SetScript("OnLeave", PartyBuffOnLeave)

local GUI_Party3InfoFrame = CreateFrame('Button', "GUI_Party3InfoFrame", GrimUIPartyFrame3, "SecureUnitButtonTemplate")
GUI_Party3InfoFrame:SetAllPoints("GrimUIPartyFrame3InfoFrame")
GUI_Party3InfoFrame:SetFrameStrata("HIGH")
GUI_Party3InfoFrame:SetFrameLevel("6")
GUI_Party3InfoFrame:RegisterForClicks("AnyUp")
GUI_Party3InfoFrame:SetAttribute("unit", "party3")
GUI_Party3InfoFrame:SetAttribute("*type1", "target")
GUI_Party3InfoFrame.menu = showPartyMenu3
GUI_Party3InfoFrame.unit = "party3"
GUI_Party3InfoFrame:SetAttribute("*type2", "menu")
GUI_Party3InfoFrame:SetScript("OnEnter", PartyBuffOnEnter3)
GUI_Party3InfoFrame:SetScript("OnLeave", PartyBuffOnLeave)


-- Party Frame 4
local showPartyMenu4 = function() 
    ToggleDropDownMenu(1, nil, PartyMemberFrame4DropDown, "cursor", 0, 0) 
end

local GUI_Party4Health = CreateFrame('Button', "GUI_Party4Health", GrimUIPartyFrame4, "SecureUnitButtonTemplate")
GUI_Party4Health:SetAllPoints("GrimUIPartyFrame4HealthBar")
GUI_Party4Health:SetFrameStrata("HIGH")
GUI_Party4Health:SetFrameLevel("6")
GUI_Party4Health:RegisterForClicks("AnyUp")
GUI_Party4Health:SetAttribute("unit", "party4")
GUI_Party4Health:SetAttribute("*type1", "target")
GUI_Party4Health.menu = showPartyMenu4
GUI_Party4Health.unit = "party4"
GUI_Party4Health:SetAttribute("*type2", "menu")
GUI_Party4Health:SetScript("OnEnter", PartyBuffOnEnter4)
GUI_Party4Health:SetScript("OnLeave", PartyBuffOnLeave)

local GUI_Party4Mana = CreateFrame('Button', "GUI_Party4Mana", GrimUIPartyFrame4, "SecureUnitButtonTemplate")
GUI_Party4Mana:SetAllPoints("GrimUIPartyFrame4ManaBar")
GUI_Party4Mana:SetFrameStrata("HIGH")
GUI_Party4Mana:SetFrameLevel("6")
GUI_Party4Mana:RegisterForClicks("AnyUp")
GUI_Party4Mana:SetAttribute("unit", "party4")
GUI_Party4Mana:SetAttribute("*type1", "target")
GUI_Party4Mana.menu = showPartyMenu4
GUI_Party4Mana.unit = "party4"
GUI_Party4Mana:SetAttribute("*type2", "menu")
GUI_Party4Mana:SetScript("OnEnter", PartyBuffOnEnter4)
GUI_Party4Mana:SetScript("OnLeave", PartyBuffOnLeave)

local GUI_Party4InfoFrame = CreateFrame('Button', "GUI_Party4InfoFrame", GrimUIPartyFrame4, "SecureUnitButtonTemplate")
GUI_Party4InfoFrame:SetAllPoints("GrimUIPartyFrame4InfoFrame")
GUI_Party4InfoFrame:SetFrameStrata("HIGH")
GUI_Party4InfoFrame:SetFrameLevel("6")
GUI_Party4InfoFrame:RegisterForClicks("AnyUp")
GUI_Party4InfoFrame:SetAttribute("unit", "party4")
GUI_Party4InfoFrame:SetAttribute("*type1", "target")
GUI_Party4InfoFrame.menu = showPartyMenu4
GUI_Party4InfoFrame.unit = "party4"
GUI_Party4InfoFrame:SetAttribute("*type2", "menu")
GUI_Party4InfoFrame:SetScript("OnEnter", PartyBuffOnEnter4)
GUI_Party4InfoFrame:SetScript("OnLeave", PartyBuffOnLeave)







--[[-----------------------------------------------------------------------------
Clique support
-------------------------------------------------------------------------------]]
ClickCastFrames = ClickCastFrames or {}
ClickCastFrames[GUI_Party1Health] = true
ClickCastFrames[GUI_Party1Mana] = true
ClickCastFrames[GUI_Party1InfoFrame] = true
ClickCastFrames[GUI_Party2Health] = true
ClickCastFrames[GUI_Party2Mana] = true
ClickCastFrames[GUI_Party2InfoFrame] = true
ClickCastFrames[GUI_Party3Health] = true
ClickCastFrames[GUI_Party3Mana] = true
ClickCastFrames[GUI_Party3InfoFrame] = true
ClickCastFrames[GUI_Party4Health] = true
ClickCastFrames[GUI_Party4Mana] = true
ClickCastFrames[GUI_Party4InfoFrame] = true