--[[
	Basic RuneWatch Widget: Disease Tracker
	Author: Voorije (ReAn)
	Last Edited: 2010-06-22T08:14:57Z
]]

local L = LibStub("AceLocale-3.0"):GetLocale("RuneWatch");

assert(RuneWatch, L["Unable to locate RuneWatch Addon Object."]);

local WidgetArt = {
	Disease = "Interface\\ICONS\\Spell_Nature_NullifyDisease",
	BloodPlague = "Interface\\ICONS\\Spell_DeathKnight_BloodPlague",
	FrostFever = "Interface\\ICONS\\Spell_DeathKnight_FrostFever"
}

local WIcons = {
	BP = "Interface\\AddOns\\RuneWatch\\Artwork\\Shared\\Icon-BloodPlague",
	FF = "Interface\\AddOns\\RuneWatch\\Artwork\\Shared\\Icon-FrostFever",
	CF = "Interface\\AddOns\\RuneWatch\\Artwork\\Shared\\Icon-CryptFever",
	EP = "Interface\\AddOns\\RuneWatch\\Artwork\\Shared\\Icon-EbonPlague",
	UB = "Interface\\AddOns\\RuneWatch\\Artwork\\Shared\\Icon-Unblight",
	Ring = "Interface\\AddOns\\RuneWatch\\Artwork\\Shared\\Icon-Ring"
}

local SpellIDs = {
	BP = 55078,
	FF = 55095,
	CF = 50509,
	EP = 51734,
	UB = 49194,--55855,
	Horn = 57330
}

local SpellNames = {
	BP = "",
	FF = "",
	CF = "",
	EP = "",
	UB = "",
	Horn = ""
}

local AceTimer = LibStub("AceTimer-3.0");

local Widget = RuneWatch:NewModule("Widget_Disease", RuneWatch.WidgetBase, "AceConsole-3.0", "AceEvent-3.0")
local _W = RuneWatch.Widgets;

RuneWatch_Widget_Disease = Widget; -- Global Variable

Widget.TargetGUID = "0x0";

RW_TrackerFont = CreateFont("RW_TrackerFont");
RW_TrackerFont:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE");
RW_TrackerFont:SetJustifyV("MIDDLE");
RW_TrackerFont:SetJustifyH("CENTER");

function Widget:OnInitialize()
	Widget.ID = "disease";
	Widget.Name = "Diseases";
	Widget.Description = "Disease Tracker";

	Widget.State = {
		Diseases = 0,
		BP = {Time = 0, Last = 0, Active = false, id = -1},
		FF = {Time = 0, Last = 0, Active = false, id = -1},
		CF = {Time = 0, Last = 0, Active = false, id = -1},
		EP = {Time = 0, Last = 0, Active = false, id = -1},
		UB = {Time = 0, Last = 0, Active = false, id = -1},
		
		Horn = {Time = 0, Last = 0, Active = false, id = -1},
	}
	
	self:InitData();
	self:InitOptions();
	self:InitGui();
	
	-- Register the Widget
	_W:Register(self.ID, self);
	
	-- Events
	self:RegisterEvent("PLAYER_TARGET_CHANGED");
	self:RegisterEvent("PLAYER_ENTERING_WORLD");
	self:RegisterEvent("PLAYER_ALIVE");
	self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED");
	RuneWatch.RegisterMessage(Widget, "RuneWatch_Widgets_Attach");
	RuneWatch.RegisterMessage(Widget, "RuneWatch_Widgets_Init");
	
	self:LookupSpellLocale();
	
	self:Super("OnInitialize");
end

function Widget:InitData()
	local basicData = {
		enabled = true
	}
	
	if (not RuneWatch.db.widgets.Diseases) then
		RuneWatch.db.widgets.Diseases = basicData;
	end
end

function Widget:OnEnable()
	self:Super("OnEnable");
end

function Widget:OnDisable()
	self:Super("OnDisable");
end

