sUnitFrames_enable = true;
sUnitFrames_info = {name="SMART.UNIT.FRAME",ver="1.7.0.beta"}

SMART_BUFFDEBUFF_POSITION = {xOfs=5,yOfs=32};

CreateFrame("Frame","SmartUnitFrame",UIParent);
SmartUnitFrame:RegisterEvent("VARIABLES_LOADED");
SmartUnitFrame:RegisterEvent("PLAYER_REGEN_ENABLED");
-- SmartUnitFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
SmartUnitFrame:SetScript("OnEvent",function() SmartUnitFrame_StartUp(event) end);

CreateFrame("Button","SmartPlayerRelocator",PlayerFrame);
SmartPlayerRelocator:SetFrameLevel(PlayerFrame:GetFrameLevel()+2);
SmartPlayerRelocator:SetFrameStrata("HIGH");
SmartPlayerRelocator:SetPoint("CENTER",PlayerName,"CENTER");
SmartPlayerRelocator:SetWidth(TargetFrameNameBackground:GetWidth());
SmartPlayerRelocator:SetHeight(TargetFrameNameBackground:GetHeight());
SmartPlayerRelocator:SetHitRectInsets(0,0,0,0);
SmartPlayerRelocator:SetScript("OnEnter",function()	SmartUnitFrame_DragEnter() end);
SmartPlayerRelocator:SetScript("OnLeave",function()	SmartUnitFrame_DragLeave() end);
SmartPlayerRelocator:SetScript("OnMouseDown",function()	SmartUnitFrame_DragStart(arg1) end);
SmartPlayerRelocator:SetScript("OnMouseUp",function() SmartUnitFrame_DragStop() end);

CreateFrame("Button","SmartTargetRelocator",TargetFrame);
SmartTargetRelocator:SetFrameLevel(TargetFrame:GetFrameLevel()+2);
SmartTargetRelocator:SetFrameStrata("HIGH");
SmartTargetRelocator:SetPoint("TOPLEFT",TargetFrameNameBackground,"TOPLEFT");
SmartTargetRelocator:SetPoint("BOTTOMRIGHT",TargetFrameNameBackground,"BOTTOMRIGHT");
SmartTargetRelocator:SetHitRectInsets(0,0,0,0);
SmartTargetRelocator:SetScript("OnEnter",function()	SmartUnitFrame_DragEnter() end);
SmartTargetRelocator:SetScript("OnLeave",function()	SmartUnitFrame_DragLeave() end);
SmartTargetRelocator:SetScript("OnMouseDown",function()	SmartUnitFrame_DragStart(arg1) end);
SmartTargetRelocator:SetScript("OnMouseUp",function() SmartUnitFrame_DragStop() end);

for id=1, 4 do
	CreateFrame("Button", "SmartParty"..id.."Relocator",getglobal("PartyMemberFrame"..id));
	getglobal("SmartParty"..id.."Relocator"):SetFrameLevel(getglobal("PartyMemberFrame"..id):GetFrameLevel()+2);
	getglobal("SmartParty"..id.."Relocator"):SetFrameStrata("HIGH");
	getglobal("SmartParty"..id.."Relocator"):SetPoint("TOPLEFT",getglobal("PartyMemberFrame"..id.."Name"),"TOPLEFT");
	getglobal("SmartParty"..id.."Relocator"):SetPoint("BOTTOMRIGHT",getglobal("PartyMemberFrame"..id.."Name"),"BOTTOMRIGHT");
	getglobal("SmartParty"..id.."Relocator"):SetHitRectInsets(0,0,0,0);
	getglobal("SmartParty"..id.."Relocator"):SetScript("OnEnter",function() SmartUnitFrame_DragEnter() end);
	getglobal("SmartParty"..id.."Relocator"):SetScript("OnLeave",function() SmartUnitFrame_DragLeave() end);
	getglobal("SmartParty"..id.."Relocator"):SetScript("OnMouseDown",function() SmartUnitFrame_DragStart(arg1) end);
	getglobal("SmartParty"..id.."Relocator"):SetScript("OnMouseUp",function() SmartUnitFrame_DragStop() end);
