--[[
  ****************************************************************
	Scrolling Combat Text - Damage 2.21

	Author: Grayhoof
	****************************************************************

	Official Site:
		http://grayhoof.wowinterface.com 
	
	****************************************************************]]
--embedded libs
local parser = ParserLib:GetInstance("1.1")	

--global name
SCTD = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceConsole-2.0", "AceHook-2.1");

--Add new frame to SCT
SCT.FRAME3 = 3;
local arrAniData3 = {};
local arrAniCrit3 = {}
tinsert(SCT.ArrayAniData, arrAniData3);
tinsert(SCT.ArrayAniCritData, arrAniCrit3);

local MSG_Y_OFFSET = 0;
local arrMsgData = {
		["MSGTEXT1"] = {size=1, xoffset=0, yoffset=0, align="CENTER", height=5, duration=1},
}

local default_config = {
		["SCTD_VERSION"] = SCTD.Version,
		["SCTD_ENABLED"] = 1,
		["SCTD_SHOWMELEE"] = 1,
		["SCTD_SHOWPERIODIC"] = 1,
		["SCTD_SHOWSPELL"] = 1,
		["SCTD_SHOWPET"] = 1,
		["SCTD_SHOWCOLORCRIT"] = false,
		["SCTD_FLAGDMG"] = false,
		["SCTD_SHOWDMGTYPE"] = false,
		["SCTD_SHOWSPELLNAME"] = 1,
		["SCTD_SHOWRESIST"] = 1,
		["SCTD_SHOWTARGETS"] = false,
		["SCTD_DMGFONT"] = 1,
		["SCTD_TARGET"] = false,
		["SCTD_USESCT"] = 1,
		["SCTD_STICKYCRIT"] = 1,
		["SCTD_SPELLCOLOR"] = false,
		["SCTD_SHOWINTERRUPT"] = 1,
	};
	
local default_config_colors = {
		["SCTD_SHOWMELEE"] = {r = 1.0, g = 1.0, b = 1.0},
		["SCTD_SHOWPERIODIC"] = {r = 1.0, g =1.0, b = 0.0},
		["SCTD_SHOWSPELL"] = {r = 1.0, g = 1.0, b = 0.0},
		["SCTD_SHOWPET"] = {r = 0.6, g = 0.6, b = 0.0},
		["SCTD_SHOWCOLORCRIT"] = {r = 0.2, g = 0.4, b = 0.6},
		["SCTD_SHOWINTERRUPT"] = {r = 0.5, g = 0.5, b = 0.7}
}

local default_frame_config = {
		["FONT"] = 1,
		["FONTSHADOW"] = 2,
		["ALPHA"] = 100,
		["ANITYPE"] = 1,
		["ANISIDETYPE"] = 1,
		["XOFFSET"] = 0,
		["YOFFSET"] = 210,
		["DIRECTION"] = false,
		["TEXTSIZE"] = 24,
		["FADE"] = 1.5,
		["GAPDIST"] = 40,
		["ALIGN"] = 2,
}

local arrShadowOutline = {
	[1] = "",
	[2] = "OUTLINE",
	[3] = "THICKOUTLINE"
}

----------------------
--Called on login
function SCTD:OnEnable()
	--check SCT version
	if (not SCT) or (tonumber(SCT.db.profile["VERSION"]) < 5.3) then
		StaticPopupDialogs["SCTD_VERSION"] = {
								  text = SCTD.LOCALS.Version_Warning,
								  button1 = TEXT(OKAY) ,
								  timeout = 0,
								  whileDead = 1,
								  hideOnEscape = 1,
								  showAlert = 1
								};
		StaticPopup_Show("SCTD_VERSION");
		if (SCTOptionsFrame_Misc103) then
			SCTOptionsFrame_Misc103:Hide();
		end
		self:OnDisable();
		return;
	end
	self:RegisterSelfEvents();
end

----------------------
-- Disable all events, not using AceDB, but may as well name it right.
function SCTD:OnDisable()
	-- no more events to handle
	parser:UnregisterAllEvents("sctd")
	self:UnregisterAllEvents()
end

