--[[
	Basic RuneWatch Widget: Runes
	Author: Voorije (ReAn)
	Last Edited: 2009-06-18T09:44:47Z
]]

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

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

--local RuneWatch_RuneFont = CreateFont("RuneWatch_RuneFont");
--RuneWatch_RuneFont:SetFont("Fonts\FRIZQT__.TTF", 20, "OUTLINE");
--RuneWatch_RuneFont:SetShadowColor(0,0,0,1);
--RuneWatch_RuneFont:SetShadowOffset(1,1);

local RuneTextures = {
	Blizzard = {
		[1] = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Blood",
		[2] = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Unholy",
		[3] = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Frost",
		[4] = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Death"
	},
	Custom1 = {
		[1] = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Blood",
		[2] = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Unholy",
		[3] = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Frost",
		[4] = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Death"
	},
	Custom2 = {
		[1] = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Blood2",
		[2] = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Unholy2",
		[3] = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Frost2",
		[4] = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Death2"
	}
}

local BorderTextures = {
	Blizzard = "Interface\\PlayerFrame\\UI-PlayerFrame-Deathknight-Ring",
	Custom1 = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Border",
	Custom2 = "Interface\\AddOns\\RuneWatch\\Artwork\\Widget-Runes\\Rune-Border",
}

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

function Widget:OnInitialize()
	Widget.ID = "runes";
	Widget.Name = "Runes";
	Widget.Description = "Rune Frames";

	self:InitOptions();
	self:InitGui();
	
	-- Register the Widget
	Widgets:Register(self.ID, self);
	
	-- Events
	self:RegisterEvent("RUNE_POWER_UPDATE")
	self:RegisterEvent("RUNE_TYPE_UPDATE")
	self:RegisterEvent("PLAYER_ENTERING_WORLD")
	self:RegisterEvent("PLAYER_ALIVE")
	
	RuneWatch.RegisterMessage(Widget, "RuneWatch_Widgets_Attach");
	RuneWatch.RegisterMessage(Widget, "RuneWatch_Widgets_Init");
	RuneWatch.RegisterMessage(Widget, "RuneWatch_Gui_Update");
	
	self:Super("OnInitialize");
end

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

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