end

-- CHECK ADDON_BLOCKED
-- local f = CreateFrame("Frame","SmartAddonsBlockCheckTestFrame");
-- f:SetScript("OnEvent",function() DEFAULT_CHAT_FRAME:AddMessage("BLOCKED: "..tostring(arg1)..", "..tostring(arg2)) end);
-- f:RegisterEvent("ADDON_ACTION_BLOCKED");

function SmartUnitFrame_StartUp(event)
	if (event == "VARIABLES_LOADED") then
		SmartUnitFrame_MovableCheck();
		SlashCmdList["SUF"] = SmartUnitFrame_CmdHandler;
		SLASH_SUF1 = "/suf";
		UnitFrame_Update = SmartUnitFrame_Update;
		TargetFrame_OnUpdate = NewTargetFrame_OnUpdate;
		TargetofTarget_Update = NewTargetofTarget_Update;
		TargetofTarget_OnUpdate = NewTargetofTarget_OnUpdate;
		DEFAULT_CHAT_FRAME:AddMessage(sUnitFrames_info.name.." v"..sUnitFrames_info.ver.." (명령어 : /suf)",1,0.82,0);
		if SCONFIG_ENABLE then
			DEFAULT_CHAT_FRAME:AddMessage("SMART.CONFIG.UI Loaded",1,1,1);
		end
		if SMART_BUFFDEBUFF_ENABLE then
			DEFAULT_CHAT_FRAME:AddMessage("SMART.BUFF/DEBUFF Loaded",1,1,1);
		end
		if SMART_FOCUS_ENABLE then
			DEFAULT_CHAT_FRAME:AddMessage("SMART.FOCUS Loaded",1,1,1);
		end
		if SMART_SKIN_ENABLE then
			DEFAULT_CHAT_FRAME:AddMessage("SMART.SKIN - "..SMART_SKIN_NAME.." Loaded",1,1,1);
		end
		if SMART_SETSCALE_ENABLE then
			DEFAULT_CHAT_FRAME:AddMessage("SMART.SET.SCALE Loaded",1,1,1);
		end
		if SMART_GROUPICON_ENABLE then
			DEFAULT_CHAT_FRAME:AddMessage("SMART.GROUP.ICON Loaded",1,1,1);
		end
		if SMART_CLASSICON_ENABLE then
			DEFAULT_CHAT_FRAME:AddMessage("SMART.CLASS.ICON Loaded",1,1,1);
		end
		if SMART_PVPICON_ENABLE then
			DEFAULT_CHAT_FRAME:AddMessage("SMART.PVP.ICON Loaded",1,1,1);
		end
		if not SMART_BUFFDEBUFF_ENABLE then
			TargetDebuffButton_Update = SmartUnitFrame_TargetDebuffButton_Update;
		end
	elseif (event == "PLAYER_REGEN_ENABLED") then
		if UnitInParty("player") or UnitInRaid("player") then
			if GetNumPartyMembers() > 0 then
				RaidOptionsFrame_UpdatePartyFrames();
			end
		end
	end
end