----------------------
--Called when addon loaded
function SCTD:OnInitialize()
	
	--slash commands
	local main = {
		type="group",
		args = {
			menu = {
				name = "Menu", type = 'execute',
		    desc = "Display SCT Option Menu",
		    func = function()
		        self:ShowSCTDMenu();
    		end
			},
		}
	}
	local menu = {
		type = 'execute',
    desc = "Display SCTD Option Menu",
    func = function()
        self:ShowSCTDMenu();
    end
	}
	
	self:RegisterChatCommand({"/sctd"}, main);
	self:RegisterChatCommand({"/sctdmenu"}, menu);
	
	--register with other mods
	self:RegisterOtherMods();
	
	--Hook SCT show menu
	self:Hook(SCT, "ShowMenu")
							
	--update old values
	self:UpdateValues();
	
	--setup msgs
	self:MsgInit();

end

----------------------
-- Show the Option Menu
function SCTD:ShowSCTDMenu()
	local loaded, message = LoadAddOn("sct_options");
	if (loaded) then
		--if options page exsists (not disabled)
		if (SCTDOptions) then
			--Hook SCT ShowExample
			if (not SCTD:IsHooked(SCT, "ShowExample")) then
				SCTD:Hook(SCT, "ShowExample");
			end
			--open sct window
			SCTD.hooks[SCT].ShowMenu();
			--mimic clicking the menu
			SCTOptionsFrame_Misc103:Click();
			--update animation options
			SCTD:UpdateAnimationOptions()
		else
			PlaySound("TellMessage");
			SCTD:Print(SCTD.LOCALS.Load_Error);
		end
	else
		PlaySound("TellMessage");
		SCTD:Print(SCT.LOCALS.Load_Error.." "..message);
	end;
end

----------------------
--Reset everything to default for SCTD
function SCTD:ShowMenu()
	SCTD:UpdateValues();
	--open sct menu
	self.hooks[SCT].ShowMenu();
	--Hook SCT ShowExample
	if (not self:IsHooked(SCT, "ShowExample") and SCT.ShowExample) then
		self:Hook(SCT, "ShowExample");
	end
end

----------------------
-- display ddl or chxbox based on type
function SCTD:UpdateAnimationOptions()
	--get scroll down checkbox
	local chkbox = getglobal("SCTOptionsFrame_CheckButton113");
	--get anime type dropdown
	local ddl1 = getglobal("SCTOptionsFrame_Selection103");
	--get animside type dropdown
	local ddl2 = getglobal("SCTOptionsFrame_Selection104");
	--get gap distance silder
	local slide = getglobal("SCTOptionsFrame_Slider106");
	--get subframe
	local subframe = getglobal("SCTDAnimationSubFrame");
	--get item
	local id = UIDropDownMenu_GetSelectedID(ddl1)
	chkbox:ClearAllPoints();
	chkbox:SetPoint("TOPLEFT", "SCTOptionsFrame_Selection103", "BOTTOMLEFT", 15, 0);
	--reset all scales
	chkbox:SetScale(1);
	ddl2:SetScale(1);
	ddl1:SetScale(1);
	if (id == 1 or id == 6) then
		chkbox:Show();
		ddl2:Hide();
		slide:Hide();
		subframe:SetHeight(80);
	elseif (id == 7 or id == 8) then
		chkbox:ClearAllPoints();
		chkbox:SetPoint("TOPLEFT", "SCTOptionsFrame_Selection103", "BOTTOMLEFT", 15, -40);
		chkbox:Show();
		ddl2:Show();
		slide:Show();
		subframe:SetHeight(140);
		--scale to fit screen
		chkbox:SetScale(.85);
		ddl2:SetScale(.85);
		ddl1:SetScale(.85);
	else
		chkbox:Hide();
		ddl2:Show();
		slide:Hide();
		subframe:SetHeight(90);
	end
end