--[===[ Initialization ]===]--
function Widget:InitOptions()
	local options = {
		type = "group",
		name = L["Runes"],
		order = 0,
		desc = L["Rune Options"],
		args = {
			dsc = {
				type = "description",
				order = 0,
				cmdHidden = true,
				dropdownHidden = true,
				name = L["Configuration options for the rune's on the frame."]
			},
			style = {
				type = "group",
				name = L["Rune Style"],
				desc = L["Rune Frame Style Options"],
				order = 1,
				inline = true,
				args = {
				
					skin = {
						type = "select",
						name = L["Rune Skin"],
						desc = L["Sets the skin of the runes."],
						order = 2,
						width = "double",
						values = {
							["Blizzard"] = L["Blizzard Default"],
							["Custom1"] = L["RuneWatch Custom Runes 1"],
							["Custom2"] = L["RuneWatch Custom Runes 2"]
						},
						style = "dropdown",
						get = function(info) return RuneWatch.db.frame.runes.skin end,
						set = function(info,v) RuneWatch.db.frame.runes.skin = v; RuneWatch:UpdateGui() end
					},
					order = {
						type = "select",
						name = L["Rune Order"],
						desc = L["Sets the order in which your runes appear on the bar."],
						order = 1,
						width = "double",
						values = { 
									["buf"] = L["Blood, Unholy, Frost"], 
									["ubf"] = L["Unholy, Blood, Frost"],
									["bfu"] = L["Blood, Frost, Unholy"],
									["ufb"] = L["Unholy, Frost, Blood"],
									["fbu"] = L["Frost, Blood, Uholy"],
									["fub"] = L["Frost, Unholy, Blood"]
								 },
						style = "dropdown",
						get = function(info) return RuneWatch.db.frame.runes.order end,
						set = function(info, v) RuneWatch.db.frame.runes.order = v; RuneWatch:UpdateGui() end
					}
				}
			},
			vtopts = {
				type = "group",
				name = "Visual Timer Options",
				desc = "Visual Timer Options",
				order = 2,
				inline = true,
				args = {
					dsc = {
						type = "description",
						order = 0,
						cmdHidden = true,
						dropdownHidden = true,
						name = "The Visual Timer is the way in which we visually represent the cooldown of a rune. These options configure it's behaviour as your runes cooldown."
					},
					viseffect = {
						type = "select",
						name = "Visual Effect",
						desc = "Sets the active visual effect for the cooldown.",
						order = 1,
						width = "double",
						values = { 
									["cooldown"] = "Cooldown Spinner",
									["colorfade"] = "Color Fade"
								 },
						style = "dropdown",
						get = function(info) return RuneWatch.db.frame.runes.vttype end,
						set = function(info, v) RuneWatch.db.frame.runes.vttype = v; RuneWatch:UpdateGui() end
					},
					blood = {
						type = "color",
						name = L["Blood Runes"],
						desc = L["Color of the blood rune timer text."],
						order = 2,
						hasAlpha = false,
						get = function(info) local v = RuneWatch.db.frame.runes.bloodfCol; return v.r, v.g, v.b, v.a; end,
						set = function(info, re,gr,bl,al) RuneWatch.db.frame.runes.bloodfCol = { r = re, g = gr, b = bl, a = al }; Widget:RuneWatch_Gui_Update("RuneWatch_Gui_Update", "null") end
					},
					unholy = {
						type = "color",
						name = L["Unholy Runes"],
						desc = L["Color of the unholy rune timer text."],
						order = 3,
						hasAlpha = false,
						get = function(info) local v = RuneWatch.db.frame.runes.unholyfCol; return v.r, v.g, v.b, v.a; end,
						set = function(info, re,gr,bl,al) RuneWatch.db.frame.runes.unholyfCol = { r = re, g = gr, b = bl, a = al }; Widget:RuneWatch_Gui_Update("RuneWatch_Gui_Update", "null") end
					},
					frost = {
						type = "color",
						name = L["Frost Runes"],
						desc = L["Color of the frost rune timer text."],
						order = 4,
						hasAlpha = false,
						get = function(info) local v = RuneWatch.db.frame.runes.frostfCol; return v.r, v.g, v.b, v.a; end,
						set = function(info, re,gr,bl,al) RuneWatch.db.frame.runes.frostfCol = { r = re, g = gr, b = bl, a = al }; Widget:RuneWatch_Gui_Update("RuneWatch_Gui_Update", "null") end
					},
					death = {
						type = "color",
						name = L["Death Runes"],
						desc = L["Color of the death rune timer text."],
						order = 5,
						hasAlpha = false,
						get = function(info) local v = RuneWatch.db.frame.runes.deathfCol; return v.r, v.g, v.b, v.a; end,
						set = function(info, re,gr,bl,al) RuneWatch.db.frame.runes.deathfCol = { r = re, g = gr, b = bl, a = al }; Widget:RuneWatch_Gui_Update("RuneWatch_Gui_Update", "null") end
					},
				}
			},
			ttcolors = {
				type = "group",
				name = L["Timer Text Colors"],
				desc = L["Rune timer text colors"],
				order = 3,
				inline = true,
				args = {
					dsc = {
						type = "description",
						order = 0,
						cmdHidden = true,
						dropdownHidden = true,
						name = L["The color for the timer text. Timer text is the numerical counter over each rune as it cools. From this section you can customize the color of each rune-type's timer text."]
					},
					blood = {
						type = "color",
						name = L["Blood Runes"],
						desc = L["Color of the blood rune timer text."],
						order = 1,
						hasAlpha = false,
						get = function(info) local v = RuneWatch.db.frame.runes.bloodCol; return v.r, v.g, v.b, v.a; end,
						set = function(info, re,gr,bl,al) RuneWatch.db.frame.runes.bloodCol = { r = re, g = gr, b = bl, a = al }; Widget:RuneWatch_Gui_Update("RuneWatch_Gui_Update", "null") end
					},
					unholy = {
						type = "color",
						name = L["Unholy Runes"],
						desc = L["Color of the unholy rune timer text."],
						order = 2,
						hasAlpha = false,
						get = function(info) local v = RuneWatch.db.frame.runes.unholyCol; return v.r, v.g, v.b, v.a; end,
						set = function(info, re,gr,bl,al) RuneWatch.db.frame.runes.unholyCol = { r = re, g = gr, b = bl, a = al }; Widget:RuneWatch_Gui_Update("RuneWatch_Gui_Update", "null") end
					},
					frost = {
						type = "color",
						name = L["Frost Runes"],
						desc = L["Color of the frost rune timer text."],
						order = 3,
						hasAlpha = false,
						get = function(info) local v = RuneWatch.db.frame.runes.frostCol; return v.r, v.g, v.b, v.a; end,
						set = function(info, re,gr,bl,al) RuneWatch.db.frame.runes.frostCol = { r = re, g = gr, b = bl, a = al }; Widget:RuneWatch_Gui_Update("RuneWatch_Gui_Update", "null") end
					},
					death = {
						type = "color",
						name = L["Death Runes"],
						desc = L["Color of the death rune timer text."],
						order = 4,
						hasAlpha = false,
						get = function(info) local v = RuneWatch.db.frame.runes.deathCol; return v.r, v.g, v.b, v.a; end,
						set = function(info, re,gr,bl,al) RuneWatch.db.frame.runes.deathCol = { r = re, g = gr, b = bl, a = al }; Widget:RuneWatch_Gui_Update("RuneWatch_Gui_Update", "null") end
					},
				}
			}
		}
	}
	
	Widget.Options = options;