function Widget:LookupSpellLocale()
	SpellNames.BP = GetSpellInfo(SpellIDs.BP);
	SpellNames.FF = GetSpellInfo(SpellIDs.FF);
	SpellNames.CF = GetSpellInfo(SpellIDs.CF);
	SpellNames.EP = GetSpellInfo(SpellIDs.EP);
	SpellNames.UB = GetSpellInfo(SpellIDs.UB);
	
	-- Self
	SpellNames.Horn = GetSpellInfo(SpellIDs.Horn);
end

--[===[ Initialization ]===]--
function Widget:InitGui()
	self:InitCenter();
	--self:InitBloodPlague();
	--self:InitFrostFever();
	
	-- Create Disease Widgets
	Widget.Gui.BP = self:InitTimer("RW_W_Disease_BP", WIcons.BP);
	Widget.Gui.FF = self:InitTimer("RW_W_Disease_FF", WIcons.FF);
	Widget.Gui.CF = self:InitTimer("RW_W_Disease_CF", WIcons.CF);
	Widget.Gui.UB = self:InitTimer("RW_W_Disease_UB", WIcons.UB);
	
	-- Place Disease Widgets
	Widget.Gui.BP:SetPoint("CENTER", Widget.Gui.Base, "CENTER", -40, 0);
	Widget.Gui.FF:SetPoint("CENTER", Widget.Gui.Base, "CENTER", 40, 0);
	
	Widget.Gui.CF:SetPoint("CENTER", Widget.Gui.Base, "CENTER", -80, 0);
	Widget.Gui.UB:SetPoint("CENTER", Widget.Gui.Base, "CENTER", 80, 0);
	
	self:ScanDebuffs();
end

function Widget:InitCenter()
	local frame = CreateFrame("frame", "RW_W_Disease", UIParent);
	frame:SetWidth(40);
	frame:SetHeight(40);
	frame:SetPoint("CENTER", UIParent, "CENTER");
	frame:Show();
	
	local bg = frame:CreateTexture("$parent_Frame", "BACKGROUND");
	bg:SetTexture("Interface\\ICONS\\INV_Misc_Horn_02");
	bg:SetVertexColor(0.5, 0.5, 0.5, 1);
	bg:SetAllPoints(frame);
	bg:Show();
	
	frame.Image = bg;
	
	local t = frame:CreateFontString("$parent_Text", "ARTWORK", "SystemFont_Shadow_Huge1");
	t:SetAllPoints(frame);
	t:SetJustifyH("CENTER");
	t:SetJustifyV("MIDDLE");
	t:SetText("0");
	t:Show();
	
	frame.Text = t;
	
	Widget.Gui.Base = frame;
end

--[[

class Timer
{
	.Cool = Cooldown Frame
	.Over = Overlay Frame
	.Art = Base Art
	.Ring = Overlay Ring
	.Timer = Timer Text
}

]]--

function Widget:InitTimer(name, iart)
	local frame = CreateFrame("frame", name, UIParent);
	frame:SetWidth(36);
	frame:SetHeight(36);
	frame:SetPoint("CENTER", Widget.Gui.Base, "CENTER", 0, 0);
	frame:Show();
	
	local cframe = CreateFrame("cooldown", "$parent_Cool", frame);
	cframe:SetPoint("CENTER", frame, "CENTER");
	cframe:SetWidth(25);
	cframe:SetHeight(25);
	cframe:Show();
	
	-- Omni CC Fix
	cframe.noCooldownCount = true;
	
	cframe:SetFrameLevel(frame:GetFrameLevel() + 1);
	
	frame.Cool = cframe;
	
	local oframe = CreateFrame("frame", "$parent_Over", frame);
	oframe:SetAllPoints(frame);
	oframe:Show();
	oframe:SetFrameLevel(frame:GetFrameLevel() + 2);
	oframe:EnableMouse(true);
	
	frame.Over = oframe;

	-- Lower Art
	
	local art = frame:CreateTexture("$parent_Art", "BACKGROUND");
	art:SetTexture(iart);
	art:SetVertexColor(1, 1, 1, 1);
	art:SetAllPoints(frame);
	art:Show();
	
	frame.Art = art;
	
	-- Over Art
	local ring = oframe:CreateTexture("$parent_Ring", "BACKGROUND");
	ring:SetAllPoints(oframe);
	ring:SetTexture(WIcons.Ring); -- Ring Overlay
	ring:Show();
	
	frame.Ring = ring;
	
	local timer = oframe:CreateFontString("$parent_Timer", "ARTWORK", "RW_TrackerFont");
	timer:SetAllPoints(oframe);
	timer:SetTextColor(1,1,0,0.7);
	timer:SetJustifyH("CENTER");
	timer:SetJustifyV("MIDDLE");
	timer:SetText("00");
	timer:Show();
	
	frame.Timer = timer;
	
	return frame;