---------------------
--Show SCT Example
function SCTD:ShowExample()
	self.hooks[SCT].ShowExample();
	self:MsgInit()
	self:SetDamageFlags();
	
	--animated example for options that may need it
	local option = this.SCTVar or "SCTD_SHOWMELEE";
	if (string.find(option,"SCTD_SHOW")) then
		self:DisplayText(option, self.LOCALS.EXAMPLE);
	end
	
	--show example FRAME3
	--get object
	example = getglobal("SCTDMsgExample1");
	--set text size
	SCT:SetFontSize(example,
									SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["FONT"],
									SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["TEXTSIZE"],
									SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["FONTSHADOW"]);
	--set the color
	example:SetTextColor(1, 1, 0);
	--set alpha
	example:SetAlpha(SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["ALPHA"]/100);
	--Position
	example:SetPoint("CENTER", "UIParent", "CENTER", 
									 SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["XOFFSET"], 
									 SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["YOFFSET"]);
	--Set the text to display
	example:SetText(self.LOCALS.EXAMPLE);
	
	--update animation options
	self:UpdateAnimationOptions()
end

----------------------
--Update old values for new versions
function SCTD:UpdateValues()
	local i, var;
	--set defaults
	for i, _ in pairs(default_config) do
		if(SCT.db.profile[i] == nil) then
			SCT.db.profile[i] = default_config[i];
		end
	end
	--set colors
	for i,_ in pairs(default_config_colors) do
		var = SCT.db.profile[SCT.COLORS_TABLE][i] or default_config_colors[i];
		SCT.db.profile[SCT.COLORS_TABLE][i] = var;
	end
	--set frame data
	if (not SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]) then
		SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3] = {};
	end
	for i,_ in pairs(default_frame_config) do
		if (SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3][i] == nil) then
			SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3][i] = default_frame_config[i];
		end
	end
end

----------------------
--Determine if its a "melee" ranged evet
function SCTD:IsMeleeRanged(skill)
	if (skill == ParserLib_MELEE or
			skill == self.LOCALS.AUTO_SHOT) then
		return true;
	else
		return false;
	end
end

----------------------
-- Parses all combat events using paserlib
function SCTD:ParseCombat(info)
	--self doesn't work here because of the call from ParserLib
	local self = SCTD;
	
	--exit if not enabled
	if (not SCT.db.profile["SCTD_ENABLED"]) then
		return;
	end
	
	--exit if not from self
	if (info.source ~= ParserLib_SELF) then
		return;
	end
	
	--Hits (melee, spell, etc..)
	if (info.type == "hit") then
		if (self:IsMeleeRanged(info.skill)) then
			local text = info.amount;
			if (info.isCrushing and SCT.db.profile["SHOWGLANCE"]) then text = SCT.LOCALS.Crushchar..text..SCT.LOCALS.Crushchar end;
			if (info.isGlancing and SCT.db.profile["SHOWGLANCE"]) then text = SCT.LOCALS.Glancechar..text..SCT.LOCALS.Glancechar end;
			self:DisplayText("SCTD_SHOWMELEE", text, info.isCrit, nil, nil, info.victim);
		else
			if (info.isDOT) then
				self:DisplayText("SCTD_SHOWPERIODIC", info.amount, nil, info.element, info.amountResist, info.victim, info.skill);
			else
				self:DisplayText("SCTD_SHOWSPELL", info.amount, info.isCrit, info.element, info.amountResist, info.victim, info.skill);
			end
		end
	--Miss Events
	elseif (info.type == "miss") then
		local type = "SCTD_SHOWMELEE";
		--remove skill if melee or ranged non-skill
		if (self:IsMeleeRanged(info.skill)) then
			info.skill = nil;
		else
			type="SCTD_SHOWSPELL";
		end
		local miss = getglobal(strupper(info.missType));
		self:DisplayText(type, miss, nil, nil, nil, info.victim, info.skill);
	--interrupts
	elseif (info.type == "interrupt") then
		self:DisplayText("SCTD_SHOWINTERRUPT", SCT.LOCALS.Interrupted, nil, nil, nil, info.victim, info.skill);
	end
end