end

function Widget:InitGui()
	for i = 1,6 do
		self.Gui[i] = self:InitRune(i);
		self.Gui[i]:SetPoint("CENTER", UIParent, "CENTER", 40*(i-1), 0); -- Temporary
		
		self:Rune_Update(i);
	end
end

function Widget:InitRune(index)
	local frame = CreateFrame("frame", "RW_Rune"..index, UIParent);
	frame:EnableMouse(true)
	frame:SetMovable(true)
	frame:SetWidth(32)
	frame:SetHeight(32)
	frame:SetPoint("CENTER", self.Gui.Anchor, "CENTER");
	frame:SetFrameStrata("HIGH");
	frame:SetFrameLevel(0);
	
	frame.ID = index;
	
	local texture = frame:CreateTexture("$parent_Background", "ARTWORK");
	frame.Image = texture
	texture:Show();
	
	texture:SetAllPoints(frame);
	texture:SetVertexColor(1,1,1,1);
	
	local cooldown = CreateFrame("cooldown", "$parent_Cooldown", frame);
	cooldown:SetPoint("CENTER", texture, "CENTER");
	cooldown:SetWidth(22);
	cooldown:SetHeight(22);
	cooldown:SetFrameStrata("HIGH");
	cooldown:SetFrameLevel(1);
	
	-- OmniCC Fix
	cooldown.noCooldownCount = true;
	
	local cooltex = frame:CreateTexture("$parent_CooldownTexture", "OVERLAY");
	cooltex:SetPoint("CENTER", texture, "CENTER", 0, 1);
	cooltex:SetWidth(20);
	cooltex:SetHeight(20);
	cooltex:SetTexture(1,0,0,1);
	cooltex:SetAlpha(0);
	--cooltex:Show();
	
	frame.CoolTex = cooltex;
	
	local border = CreateFrame("frame", "$parent_Border", frame);
	border:SetAllPoints(frame);
	border:SetFrameStrata("HIGH");
	border:SetFrameLevel(4);	
	border:Show();
	frame.Border = border;
	
	local bart = border:CreateTexture("$parent_Art", "OVERLAY");
	bart:SetTexture(BorderTextures.Blizzard);
	bart:SetAllPoints(border);
	bart:Show();
	
	border.Art = bart;
	
	frame.Cooldown = cooldown;
	
	local t = border:CreateFontString("$parent_Timer", "OVERLAY", "SystemFont_Shadow_Huge1");
	frame.Timer = t;
	--t:SetFontObject(RuneWatch_RuneFont);
	t:SetTextColor(1,1,0,1);
	
	-- Set Data
	t:SetText("0");
	t:SetAllPoints(frame);
	t:SetJustifyH("CENTER");
	t:SetJustifyV("MIDDLE");
	--t:SetShadowOffset(2,2);
	--t:SetShadowColor(0,0,0,1);
	t:Hide();
	
	frame:Show();
	
	return frame;
end

--[===[ Events ]===]--
function Widget:RUNE_POWER_UPDATE(event, ...)
	local rune, usable = ...;
	if not usable then
		self.Gui[rune]:SetScript("OnUpdate", function(self, elapsed) Widget:Rune_OnUpdate(self, elapsed) end);
		self.Gui[rune].Timer:Show();
		if (RuneWatch.db.frame.runes.vttype == "cooldown") then
			self.Gui[rune].Cooldown:Show();
		else
			self.Gui[rune].Cooldown:Hide();
		end
		self.Gui[rune].Image:SetVertexColor(0.8,0.8,0.8,0.9);
	end
end

function Widget:RUNE_TYPE_UPDATE(event, ...)
	local rune = ...;
	self:Rune_Update(rune);
end

function Widget:PLAYER_ALIVE(event, ...)
	Widget:RuneWatch_Gui_Update(event, ...);
end

function Widget:PLAYER_ENTERING_WORLD(event, ...)
	Widget:RuneWatch_Gui_Update(event, ...);
end

function Widget:RuneWatch_Gui_Update(event, ...)
	for i = 1,6 do
		Widget:Rune_Update(i)
	end
end

function Widget:RuneWatch_Widgets_Attach(event, ...)
	local skinID, ori = ...;
	
	local skinObj = RuneWatch.Skins:GetSkin(skinID);
	
	for i = 1,6 do
		local MountName = "RUNE"..i;
		local Mount = RuneWatch.Mounts:GetMount(skinObj, MountName, ori);
		
		self:AttachRune(i, Mount);
	end
end