end

function Widget:InitOptions()
	local options = {
		type = "group",
		name = L["Diseases"],
		order = 0,
		desc = L["Disease Tracker Options"],
		args = {
			dsc = {
				type = "description",
				order = 0,
				cmdHidden = true,
				dropdownHidden = true,
				name = L["Configuration options for the disease tracker on the frame."]
			},
			enabled = {
				type = "toggle",
				name = L["Enabled"],
				width = "full",
				desc = L["Enables/Disables the Disease Frame"],
				get = function(info) return Widget:Data_Enabled(nil); end,
				set = function(info, v) Widget:Data_Enabled(v); end
			}
		}
	}
	
	Widget.Options = options;
end

function Widget:Data_Enabled(val)
	if (val == nil) then
		return RuneWatch.db.widgets.Diseases.enabled;
	end
	
	RuneWatch.db.widgets.Diseases.enabled = val;
	Widget:State_Enabled();
end

function Widget:State_Enabled()
	if (RuneWatch.db.widgets.Diseases.enabled) then
		Widget.Gui.Base:Show();
		Widget:ScanDebuffs();
	else
		Widget.Gui.Base:Hide();
		Widget.Gui.BP:Hide();
		Widget.Gui.FF:Hide();
		Widget.Gui.CF:Hide();
		Widget.Gui.UB:Hide();
	end
end

--[===[ Events ]===]--
function Widget:COMBAT_LOG_EVENT_UNFILTERED(event, ...)
	local _, ev, src, _, _, dst, _, _, a1, a2, a3, a4, a5, a6, a7, a8 = ...;
	
	if (not Widget:Data_Enabled(nil)) then
		return
	end
	
	if (src == UnitGUID("player")) then
		if (ev == "SPELL_AURA_APPLIED" or
		    ev == "SPELL_AURA_REMOVED" or
			ev == "SPELL_AURA_REFRESH") then
			
			local spellID = a1;
			local auraType = a4;
			
			Widget:ScanDebuffs();
		end
	end
end

function Widget:PLAYER_ENTERING_WORLD(event, ...)	
	Widget.Gui.Base:SetScript("OnUpdate", nil); -- Reset the Script
	Widget:State_Enabled();
	if (not Widget:Data_Enabled(nil)) then
		return
	end
	Widget:ScanDebuffs();
end

function Widget:PLAYER_ALIVE(event, ...)
	Widget.Gui.Base:SetScript("OnUpdate", nil); -- Reset the Script
	Widget:State_Enabled();
	if (not Widget:Data_Enabled(nil)) then
		return
	end
	Widget:ScanDebuffs();
end

function Widget:PLAYER_TARGET_CHANGED(event, ...)
	if (not Widget:Data_Enabled(nil)) then
		return
	end
	Widget.TargetGUID = UnitGUID("target");
	Widget:ScanDebuffs();
end

function Widget:RuneWatch_Widgets_Attach(event, ...)
	local skinID, ori = ...;
	local skinObj = RuneWatch.Skins:GetSkin(skinID);
	local Mount = RuneWatch.Mounts:GetMount(skinObj, "TOP", ori);
	
	Widget.Gui.Base:SetPoint("CENTER", RuneWatch.Gui.Anchor, "CENTER", Mount.x, Mount.y);