function SmartUnitFrame_TargetDebuffButton_Update()
	local button;
	local name, rank, icon, count, duration, timeLeft;
	local buffCount;
	local numBuffs = 0;
	local largeBuffList = {};
	local playerIsTarget = UnitIsUnit("player", "target");
	local cooldown, startCooldownTime;
	for i=1, MAX_TARGET_BUFFS do
		name, rank, icon, count, duration, timeLeft = UnitBuff("target", i);
		button = getglobal("TargetFrameBuff"..i);
		if ( not button ) then
			if ( not icon ) then
				break;
			else
				button = CreateFrame("Button", "TargetFrameBuff"..i, TargetFrame, "TargetBuffButtonTemplate");
			end
		end
		
		if ( icon ) then
			getglobal("TargetFrameBuff"..i.."Icon"):SetTexture(icon);
			buffCount = getglobal("TargetFrameBuff"..i.."Count");
			button:Show();
			if ( count > 1 ) then
				buffCount:SetText(count);
				buffCount:Show();
			else
				buffCount:Hide();
			end
			
			-- Handle cooldowns
			cooldown = getglobal("TargetFrameBuff"..i.."Cooldown");
			if ( duration ) then
				if ( duration > 0 ) then
					cooldown:Show();
					startCooldownTime = GetTime()-(duration-timeLeft);
					CooldownFrame_SetTimer(cooldown, startCooldownTime, duration, 1);
				else
					cooldown:Hide();
				end
				
				-- Set the buff to be big if the buff is cast by the player and the target is not the player
				if ( not playerIsTarget ) then
					largeBuffList[i] = 1;
				end
			else
				cooldown:Hide();
			end

			button.id = i;
			numBuffs = numBuffs + 1; 
			button:ClearAllPoints();
		else
			button:Hide();
		end
	end

	local debuffType, color;
	local debuffCount;
	local numDebuffs = 0;
	local largeDebuffList = {};
	for i=1, MAX_TARGET_DEBUFFS do
		local debuffBorder = getglobal("TargetFrameDebuff"..i.."Border");
		name, rank, icon, count, debuffType, duration, timeLeft = UnitDebuff("target", i);
		button = getglobal("TargetFrameDebuff"..i);
		if ( not button ) then
			if ( not icon ) then
				break;
			else
				button = CreateFrame("Button", "TargetFrameDebuff"..i, TargetFrame, "TargetDebuffButtonTemplate");
				debuffBorder = getglobal("TargetFrameDebuff"..i.."Border");
			end
		end
		if ( icon ) then
			getglobal("TargetFrameDebuff"..i.."Icon"):SetTexture(icon);
			debuffCount = getglobal("TargetFrameDebuff"..i.."Count");
			if ( debuffType ) then
				color = DebuffTypeColor[debuffType];
			else
				color = DebuffTypeColor["none"];
			end
			if ( count > 1 ) then
				debuffCount:SetText(count);
				debuffCount:Show();
			else
				debuffCount:Hide();
			end

			-- Handle cooldowns
			cooldown = getglobal("TargetFrameDebuff"..i.."Cooldown");
			if ( duration  ) then
				if ( duration > 0 ) then
					cooldown:Show();
					startCooldownTime = GetTime()-(duration-timeLeft);
					CooldownFrame_SetTimer(cooldown, startCooldownTime, duration, 1);
				else
					cooldown:Hide();
				end
				-- Set the buff to be big if the buff is cast by the player
				largeDebuffList[i] = 1;
			else
				cooldown:Hide();
			end
			
			debuffBorder:SetVertexColor(color.r, color.g, color.b);
			button:Show();
			numDebuffs = numDebuffs + 1;
			button:ClearAllPoints();
		else
			button:Hide();
		end
		button.id = i;
	end
	
	-- Figure out general information that affects buff sizing and positioning
	local numFirstRowBuffs;
	local buffSize = LARGE_BUFF_SIZE;
	local buffFrameSize = LARGE_BUFF_FRAME_SIZE;
	if ( TargetofTargetFrame:IsShown() ) then
		numFirstRowBuffs = 5;
	else
		numFirstRowBuffs = 6;
	end
	if ( getn(largeBuffList) > 0 or getn(largeDebuffList) > 0 ) then
		numFirstRowBuffs = numFirstRowBuffs - 1;
	end
	-- Shrink the buffs if there are too many of them
	if ( (numBuffs >= numFirstRowBuffs) or (numDebuffs >= numFirstRowBuffs) ) then
		buffSize = SMALL_BUFF_SIZE;
		buffFrameSize = SMALL_BUFF_FRAME_SIZE;
	end
		
	-- Reset number of buff rows
	TargetFrame.buffRows = 0;
	-- Position buffs
	local size;
	local previousWasPlayerCast;
	local offset;
	for i=1, numBuffs do
		if ( largeBuffList[i] ) then
			size = LARGE_BUFF_SIZE;
			offset = 3;
			previousWasPlayerCast = 1;
		else
			size = buffSize;
			offset = 3;
			if ( previousWasPlayerCast ) then
				offset = 6;
				previousWasPlayerCast = nil;
			end
		end
		TargetFrame_UpdateBuffAnchor("TargetFrameBuff", i, numFirstRowBuffs, numDebuffs, size, offset, TargetofTargetFrame:IsShown());
	end
	-- Position debuffs
	previousWasPlayerCast = nil;
	for i=1, numDebuffs do
		if ( largeDebuffList[i] ) then
			size = LARGE_BUFF_SIZE;
			offset = 4;
			previousWasPlayerCast = 1;
		else
			size = buffSize;
			offset = 4;
			if ( previousWasPlayerCast ) then
				offset = 6;
				previousWasPlayerCast = nil;
			end
		end
		TargetFrame_UpdateDebuffAnchor("TargetFrameDebuff", i, numFirstRowBuffs, numBuffs, size, offset, TargetofTargetFrame:IsShown());
	end

	-- update the spell bar position
	Target_Spellbar_AdjustPosition();