function Widget:RuneWatch_Widgets_Init(event, ...)
	local anchor = ...;
	
	for i = 1,6 do
		Widget.Gui[i]:SetParent(anchor);
	end
end

function Widget:AttachRune(index, pos)
	local runes = self:GetRuneOrder();
	
	if (pos == nil) then
		-- Empty
		self.Gui[runes[index]]:Hide();
		return;
	end
	
	local rune = self.Gui[runes[index]];
	rune:Show();
	
	rune:ClearAllPoints();
	rune:SetWidth(32);
	rune:SetHeight(32);
	rune:SetPoint("CENTER", RuneWatch.Gui.Anchor, "CENTER", pos.x, pos.y);
end

function Widget:GetRuneOrder()
	local ord = RuneWatch.db.frame.runes.order;
	local runes = {}
	
	if (ord == "buf") then
		runes = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6 }
	elseif (ord == "bfu") then
		runes = { [1] = 1, [2] = 2, [3] = 5, [4] = 6, [5] = 3, [6] = 4 }
	elseif (ord == "fbu") then
		runes = { [1] = 5, [2] = 6, [3] = 1, [4] = 2, [5] = 3, [6] = 4 }
	elseif (ord == "fub") then
		runes = { [1] = 5, [2] = 6, [3] = 3, [4] = 4, [5] = 1, [6] = 2 }
	elseif (ord == "ubf") then
		runes = { [1] = 3, [2] = 4, [3] = 1, [4] = 2, [5] = 5, [6] = 6 }
	elseif (ord == "ufb") then
		runes = { [1] = 3, [2] = 4, [3] = 5, [4] = 6, [5] = 1, [6] = 2 }
	else
		runes = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6 } -- Default
	end
	
	return runes;
end

--[===[ Update ]===]--
function Widget:Rune_Update(rune)
	local runeTheme = RuneWatch.db.frame.runes.skin or "Custom1";
	local runeType = GetRuneType(rune);	
	
	if (rune ~= 7 and rune ~= 8) then
		if (runeType) then
			if (RuneWatch.db.frame.runes.vttype == "cooldown") then
				self.Gui[rune].Cooldown:Show();
				self.Gui[rune].CoolTex:Hide();
			end
			
			if (RuneWatch.db.frame.runes.vttype == "colorfade") then
				self.Gui[rune].Cooldown:Hide();
				self.Gui[rune].CoolTex:Show();
			end
		
			self.Gui[rune]:Show();
			self.Gui[rune].Image:SetTexture(RuneTextures[runeTheme][runeType]);
			self.Gui[rune].Border.Art:SetTexture(BorderTextures[runeTheme]);
			
			local tCol;
			if (runeType == 1) then
				tCol = RuneWatch.db.frame.runes.bloodCol;
				fCol = RuneWatch.db.frame.runes.bloodfCol;
			elseif(runeType == 2) then
				tCol = RuneWatch.db.frame.runes.unholyCol;
				fCol = RuneWatch.db.frame.runes.unholyfCol;
			elseif(runeType == 3) then
				tCol = RuneWatch.db.frame.runes.frostCol;
				fCol = RuneWatch.db.frame.runes.frostfCol;
			else
				tCol = RuneWatch.db.frame.runes.deathCol;
				fCol = RuneWatch.db.frame.runes.deathfCol;
			end
			
			self.Gui[rune].CoolTex:SetTexture(fCol.r, fCol.g, fCol.b, fCol.a);
			self.Gui[rune].Timer:SetTextColor(tCol.r, tCol.g, tCol.b, tCol.a);
		else
			self.Gui[rune]:Hide();
		end
	end
end

function Widget:Rune_OnUpdate (self, elapsed)
	local start, duration, runeReady = GetRuneCooldown(self.ID);
	
	local displayCooldown = (runeReady and 0) or 1;
	local showCooldown;
	
	if (RuneWatch.db.frame.runes.vttype == "cooldown") then
		showCooldown = true;
	else
		showCooldown = false;
	end
	
	if (displayCooldown) then
		local offset = GetTime() - start;
		local timer = ceil(duration - offset);
		local percAlpha = 1 - (offset / duration);
		
		-- Fix for rune-timeout when dead
		if (timer <= 0) then
			self.CoolTex:SetAlpha(0);
			self.Timer:Hide();
			self.Image:SetVertexColor(1,1,1,1);
			self:SetScript("OnUpdate", nil);
		else
			self.CoolTex:SetAlpha(percAlpha);
			self.Timer:SetText(timer);
			if showCooldown then
				self.Cooldown:SetCooldown(start, duration);
			end
		end
	end
	
	if ( runeReady ) then
		-- Stop Updating! Unregister the script
		self.CoolTex:SetAlpha(0);
		self.Timer:Hide();
		self.Image:SetVertexColor(1,1,1,1);
		self:SetScript("OnUpdate", nil);
	end
end