end

function Widget:RuneWatch_Widgets_Init(event, ...)
	local anchor = ...;

	Widget.Gui.Base:SetParent(anchor);
end

--[===[ Update ]===]--
function Widget:ScanBuffs()
	
	local data = { found = false, start = 0, duration = 0, expire = 0 }

	local foundHorn = false;
	local hornData = {};
	for i = 1,40 do
		local nm, rank, icon, count, debuff, duration, expire, owner, isSteal = UnitAura("player", i, "HELPFUL");
		
		if (nm == SpellNames.Horn) then
			-- My Horn
			Widget.State.Horn.Time = expire; -- Time the debuff expires
			Widget.State.Horn.Active = true;
			
			--Widget.Gui.BP.Cool:SetCooldown((expire - duration), duration);
			
			foundHorn = true;
		end
	end

	if (foundHorn) then	
		local g = Widget.Gui.Base;
		if (g:GetScript("OnUpdate") == nil) then
			g:SetScript("OnUpdate", function(frame, elapsed)
				Widget.State.Horn.Last = Widget.State.Horn.Last + elapsed;
				
				if (Widget.State.Horn.Last > 0.5) then
					Widget.State.Horn.Last = 0;
					
					-- Do a visual
					local left = floor(Widget.State.Horn.Time - GetTime());
					local ltext;
					
					if left > 60 then
						local leftMin = ceil(left / 60);
						ltext = leftMin.."m";
					else
						ltext = left..""; -- Make it a string
					end
					
					Widget.Gui.Base.Text:SetText(ltext);
				end
			end);
		end
	else
		local g = Widget.Gui.Base;
		Widget.State.Horn.Active = false;
		
		-- Remove an update script if it's active
		if (g:GetScript("OnUpdate") ~= nil) then
			g:SetScript("OnUpdate", nil);
		end
	end
	
	return data;
end	