----------------------
-- Parses all combat events using paserlib for pets
function SCTD:ParsePetCombat(info)
	--self doesn't work here because of the call from ParserLib
	local self = SCTD;
		
	--exit if not enabled
	if (not SCT.db.profile["SCTD_ENABLED"]) then
		return;
	end
	
	--Hits (melee, spell, etc..)
	if (info.type == "hit") then
		if (info.skill == ParserLib_MELEE) then
			local text = info.amount;
			if (info.isCrushing and SCT.db.profile["SHOWGLANCE"]) then text = SCT.LOCALS.Crushchar..text..SCT.LOCALS.Crushchar end;
			if (info.isGlancing and SCT.db.profile["SHOWGLANCE"]) then text = SCT.LOCALS.Glancechar..text..SCT.LOCALS.Glancechar end;
			self:DisplayText("SCTD_SHOWPET", text, info.isCrit, info.element, info.amountResist, info.victim, PET);
		else
			self:DisplayText("SCTD_SHOWPET", info.amount, info.isCrit, info.element, info.amountResist, info.victim, info.skill);
		end
	
	--Miss Events
	elseif (info.type == "miss") then
		--remove skill if melee or ranged non-skill
		if (self:IsMeleeRanged(info.skill)) then
			info.skill = nil;
		end
		local miss = getglobal(strupper(info.missType));
		self:DisplayText("SCTD_SHOWPET", miss, nil, nil, nil, info.victim, info.skill);
	end
end

----------------------
--Display for mainly combat events
--Mainly used for short messages
function SCTD:DisplayText(option, msg1, crit, damagetype, resisted, target, spell)
	local rbgcolor, showcrit, showmsg, adat;
	--if option is on
	if (SCT.db.profile[option]) then
		--if show only target
		if (SCT.db.profile["SCTD_TARGET"]) then
			if (target ~= UnitName("target")) then
				return;
			end
		end
		--get options
		rbgcolor = SCT.db.profile[SCT.COLORS_TABLE][option];
		--if damage type
		if ((damagetype) and (SCT.db.profile["SCTD_SHOWDMGTYPE"])) then
			msg1 = msg1.." "..damagetype.."";
		end
		--if spell color
		if ((damagetype) and (SCT.db.profile["SCTD_SPELLCOLOR"])) then
			rbgcolor = SCT.db.profile[SCT.SPELL_COLORS_TABLE][damagetype] or rbgcolor;
		end
		--if resisted
		if ((resisted) and (SCT.db.profile["SCTD_SHOWRESIST"])) then
			msg1 = msg1.." {"..resisted.."}";
		end
		--if target label
		if ((target) and (SCT.db.profile["SCTD_SHOWTARGETS"])) then
			msg1 = target..": "..msg1;
		end
		--if spell 
		if ((spell) and (SCT.db.profile["SCTD_SHOWSPELLNAME"])) then
			msg1 = msg1.." ("..spell..")";
		end
		--if flag
		if (SCT.db.profile["SCTD_FLAGDMG"]) then
			msg1 = self.LOCALS.SelfFlag..msg1..self.LOCALS.SelfFlag;
		end
		--if crit
		if (crit) then
			if (SCT.db.profile["SCTD_SHOWCOLORCRIT"]) then
				rbgcolor = SCT.db.profile[SCT.COLORS_TABLE]["SCTD_SHOWCOLORCRIT"];
			end
			self:Display_Crit_Damage( msg1, rbgcolor );
		else
			self:Display_Damage( msg1, rbgcolor );
		end

	end
end


----------------------
--Displays a message at the top of the screen
function SCTD:Display_Damage(msg, color)
	if (SCT.db.profile["SCTD_USESCT"]) then
			SCT:DisplayText(msg, color, nil, "damage", SCT.FRAME3);
	else
		SCTD_MSGTEXT1:SetPoint("CENTER", "UIParent", "CENTER",
													 SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["XOFFSET"],
													 SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["YOFFSET"] + MSG_Y_OFFSET);
		SCTD_MSGTEXT1:SetTimeVisible(SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["FADE"]);
		SCTD_MSGTEXT1:AddMessage(msg, color.r, color.g, color.b, 1);
	end
end

----------------------
--Displays a message at the top of the screen
function SCTD:Display_Crit_Damage(msg, color)
	if (SCT.db.profile["SCTD_STICKYCRIT"]) then
		SCT:DisplayText(msg, color, 1, "damage", SCT.FRAME3);
	elseif (SCT.db.profile["SCTD_USESCT"]) then
		SCT:DisplayText("+"..msg.."+", color, nil, "damage", SCT.FRAME3);
	else
		SCTD_MSGTEXT1:SetPoint("CENTER", "UIParent", "CENTER",
													 SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["XOFFSET"],
													 SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["YOFFSET"] + MSG_Y_OFFSET);
		SCTD_MSGTEXT1:SetTimeVisible(SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["FADE"] or 1.5);
		SCTD_MSGTEXT1:AddMessage("+"..msg.."+", color.r, color.g, color.b, 1);
	end