end

function SmartUnitFrame_Update()
	local nameServer;
	if (this.unit == "party1") or (this.unit == "party2") or (this.unit == "party3") or (this.unit == "party4") then
		nameServer = SMART_PARTY_Config.namewithserver;
	end
	this.name:SetText(GetUnitName(this.unit,nameServer));
	SetPortraitTexture(this.portrait, this.unit);
	UnitFrameHealthBar_Update(this.healthbar, this.unit);
	UnitFrameManaBar_Update(this.manabar, this.unit);
end

function SmartUnitFrame_CmdHandler(msg)
	if ( strlower(msg) == strlower("reset") ) then
		SmartUnitFrame_Reset();
	elseif ( strlower(msg) == strlower("reseticon") ) then
		if SCONFIG_ENABLE then
			SmartConfigUI_CommandHandler("reseticon");
		else
			DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame: 미니맵 아이콘 사용불가",1,0.5,0);
			DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame: SmartConfigUI가 필요합니다.",1,0.5,0);
		end
	elseif ( strlower(msg) == strlower("config") ) then
		if SCONFIG_ENABLE then
			SmartConfigUI_OpenConfig();
		else
			DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame: 유닛프레임 설정 사용불가",1,0.5,0);
			DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame: SmartConfigUI가 필요합니다.",1,0.5,0);
		end
	elseif ( strlower(msg) == strlower("resetconfig") ) then
		if SCONFIG_ENABLE then
			SmartConfigUI_ResetConfig();
		else
			DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame: 유닛프레임 설정 사용불가",1,0.5,0);
			DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame: SmartConfigUI가 필요합니다.",1,0.5,0);
		end
	elseif ( strlower(msg) == strlower("scale") ) then
		if SMART_SETSCALE_ENABLE then
			SmartUnitFrame_SetScaleOpen()
		else
			DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame: 유닛프레임 크기설정 사용불가",1,0.5,0);
			DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame: SmartSetScale이 필요합니다.",1,0.5,0);
		end
	else
		DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame Command: /suf",1,1,1);
		DEFAULT_CHAT_FRAME:AddMessage("[ reset | reseticon | config | resetconfig | scale ]",1,1,1);
		DEFAULT_CHAT_FRAME:AddMessage("▤ reset - 유닛프레임 위치초기화",0.75,0.75,0.75);
		DEFAULT_CHAT_FRAME:AddMessage("▤ reseticon - 미니맵아이콘 위치초기화",0.75,0.75,0.75);
		DEFAULT_CHAT_FRAME:AddMessage("▤ config - 유닛프레임 설정창 열기/닫기",0.75,0.75,0.75);
		DEFAULT_CHAT_FRAME:AddMessage("▤ resetconfig - 유닛프레임 설정초기화",0.75,0.75,0.75);
		DEFAULT_CHAT_FRAME:AddMessage("▤ scale - 유닛프레임 크기설정창 열기/닫기",0.75,0.75,0.75);
	end