function Widget:ScanDebuffs()
	
	local dCount = 0;
	local foundBP = false;
	local foundFF = false;
	local foundCF = false;
	local foundEP = false;
	local foundUB = false;
	
	Widget:ScanBuffs() -- Horn
	
	for i = 1,40 do
		local nm, rank, icon, count, debuff, duration, expire, owner, isSteal = UnitAura("target", i, "HARMFUL");
		
		-- Patch for 3.1 Changes to UnitAura(...)
		if owner == "player" then
			isMine = true;
		else
			isMine = false;
		end

	
		if (debuff == "Disease") then
			-- Disease!
			if (isMine) then
				dCount = dCount + 1;
			end
			
			if (isMine) then
				if (nm == SpellNames.BP) then
					-- My Blood Plague
					Widget.State.BP.Time = expire; -- Time the debuff expires
					Widget.State.BP.Active = true;
					
					Widget.Gui.BP.Cool:SetCooldown((expire - duration), duration);
					
					foundBP = true;
				end
				
				if (nm == SpellNames.FF) then
					-- My Frost Fever
					Widget.State.FF.Time = expire; -- Time the debuff expires
					Widget.State.FF.Active = true;
					
					Widget.Gui.FF.Cool:SetCooldown((expire - duration), duration);
					
					foundFF = true;
				end
				
				if (nm == SpellNames.CF) then
					-- My Crypt Fever
					Widget.State.CF.Time = expire; -- Time the debuff expires
					Widget.State.CF.Active = true;
					
					Widget.Gui.CF.Cool:SetCooldown((expire - duration), duration);
					
					foundCF = true;
				end
				
				if (nm == SpellNames.EP) then
					-- My Ebon Plague
					Widget.State.CF.Time = expire; -- Time the debuff expires
					Widget.State.CF.Active = true;
					
					Widget.Gui.CF.Cool:SetCooldown((expire - duration), duration);
					
					foundCF = true;
					foundEP = true;
				end
			end
		else
			if (isMine) then
				if (nm == SpellNames.UB) then
					-- My Unholy Blight
					Widget.State.UB.Time = expire; -- Time the debuff expires
					Widget.State.UB.Active = true;
					
					Widget.Gui.UB.Cool:SetCooldown((expire - duration), duration);
					
					foundUB = true;
				end
			end
		end
	end
	
	if (foundBP) then	
		local g = Widget.Gui.BP;
		if (g:GetScript("OnUpdate") == nil) then
			g:SetScript("OnUpdate", function(frame, elapsed)
				Widget.State.BP.Last = Widget.State.BP.Last + elapsed;
				
				if (Widget.State.BP.Last > 0.5) then
					Widget.State.BP.Last = 0;
					
					-- Do a visual
					local left = floor(Widget.State.BP.Time - GetTime());
					Widget.Gui.BP.Timer:SetText(left);
				end
			end);
		end
		
		g:Show();
		--g.Text:Show();
	else
		local g = Widget.Gui.BP;
		g:Hide();
		
		Widget.State.BP.Active = false;
		
		-- Remove an update script if it's active
		if (g:GetScript("OnUpdate") ~= nil) then
			g:SetScript("OnUpdate", nil);
		end
	end
	
	if (foundFF) then	
		local g = Widget.Gui.FF;
		if (g:GetScript("OnUpdate") == nil) then
			g:SetScript("OnUpdate", function(frame, elapsed)
				Widget.State.FF.Last = Widget.State.FF.Last + elapsed;
				
				if (Widget.State.FF.Last > 0.5) then
					Widget.State.FF.Last = 0;
					
					-- Do a visual
					local left = floor(Widget.State.FF.Time - GetTime());
					Widget.Gui.FF.Timer:SetText(left);
				end
			end);
		end
		
		g:Show();
		--g.Text:Show();
	else
		local g = Widget.Gui.FF;
		g:Hide();
		
		Widget.State.FF.Active = false;
		
		-- Remove an update script if it's active
		if (g:GetScript("OnUpdate") ~= nil) then
			g:SetScript("OnUpdate", nil);
		end
	end
	
	if (foundUB) then	
		local g = Widget.Gui.UB;
		if (g:GetScript("OnUpdate") == nil) then
			g:SetScript("OnUpdate", function(frame, elapsed)
				Widget.State.UB.Last = Widget.State.UB.Last + elapsed;
				
				if (Widget.State.UB.Last > 0.5) then
					Widget.State.UB.Last = 0;
					
					-- Do a visual
					local left = floor(Widget.State.UB.Time - GetTime());
					Widget.Gui.UB.Timer:SetText(left);
				end
			end);
		end
		
		g:Show();
	else
		local g = Widget.Gui.UB;
		g:Hide();
		
		Widget.State.UB.Active = false;
		
		-- Remove an update script if it's active
		if (g:GetScript("OnUpdate") ~= nil) then
			g:SetScript("OnUpdate", nil);
		end
	end
	
	if (foundCF) then	
		local g = Widget.Gui.CF;
		if (g:GetScript("OnUpdate") == nil) then
			g:SetScript("OnUpdate", function(frame, elapsed)
				Widget.State.CF.Last = Widget.State.CF.Last + elapsed;
				
				if (Widget.State.CF.Last > 0.5) then
					Widget.State.CF.Last = 0;
					
					-- Do a visual
					local left = floor(Widget.State.CF.Time - GetTime());
					Widget.Gui.CF.Timer:SetText(left);
				end
			end);
		end
		
		if (foundEP) then
			Widget.Gui.CF.Art:SetTexture(WIcons.EP);
		else
			Widget.Gui.CF.Art:SetTexture(WIcons.CF);
		end
		
		g:Show();
		--g.Text:Show();
	else
		local g = Widget.Gui.CF;
		g:Hide();
		
		Widget.State.CF.Active = false;
		
		-- Remove an update script if it's active
		if (g:GetScript("OnUpdate") ~= nil) then
			g:SetScript("OnUpdate", nil);
		end
	end
	
	-- Update Diseases
	--local _f = Widget.Gui.Base;
	--_f.Text:SetText(dCount);
end