end

------------------------
--Setup msg arrays
function SCTD:MsgInit()
	for key, value in pairs(arrMsgData) do
		value.FObject = getglobal("SCTD_"..key);
		self:SetMsgFont(value.FObject);
	end
	self:SetDamageFlags()
end

------------------------
--Setup Damage Flags based on Options
function SCTD:SetDamageFlags()
	--set WoW Damage Flags
	if (SCT.db.profile["SCTD_DMGFONT"]) then
		SetCVar("CombatDamage", 0);
	else
		SetCVar("CombatDamage", 1);
	end
end

-------------------------
--Set the font of an object using msg vars
function SCTD:SetMsgFont(object)
	--set font
	object:SetFont(SCT.LOCALS.FONTS[SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["FONT"]].path,
								 SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["TEXTSIZE"], 
								 arrShadowOutline[SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["FONTSHADOW"]]);
	--reset size of allow 5 messages
	object:SetHeight(SCT.db.profile[SCT.FRAMES_DATA_TABLE][SCT.FRAME3]["TEXTSIZE"] * 6)
	--Set Fade Duration
	object:SetFadeDuration(1);
	--set offset to center
	MSG_Y_OFFSET = object:GetHeight()/2;
end

----------------------
--Register All Events
function SCTD:RegisterSelfEvents()
	--core chat events for Parserlib
	parser:RegisterEvent("sctd", "CHAT_MSG_COMBAT_SELF_HITS", SCTD.ParseCombat) ;
	parser:RegisterEvent("sctd", "CHAT_MSG_COMBAT_SELF_MISSES", SCTD.ParseCombat) ;
	parser:RegisterEvent("sctd", "CHAT_MSG_SPELL_SELF_DAMAGE", SCTD.ParseCombat) ;
	parser:RegisterEvent("sctd", "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE", SCTD.ParseCombat) ;
	parser:RegisterEvent("sctd", "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE", SCTD.ParseCombat) ;
	parser:RegisterEvent("sctd", "CHAT_MSG_COMBAT_PET_HITS", SCTD.ParsePetCombat) ;
	parser:RegisterEvent("sctd", "CHAT_MSG_COMBAT_PET_MISSES", SCTD.ParsePetCombat) ;
	parser:RegisterEvent("sctd", "CHAT_MSG_SPELL_PET_DAMAGE", SCTD.ParsePetCombat) ;
end

-------------------------
--Regsiter SCTD with other mods
function SCTD:RegisterOtherMods()
	-- myAddOns support
	if(myAddOnsFrame_Register) then
		local SCTDDetails = {
			name = "sctd",
			version = SCTD.Version,
			optionsframe = "SCTDOptions",
			category = MYADDONS_CATEGORY_COMBAT
		};
		myAddOnsFrame_Register(SCTDDetails);
	end
	
	--Cosmos support
	if ( EarthFeature_AddButton ) then
		EarthFeature_AddButton(
		   {
		      id="SCT";
		      name=self.LOCALS.CB_NAME;
		      text=self.LOCALS.CB_NAME;
		      subtext=self.LOCALS.CB_SHORT_DESC;
		      helptext=self.LOCALS.CB_LONG_DESC;
		      icon=self.LOCALS.CB_ICON;
		      callback=SCTD.ShowSCTDMenu;
		   }
		);
	elseif (Cosmos_RegisterButton) then
		Cosmos_RegisterButton (
		   self.LOCALS.CB_NAME,
		   self.LOCALS.CB_SHORT_DESC,
		   self.LOCALS.CB_LONG_DESC,
		   self.LOCALS.CB_ICON,
		   SCTD.ShowSCTDMenu,
		   function()
		      return true;
		   end
		);
		default_config.ENABLED = 0;
	end
	
	-- Add to CTMod Control panel if available
	if ( CT_RegisterMod ) then
		CT_RegisterMod(self.LOCALS.CB_NAME, nil, 5, self.LOCALS.CB_ICON, self.LOCALS.CB_LONG_DESC, "switch", nil, SCTD.ShowSCTDMenu);
	end
end