end

function SmartUnitFrame_Reset()
	SmartPlayer_ResetPosition();
	SmartTarget_ResetPosition();
	SmartParty_ResetPosition();
	SmartParty_GroupCheck(true);
	SmartToT_ResetPosition();
	if SMART_FOCUS_ENABLE then
		SmartFocus_ResetPosition();
	end
	DEFAULT_CHAT_FRAME:AddMessage("SmartUnitFrame: 모든 유닛프레임 위치초기화",1,0.5,0);
end

function SmartUnitFrame_MovableLock()
	SmartPlayerRelocator.movable = false;
	SmartTargetRelocator.movable = false;
	SmartParty1Relocator.movable = false;
	SmartParty2Relocator.movable = false;
	SmartParty3Relocator.movable = false;
	SmartParty4Relocator.movable = false;
end

function SmartUnitFrame_MovableCheck()
	if SMART_PLAYER_Config.movable then
		SmartPlayerRelocator.movable = true;
		SmartPlayerRelocator:Show();
	else
		SmartPlayerRelocator.movable = false;
		SmartPlayerRelocator:Hide();
	end
	if SMART_TARGET_Config.movable then
		SmartTargetRelocator.movable = true;
		SmartTargetRelocator:Show();
	else
		SmartTargetRelocator.movable = false;
		SmartTargetRelocator:Hide();
	end
	if SMART_PARTY_Config.movable then
		SmartParty1Relocator.movable = true;
		SmartParty1Relocator:Show();
		if SMART_PARTY_Config.movablegroup then
			SmartParty2Relocator.movable = false;
			SmartParty3Relocator.movable = false;
			SmartParty4Relocator.movable = false;
			SmartParty2Relocator:Hide();
			SmartParty3Relocator:Hide();
			SmartParty4Relocator:Hide();
		else
			SmartParty2Relocator.movable = true;
			SmartParty3Relocator.movable = true;
			SmartParty4Relocator.movable = true;
			SmartParty2Relocator:Show();
			SmartParty3Relocator:Show();
			SmartParty4Relocator:Show();
		end
	else
		SmartParty1Relocator.movable = false;
		SmartParty2Relocator.movable = false;
		SmartParty3Relocator.movable = false;
		SmartParty4Relocator.movable = false;
		SmartParty1Relocator:Hide();
		SmartParty2Relocator:Hide();
		SmartParty3Relocator:Hide();
		SmartParty4Relocator:Hide();
	end
end

function SmartUnitFrame_DragEnter()
	if this.movable then
		GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT");
		GameTooltip:AddLine("프레임 이동가능");
		GameTooltip:AddLine("알트키와 함께 왼쪽 또는 오른쪽 마우스버튼으로 프레임 이동",1,1,1);
		GameTooltip:Show();
	end
end

function SmartUnitFrame_DragLeave()
	GameTooltip:Hide();
end

function SmartUnitFrame_DragStart(button)
	if this.movable and IsAltKeyDown() then
		if (button == "LeftButton") or (button == "RightButton") then
			this:GetParent():IsMovable();
			this:GetParent():StartMoving();
		end
	end
end

function SmartUnitFrame_DragStop()
	this:GetParent():StopMovingOrSizing();
end
