local addonName, addon = ...

local SIZE = 15
local DURABILITY_MID_RANGE = 50
local FPS_MID_RANGE = 20
local LATENCY_MID_RANGE = 300
local PERFORMANCEBAR_UPDATE_INTERVAL = PERFORMANCEBAR_UPDATE_INTERVAL or 10
local date, floor, max, min, tonumber = date, floor, max, min, tonumber
local GetFramerate, GetGameTime, GetNetStats = GetFramerate, GetGameTime, GetNetStats
local colors, CLASS = CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS, addon.CLASS

-- Main Frame Creation
local DashBoardFrame = CreateFrame('frame', nil, UIParent)
DashBoardFrame:SetFrameStrata("HIGH")
local DBFbg = DashBoardFrame:CreateTexture(nil, "BACKGROUND")
DBFbg:SetAllPoints(DashBoardFrame)

-- First, define a set of default properties for reference.
local frameDefaults = {
	object = "Frame", -- string
	parent = DashBoardFrame, -- nil or object
	template = nil, -- nil or string
	justify = "RIGHT", -- string; LEFT, RIGHT, or CENTER
	text = "188",
	framewidth = nil,
	texture = nil, -- boolean
	texturepath = nil,
	textureheight = 12,
	texturewidth = 12,
}

local dashFramesToCreate = {
	["GUI_DashMail"] = {
		texture = true,
		texturepath = [[Interface\AddOns\]] .. addonName .. [[\Media\MailIcon]],
	},
	["GUI_DashQuest"] = {
		object = "Button",
		text = " 25/25",
		texture = true,
		texturepath = [[Interface\AddOns\]] .. addonName .. [[\Media\QuestIcon]],
	},
	["GUI_DashDurability"] = {
		object = "Button",
		text = "  100%",
		texture = true,
		texturepath = [[Interface\Icons\Trade_BlackSmithing]],
	},
	["GUI_DashInventory"] = {
		object = "Button",
		texture = true,
		template = "SecureHandlerClickTemplate",
		text = " 888/888",
		textureheight = SIZE,
		texturewidth = SIZE,
		texturepath = [[Interface\AddOns\]] .. addonName .. [[\Media\BagIcon]],
	},
	["GUI_DashMoney"] = {
		framewidth = 1,
		object = "Button",
		justify = nil,
		text = nil
	},
	["GUI_DashSocial"] = {
		object = "Button",
		template = "SecureHandlerClickTemplate",
		texture = true,
		textureheight = 20,
		texturewidth = 20,
		texturepath = "Interface/FriendsFrame/UI-Toast-FriendOnlineIcon.blp",
	},
	["GUI_DashGuild"] = {
		object = "Button",
		template = "SecureHandlerClickTemplate",
		texture = true,
		textureheight = 26,
		texturewidth = 21,
		texturepath = "Interface/Buttons/UI-MicroButton-Guild-Banner.blp",
	},
	["GUI_DashClock"] = {
		object = "Button",
		texture = true,
		text = " 18:88pm",
		textureheight = SIZE,
		texturewidth = nil,
		texturepath = "Interface/PlayerFrame/UI-PlayerFrame-Deathknight-Glow.blp",
	},
	["GUI_DashLatency"] = {
		text = " 888ms",
	},
	["GUI_DashFPS"] = {
		text = " 188fps",
	},
	["GUI_DashSpeed"] = {
		framewidth = 46,
		texture = true,
		text = " 100%",
		texturepath = "Interface/TAXIFRAME/UI-Taxi-Icon-Green.blp",
	},
}

local function DashCreateFrame(name, data)
	local frame = CreateFrame(
		data.object or "Frame",  -- default to "Frame" if not defined
		name,                    -- required
		data.parent or DashBoardFrame, -- default to UIParent
		data.template            -- optional
	)
	frame:EnableMouse(true)
	frame:SetHeight(SIZE)
	frame:SetScript("OnLeave", addon.HideTooltip)
	frame:SetFrameStrata("HIGH")
	if data.framewidth then
		frame:SetWidth(data.framewidth)
	end
	frame.text = frame:CreateFontString(nil, "OVERLAY")
	frame.text:SetPoint("RIGHT")
	frame.text:SetFont([[Fonts\FRIZQT__.TTF]], 12)
	frame.text:SetShadowOffset(1, -1)
	frame.text:SetJustifyH(data.justify or "RIGHT")
	frame.text:SetText(data.text or "188")
	
	if data.object == "Button" then
		frame:RegisterForClicks("AnyUp")
	end
	
	if data.texture then
		frame.texture = frame:CreateTexture()
		frame.texture:SetTexture(data.texturepath)
		frame.texture:SetHeight(data.textureheight or 12)
		frame.texture:SetWidth(data.texturewidth or 12)
		if data.textureanchor then
			frame.texture:SetPoint('RIGHT', frame.text, 'LEFT')
		end
	end
	
	return frame
end

for name, data in pairs(dashFramesToCreate) do
	DashCreateFrame(name, data)
end

-- Mail frame --
GUI_DashMail:SetWidth(GUI_DashMail.text:GetStringWidth() + GUI_DashMail.texture:GetWidth() - 8)
GUI_DashMail.texture:SetPoint('RIGHT', GUI_DashMail.text, 'LEFT')
-- Quests --
GUI_DashQuest.texture:SetTexCoord(0.25, 0.75, 0.25, 0.75)
GUI_DashQuest:SetWidth(GUI_DashQuest.text:GetStringWidth() + GUI_DashQuest.texture:GetWidth())
GUI_DashQuest.texture:SetPoint('RIGHT', GUI_DashQuest.text, 'LEFT')
-- Armor durability --
GUI_DashDurability.texture:SetTexCoord(0.07, 0.93, 0.07, 0.93)
GUI_DashDurability:SetWidth(GUI_DashDurability.text:GetStringWidth() + GUI_DashDurability.texture:GetWidth())
GUI_DashDurability.texture:SetPoint('RIGHT', GUI_DashDurability.text, 'LEFT')
-- Inventory --
addon.GUI_DashInventory = GUI_DashInventory -- Needs to be made global for secure attrib functions in other files
GUI_DashInventory:SetWidth(GUI_DashInventory.text:GetStringWidth() + GUI_DashInventory.texture:GetWidth())
GUI_DashInventory.texture:SetPoint('RIGHT', GUI_DashInventory.text, 'LEFT')
-- Clock --
GUI_DashClock:SetWidth(GUI_DashClock.text:GetStringWidth())
GUI_DashClock.texture:SetWidth((GUI_DashClock.text:GetStringWidth() - 6))
GUI_DashClock.texture:SetPoint("CENTER", GUI_DashClock, "CENTER", 5, 0)
GUI_DashClock.texture:Hide()
-- Latency --
GUI_DashLatency:SetWidth(GUI_DashLatency.text:GetStringWidth())
-- FPS --
GUI_DashFPS:SetWidth(GUI_DashFPS.text:GetStringWidth())
-- Social/Friends --
GUI_DashSocial:SetWidth(GUI_DashSocial.text:GetStringWidth() + GUI_DashSocial.texture:GetWidth() - 10)
GUI_DashSocial.texture:SetPoint('RIGHT', GUI_DashSocial.text, 'LEFT')
-- Guild Frame --
GuildMicroButtonTabard:SetParent(GUI_DashGuild)
GuildMicroButtonTabard:SetPoint('RIGHT', GUI_DashGuild.text, 'LEFT')
GuildMicroButtonTabard:SetHeight(5)
GuildMicroButtonTabard:SetWidth(5)
GuildMicroButtonTabard.emblem:SetHeight(9)
GuildMicroButtonTabard.emblem:SetWidth(9)
GuildMicroButtonTabard.background:SetHeight(26)
GuildMicroButtonTabard.background:SetWidth(21)
GuildMicroButtonTabard.emblem:SetPoint("CENTER", GuildMicroButtonTabard.background, "CENTER", 0, -4)
GUI_DashGuild.texture:SetPoint('RIGHT', GUI_DashGuild.text, 'LEFT', 0, 4)
GUI_DashGuild.texture2 = GUI_DashGuild:CreateTexture()
GUI_DashGuild.texture2:SetTexture("Interface/GUI_DashGuild/GuildEmblems_01.blp")
GUI_DashGuild.texture2:SetPoint('CENTER', GUI_DashGuild.texture1, 'CENTER', 0, -4)
GUI_DashGuild.texture2:SetHeight(9)
GUI_DashGuild.texture2:SetWidth(9)
GUI_DashGuild:SetWidth(GUI_DashGuild.text:GetStringWidth() + GUI_DashGuild.texture:GetWidth() - 10)
-- Speed --
GUI_DashSpeed.texture:SetPoint('LEFT', GUI_DashSpeed, 'LEFT')

--[[-----------------------------------------------------------------------------
OnEnter Functions
-------------------------------------------------------------------------------]]
-- Universal OnEnter Setup Func --
local function GUI_ToolTipSetup(self)
	if self.tooltip then
		GameTooltip:ClearLines()
	else
		if not addon.settings.dashOnTop or addon.settings.dashOnTop == false then
			GameTooltip:SetOwner(self, 'ANCHOR_TOP', 0, 1)
		else
			GameTooltip:SetOwner(self, 'ANCHOR_BOTTOM', 0, -5)
		end
	end
end
-- Clock --
local server_hour, server_minute = 0, 0
local function GUI_DashClock_OnEnter(self)
	if GUI_DashClock.tooltip then
		GameTooltip:ClearLines()
	else
		if not addon.settings.dashOnTop or addon.settings.dashOnTop == false then
			GameTooltip:SetOwner(GUI_DashClock, 'ANCHOR_TOP', 0, 1)
		else
			GameTooltip:SetOwner(GUI_DashClock, 'ANCHOR_BOTTOM', 0, -5)
		end
	end
	GameTooltip:AddDoubleLine("Today's Date", date("%A, %B %d, %Y"))
	GameTooltip:AddLine(" ")
	GameTooltip:AddDoubleLine("Local Time", GUI_DashClock.text:GetText())
	GameTooltip:AddDoubleLine("Server Time", ("%d:%.02d %s"):format(server_hour ~= 0 and server_hour or 12, server_minute, "h"))
	GameTooltip:AddLine(" ")
	GameTooltip:AddLine("|cffeda55fLeft Click|r toggles the Time Manager", 0.2, 1, 0.2)
	GameTooltip:AddLine("|cffeda55fRight Click|r toggles the Calendar", 0.2, 1, 0.2)
	if not GUI_DashClock.tooltip then
		GameTooltip:Show()
		GUI_DashClock.tooltip = true
	end
end
GUI_DashClock:SetScript('OnEnter', GUI_DashClock_OnEnter)

-- Mail frame --
local function GUI_DashMail_OnEnter(self)
	if not HasNewMail() then return end
	GUI_ToolTipSetup(self)
		MinimapMailFrameUpdate()
	if not self.tooltip then
		GameTooltip:Show()
		self.tooltip = true
	end
end
GUI_DashMail:SetScript('OnEnter', GUI_DashMail_OnEnter)

-- Durability Frame --
local equipCost = 0;
local bagCost = 0;
local totalCost = 0;
local pEquipDura = { min=0, max=0};
local pBagDura = { min=0, max=0};
local slots = { "HeadSlot", "ShoulderSlot", "ChestSlot", "WaistSlot", "WristSlot", "HandsSlot", "LegsSlot", "FeetSlot", "MainHandSlot", "SecondaryHandSlot", "RangedSlot" }
slots[0] = 'AmmoSlot'
function GUI_DashDurability:GetDurabilityInfo()
	pEquipDura = { min=0, max=0};
	pBagDura = { min=0, max=0};
	if not tmpTip then tmpTip = CreateFrame("GameTooltip", "GUITT") end
	equipCost = 0
	for _, slotName in ipairs(slots) do
		local item = _G["Character" .. slotName]
		local hasItem, _, repairCost = tmpTip:SetInventoryItem("player", item:GetID())
		local Minimum, Maximum = GetInventoryItemDurability(item:GetID())
		if hasItem and repairCost and repairCost > 0 then
			equipCost = equipCost + repairCost
		end
		if Minimum and Maximum then
			pEquipDura.min = pEquipDura.min + Minimum
			pEquipDura.max = pEquipDura.max + Maximum
		end
	end
	bagCost = 0
	for bag = 0, 4 do
		for slot = 1, GetContainerNumSlots(bag) do
			local hasCooldown, repairCost = tmpTip:SetBagItem(bag, slot)
			local Minimum, Maximum = GetContainerItemDurability(bag, slot)
			if repairCost and repairCost > 0 then
				bagCost = bagCost + repairCost
			end
			if Minimum and Maximum then
				pBagDura.min = pBagDura.min + Minimum
				pBagDura.max = pBagDura.max + Maximum
			end
		end
	end
	if bagCost < 0 then bagCost = 0 end
	totalCost = equipCost + bagCost
end
local function GUI_DashDurability_OnEnter(self)
	local cP = (pEquipDura.max > 0 and floor(pEquipDura.min / pEquipDura.max * 100)) or 100
	local bP = (pBagDura.max > 0 and floor(pBagDura.min / pBagDura.max * 100)) or 100
	local tP = ((pEquipDura.max + pBagDura.max) > 0 and floor( (pEquipDura.min + pBagDura.min) / (pEquipDura.max + pBagDura.max) * 100)) or 100
	if cP > 100 then cP = 100 end
	if bP > 100 then bP = 100 end
	if tP > 100 then tP = 100 end
	GUI_ToolTipSetup(self)
	GameTooltip:AddLine(_G['REPAIR_COST'])
	GameTooltip:AddLine(" ")
	GameTooltip:AddDoubleLine(_G['CURRENTLY_EQUIPPED'].." ("..addon:DurColor(cP)..cP.."%|r".."):", addon:MoneyToString(equipCost, true))
	GameTooltip:AddDoubleLine("Inventory".." ("..addon:DurColor(bP)..bP.."%|r".."):", addon:MoneyToString(bagCost, true))
	GameTooltip:AddLine(" ")
	GameTooltip:AddDoubleLine(_G['REPAIR_ALL_ITEMS'].." ("..addon:DurColor(tP)..tP.."%|r".."):", addon:MoneyToString(totalCost, true))
	GameTooltip:AddDoubleLine("Friendly Discount", addon:MoneyToString(addon:truncate((totalCost * 0.95), 0), true))
	GameTooltip:AddDoubleLine("Honored Discount", addon:MoneyToString(addon:truncate((totalCost * 0.9), 0), true))
	GameTooltip:AddDoubleLine("Revered Discount", addon:MoneyToString(addon:truncate((totalCost * 0.85), 0), true))
	GameTooltip:AddDoubleLine("Exaulted Discount", addon:MoneyToString(addon:truncate((totalCost * 0.8), 0), true))
	GameTooltip:AddLine(" ")
	GameTooltip:AddLine("|cffeda55fLeft Click|r toggle Auto-Repair  " .. (addon.settings.autoRepair and "|cff88ff88on|r" or "|cffff8888off|r"), 0.2, 1, 0.2)
	GameTooltip:AddLine("|cffeda55fRight Click|r toggle Guild Funds  " .. (addon.settings.GuildRepair and "|cff88ff88on|r" or "|cffff8888off|r"), 0.2, 1, 0.2)
	if not self.tooltip then
		GameTooltip:Show()
		self.tooltip = true
	end
end
GUI_DashDurability:SetScript('OnEnter', GUI_DashDurability_OnEnter)

-- Inventory --
local function GUI_DashInventory_OnEnter(self)
	GUI_ToolTipSetup(self)
	local keyBinding = GetBindingKey("TOGGLEBACKPACK");
	GameTooltip:AddLine(""..NORMAL_FONT_COLOR_CODE.."Backpack ("..keyBinding..")"..FONT_COLOR_CODE_CLOSE);
	GameTooltip:AddLine(" ")
	GameTooltip:AddLine(string.format(NUM_FREE_SLOTS, (MainMenuBarBackpackButton.freeSlots or 0)));
	GameTooltip:AddLine(" ")
	GameTooltip:AddLine("|cffeda55fLeft Click|r toggle Inventory", 0.2, 1, 0.2)
	GameTooltip:AddLine("|cffeda55fRight Click|r toggle Bag Bar", 0.2, 1, 0.2)
	if not self.tooltip then
		GameTooltip:Show()
		self.tooltip = true
	end
end
GUI_DashInventory:SetScript('OnEnter', GUI_DashInventory_OnEnter)

-- Quest --
local function GUI_DashQuest_OnEnter(self)
	GUI_ToolTipSetup(self)
	GameTooltip:AddLine(MicroButtonTooltipText(QUESTLOG_BUTTON, "TOGGLEQUESTLOG"));
	if not self.tooltip then
		GameTooltip:Show()
		self.tooltip = true
	end
end
GUI_DashQuest:SetScript('OnEnter', GUI_DashQuest_OnEnter)

-- Social --
local function GUI_DashSocial_OnEnter(self)
	GUI_ToolTipSetup(self)
	local numBNetFriends, numBNetOnline = BNGetNumFriends();
	local numWoWFriends, numWoWOnline = GetNumFriends();
	local sPlural = "s";
	if (numBNetOnline + numWoWOnline) == 1 then
		sPlural = "";
	end
	GameTooltip:AddLine(MicroButtonTooltipText(SOCIALS ,"TOGGLESOCIAL"));
	GameTooltip:AddLine(" ")
	GameTooltip:AddLine((numBNetOnline + numWoWOnline) .. " Friend" .. sPlural .. " Online", 0, 1, 0);
	-- Battle.net Friends
	for i = 1, numBNetFriends, 1 do
		local sPresenceID, sNameFirst, sNameLast, sCharName, sCharID, sClient, bIsOnline = BNGetFriendInfo(i);
		if bIsOnline then
			local sArea = sClient;
			if sClient == "WoW" then
				local _, _, _, sServer = BNGetToonInfo(sPresenceID);
				sArea = sServer;
			end
			GameTooltip:AddLine(sCharName .. " (" .. sArea .. ") [" .. sNameFirst .. " " .. sNameLast .. "]", 0, 1, 1 );
		end
	end
	-- Regular Friends
	for i = 1, numWoWFriends, 1 do
		local sName, iLevel, sClass, sArea, bConnected, sNote, fStatus = GetFriendInfo(i);
		local color = colors[CLASS[sClass]]
		if bConnected then
			GameTooltip:AddLine(sName, color.r, color.g, color.b);
		end
	end
	if not self.tooltip then
		GameTooltip:Show()
		self.tooltip = true
	end
end
GUI_DashSocial:SetScript('OnEnter', GUI_DashSocial_OnEnter)

-- Guild --
local function GUI_DashGuild_OnEnter(self)
	GUI_ToolTipSetup(self)
	GameTooltip:AddLine(MicroButtonTooltipText(GUILD, "TOGGLEGUILDTAB"));
	GameTooltip:AddLine(" ")
	if IsInGuild() == nil then
		GameTooltip:AddLine("Not in a Guild")
	else
	local total = GetNumGuildMembers(true)
	local onlineTotal = 0
	local offlineTotal = 0
	for i = 1, total 
	   do 
	   local name, rank, rankIndex, level, class, zone, note, officernote, online, status, classFileName = GetGuildRosterInfo(i)
	   if online and name ~= GetUnitName("player")
	   then
		  onlineTotal = onlineTotal + 1
	   else
		  offlineTotal = offlineTotal + 1
	   end
	end
	local sPlural = "s";
	if  onlineTotal == 1 then
		sPlural = "";
	end
	GameTooltip:AddLine((onlineTotal) .. " Guildie" .. sPlural .. " Online", 0, 1, 0);
	for index = 1, total, 1 do
		local gName, gRank,_, gLevel, gClass,_,_,_, gConnected, gStatus, gFileName = GetGuildRosterInfo(index);
		local color = colors[CLASS[gClass]]
		if gConnected and gName ~= GetUnitName("player") then
			GameTooltip:AddDoubleLine(gName, gLevel,  color.r, color.g, color.b);
		end
	end
	end
	if not self.tooltip then
		GameTooltip:Show()
		self.tooltip = true
	end
end
GUI_DashGuild:SetScript('OnEnter', GUI_DashGuild_OnEnter)

-- Money --
local moneyGained, moneySpent = 0, 0
local function GUI_DashMoney_OnEnter(self)
	GUI_ToolTipSetup(self)
	GameTooltip:AddLine("Cash flow:")
	if moneyGained > 0 or moneySpent > 0 then
		GameTooltip:AddLine(" ")
		GameTooltip:AddLine("This session")
		GameTooltip:AddDoubleLine("Gained", addon:MoneyToString(moneyGained, true), 1, 1, 1, 1, 1, 1)
		GameTooltip:AddDoubleLine("Spent", addon:MoneyToString(moneySpent, true), 1, 1, 1, 1, 1, 1)
		if moneyGained - moneySpent > 0 then
			GameTooltip:AddDoubleLine(" ", "|cff00ff00(+)|r " .. addon:MoneyToString(moneyGained - moneySpent, true), 1, 1, 1, 1, 1, 1)
		else
			GameTooltip:AddDoubleLine(" ", "|cffff0000(-)|r " .. addon:MoneyToString(moneySpent - moneyGained, true), 1, 1, 1, 1, 1, 1)
		end
	end
	GameTooltip:AddLine(" ")
	local total, colors, color = 0, CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS
	for name, settings in pairs(_G[addonName .. "Settings"][GetRealmName()]) do
			color = colors[settings.class]
			GameTooltip:AddDoubleLine(name, addon:MoneyToString(settings.money, true), color.r, color.g, color.b, 1, 1, 1)
			if type(settings.money) ~= 'number' then
				settings.money = 0
			end
			total = total + settings.money
	end
	GameTooltip:AddLine(" ")
	GameTooltip:AddDoubleLine("Total", addon:MoneyToString(total, true), NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1, 1, 1)
	if not self.tooltip then
		GameTooltip:Show()
		self.tooltip = true
	end
end
GUI_DashMoney:SetScript("OnEnter", GUI_DashMoney_OnEnter)


--[[-----------------------------------------------------------------------------
OnUpdate Functions
-------------------------------------------------------------------------------]]
-- Speed --
GUI_DashSpeed:SetScript('OnUpdate', function(self)
	local s = string.format("%d%%", (GetUnitSpeed("Player") / 7) * 100);
	GUI_DashSpeed.text:SetText(s)
end)
-- Clock --
function addon:SetClockHrFormat(self)
	if addon.settings.clock24hr == false then
		GUI_DashClock.text:SetText(("%d:%s"):format(tonumber(date("%I")), date("%M%p"):lower()))
	else
		GUI_DashClock.text:SetText(("%d:%s"):format(tonumber(date("%H")), date("%M h"):lower()))
	end
end
local previousMinute, ctimer = -1, 5
GUI_DashClock:SetScript('OnUpdate', function(self, elapsed)
	ctimer = ctimer + elapsed
	if ctimer < 5 then return end
	ctimer = 0
	server_hour, server_minute = GetGameTime()
	if server_minute == previousMinute then return end
	previousMinute = server_minute
	addon:SetClockHrFormat()
	if GUI_DashClock.tooltip then
		GUI_DashClock.tooltip = nil
		GUI_DashClock_OnEnter()
	end
end)
-- Latency --
local ltimer = 10
GUI_DashLatency:SetScript('OnUpdate', function(self, elapsed)
	ltimer = ltimer + elapsed
	if ltimer < PERFORMANCEBAR_UPDATE_INTERVAL then return end
	ltimer = 0
	local _, _, latency = GetNetStats()
	GUI_DashLatency.text:SetTextColor(min(latency / LATENCY_MID_RANGE, 1), 1 - min(max(latency - LATENCY_MID_RANGE, 0) / LATENCY_MID_RANGE, 1), 0)
	GUI_DashLatency.text:SetFormattedText("%sms", latency)
end)
-- FPS --
local ftimer = 1
GUI_DashFPS:SetScript('OnUpdate', function(self, elapsed)
	ftimer = ftimer + elapsed
	if ftimer < 1 then return end
	ftimer = 0
	local fps = floor(GetFramerate() + 0.5)
	GUI_DashFPS.text:SetTextColor(1 - min(max(fps - FPS_MID_RANGE, 0) / FPS_MID_RANGE, 1), min(fps / FPS_MID_RANGE, 1), 0)
	GUI_DashFPS.text:SetFormattedText("%sfps", fps)
end)

--[[-----------------------------------------------------------------------------
OnClick Functions
-------------------------------------------------------------------------------]]
-- Clock --
GUI_DashClock:SetScript('OnClick', function(self, button)
	if button == 'LeftButton' then
		ToggleTimeManager()
	else
		ToggleCalendar()
	end
end)
-- Durability --
GUI_DashDurability:SetScript('OnClick', function(self, button)
	if button == 'LeftButton' then
		if addon.settings.autoRepair == true then
			addon.settings.autoRepair = false
			UIErrorsFrame:AddMessage("Auto-Repair: Off", 1, 0, 0, 53, 3);
		elseif addon.settings.autoRepair == false then
			addon.settings.autoRepair = true
			UIErrorsFrame:AddMessage("Auto-Repair: On", 0, 1, 0, 53, 3);
		end
		self.tooltip = nil
		GUI_DashDurability_OnEnter(self)
	end	
	if button == 'RightButton' then
		if addon.settings.GuildRepair == true then
			addon.settings.GuildRepair = false
			UIErrorsFrame:AddMessage("Guild-Repair: Off", 1, 0, 0, 53, 3);
		elseif addon.settings.GuildRepair == false then
			addon.settings.GuildRepair = true
			UIErrorsFrame:AddMessage("Guild-Repair: On", 0, 1, 0, 53, 3);
		end
		self.tooltip = nil
		GUI_DashDurability_OnEnter(self)
	end	
end)
-- Inventory --
GUI_DashInventory:SetAttribute('_onclick', [[
	if button == 'LeftButton' then
		control:CallMethod("ToggleBags")
	else
		local bagBar = self:GetFrameRef("bagBar")
		if bagBar:IsVisible() then
			bagBar:Hide()
		else
			bagBar:Show()
		end
	end
]])
function GUI_DashInventory:ToggleBags()
	if Baggins then
		Baggins:ToggleBackpack()
	else
		if ContainerFrame1:IsShown() then
			CloseAllBags()
		else
			OpenAllBags()
		end
	end
end
-- Social --
GUI_DashSocial:SetScript('OnClick', function(self)
	ToggleFriendsFrame()
end)
-- Guild --
GUI_DashGuild:SetScript('OnClick', function(self, button)
	ToggleGuildFrame()
end)
-- Quest --
GUI_DashQuest:SetScript('OnClick', function(self)
	ToggleFrame(QuestLogFrame)
end)

--[[-----------------------------------------------------------------------------
OnEvent Functions
-------------------------------------------------------------------------------]]
-- Mail --
local function GUI_DashMail_Init(self, event)
	GUI_DashMail.text:SetText(addon.settings.CurrentMail)
end
local function GUI_DashMail_OnEvent(self, event)
	if HasNewMail() then
		GUI_DashMail.text:SetTextColor(0, 1, 0)
		GUI_DashMail.texture:SetVertexColor(0, 1, 0)
	else
		GUI_DashMail.text:SetTextColor(1, 1, 1)
		GUI_DashMail.texture:SetVertexColor(1, 1, 1)
	end
	if event == "MAIL_INBOX_UPDATE" then
		GUI_DashMail.text:SetText(GetInboxNumItems())
		addon.settings.CurrentMail = GetInboxNumItems()
	end
	if GUI_DashMail.tooltip then
		MinimapMailFrameUpdate()
	end
end
-- Quests --
local function GUI_DashQuest_OnEvent(self, event)
	local numEntries, numQuests = GetNumQuestLogEntries()
	GUI_DashQuest.text:SetFormattedText("%s/25", numQuests)
end
-- Durability --
function GUI_DashDurability:UpdatePercent()
	local tPer = floor(pEquipDura.min / pEquipDura.max * 100)
	GUI_DashDurability.text:SetText(addon:DurColor(tPer)..tPer.."%|r");
end
local function GUI_DashDurability_OnEvent(self, event)
	GUI_DashDurability:GetDurabilityInfo()
	GUI_DashDurability:UpdatePercent()
end
addon.RegisterEvent("DashBoard-AutoRepair", 'MERCHANT_SHOW', function()
	if addon.settings.autoRepair and CanMerchantRepair() then
		if addon.settings.GuildRepair == true then
			local cost = GetRepairAllCost()
			if cost > 0 and cost <= GetMoney() then
				RepairAllItems(1)
				print("|cff33ff99" .. addonName .. "|r: Repaired all equipment for " .. addon:MoneyToString(cost) .."(Guild Funds)")
			end
		else
			local cost = GetRepairAllCost()
			if cost > 0 and cost <= GetMoney() then
				RepairAllItems()
				print("|cff33ff99" .. addonName .. "|r: Repaired all equipment for " .. addon:MoneyToString(cost) .. "(Your Funds)")
			end
		end
	end
end)
-- Inventory --
local function GUI_DashInventory_OnEvent(self, event)
	local free, total = 0, 0
	for bag = 0, NUM_BAG_FRAMES do
		free = free + GetContainerNumFreeSlots(bag)
		total = total + GetContainerNumSlots(bag)
	end
	local freePercent = floor(free / total * 100 + 0.5)
	local BAG_SPACE_MID_RANGE = (total / 2)
	GUI_DashInventory.text:SetTextColor(1 - min(max(freePercent - BAG_SPACE_MID_RANGE, 0) / BAG_SPACE_MID_RANGE, 1), min(freePercent / BAG_SPACE_MID_RANGE, 1), 0)
	GUI_DashInventory.text:SetFormattedText("%s/%s", free, total)
end
GUI_DashInventory:SetScript('OnEvent', function(self)
	GUI_DashInventory_OnEvent()
end)
-- Money --
local LDBObj
local function GUI_DashMoney_OnEvent(self, event)
	GUI_DashMoney:SetWidth(0)
	GUI_DashMoney.text:SetText(addon:MoneyToString(GetMoney(), true))
	GUI_DashMoney:SetWidth(GUI_DashMoney.text:GetStringWidth())
end
local function GUI_DashMoney_Init(self, event)
	if type(addon.settings.money) ~= 'number' then
		addon.settings.money = GetMoney() or 0
	end
	addon:RegisterDefaultSetting("money", 0)
	if LDBObj then
		LDBObj.text = addon:MoneyToString(addon.settings.money, true)
	end
end
-- Clock --
local function GetInvites()
	if CalendarGetNumPendingInvites() ~= 0 then
		GUI_DashClock.texture:Show()
	else
		GUI_DashClock.texture:Hide()
	end
	if CalendarFrame and CalendarFrame:IsShown() then
		GUI_DashClock.texture:Hide()
	end
end
local function GetGuildEvents()
	local numguildEvents = CalendarGetNumGuildEvents()
	local currentweekday, currentmonth, currentday, currentyear = CalendarGetDate()
	for eventIndex = 1, numguildEvents do
		local month, day, weekday, hour, minute, eventType, title, calendarType, textureName = CalendarGetGuildEventInfo(eventIndex)
		local monthOffset = month - currentmonth
		local numEvents = CalendarGetNumDayEvents(monthOffset, day)
		if numEvents ~= 0 then
			GUI_DashClock.texture:Show()
		else
			GUI_DashClock.texture:Hide()
		end
	end
	if CalendarFrame and CalendarFrame:IsShown() then
		GUI_DashClock.texture:Hide()
	end
end 
local function GUI_DashClock_Init(self, event)
	local _, todaysmonth, _, todaysyear = CalendarGetDate()
	CalendarSetAbsMonth(todaysmonth, todaysyear)
	OpenCalendar()
	GetInvites()
	GetGuildEvents()
end
local function GUI_DashClock_OnEvent(self, event)
	GetInvites()
	GetGuildEvents()
end
-- Social/Friends --
local function GUI_DashSocial_OnEvent(self, event)
	local numberOfFriends, onlineFriends = GetNumFriends()
	local BNnumberOfFriends, BNonlineFriends = BNGetNumFriends()
	if onlineFriends > 0 then
		GUI_DashSocial.text:SetTextColor(0, 1, 0)
	elseif BNonlineFriends > 0 then
		GUI_DashSocial.text:SetTextColor(0, 1, 0)
	else
		GUI_DashSocial.text:SetTextColor(1, 1, 1)
	end
	GUI_DashSocial.text:SetText(onlineFriends + BNonlineFriends)
	if GUI_DashSocial.tooltip then
		FriendsList_Update()
	end
end
-- Guild Frame --
local function GUI_DashGuild_OnEvent(self, event)
	GuildRoster()
	local total = GetNumGuildMembers(true)
	local onlineTotal = 0
	local offlineTotal = 0
	for i = 1, total do 
		local name, rank, rankIndex, level, class, zone, note, officernote, online, status, classFileName = GetGuildRosterInfo(i)
		if online and name ~= GetUnitName("player") then
			onlineTotal = onlineTotal + 1
		else
			offlineTotal = offlineTotal + 1
		end
	end
	if onlineTotal > 0 then
		GUI_DashGuild.text:SetTextColor(0, 1, 0)
	else
		GUI_DashGuild.text:SetTextColor(1, 1, 1)
	end
	GUI_DashGuild.text:SetText(onlineTotal)
	if IsInGuild() == nil then 
		GUI_DashGuild.texture:Show()
		GUI_DashGuild.texture2:Show()
	else
		GUI_DashGuild.texture:Hide()
		GUI_DashGuild.texture2:Hide()
	end
end

--[[-----------------------------------------------------------------------------
DashBoard Layout
-------------------------------------------------------------------------------]]
function addon:DashLayout()
	if not addon.settings.dashOnTop or addon.settings.dashOnTop == false then
		DashBoardFrame:ClearAllPoints()
		DashBoardFrame:SetPoint('TOPRIGHT', addon.skin, 'TOPRIGHT', -20, -11)
		DashBoardFrame:SetHeight(200)
		DashBoardFrame:SetWidth(500)
		DBFbg:SetTexture(0, 0, 0, 0)
		GUI_DashClock:SetPoint('TOPRIGHT', DashBoardFrame, 'TOPRIGHT', 0, 0)
		GUI_DashSocial:SetPoint('RIGHT', GUI_DashClock, 'LEFT', 0, 0)
		GUI_DashGuild:SetPoint('RIGHT', GUI_DashSocial, 'LEFT', 0, 0)
		GUI_DashQuest:SetPoint('RIGHT', GUI_DashGuild, 'LEFT', -5, 0)
		GUI_DashInventory:SetPoint('RIGHT', GUI_DashQuest, 'LEFT')
		GUI_DashMail:ClearAllPoints()
		GUI_DashMail:SetPoint('TOPRIGHT', GUI_DashClock, 'BOTTOMRIGHT', 0, -2)
		if addon.settings.speedShow == true then
			GUI_DashSpeed:Show()
			GUI_DashSpeed:SetPoint('RIGHT', GUI_DashMail, 'LEFT', 0, 0)	
			GUI_DashDurability:SetPoint('RIGHT', GUI_DashSpeed, 'LEFT', -5, 0)
			GUI_DashMoney:SetPoint('RIGHT', GUI_DashDurability, 'LEFT')
		elseif addon.settings.speedShow == false then
			GUI_DashSpeed:Hide()
			GUI_DashDurability:SetPoint('RIGHT', GUI_DashMail, 'LEFT', -5, 0)
			GUI_DashMoney:SetPoint('RIGHT', GUI_DashDurability, 'LEFT')
		end
		if addon.settings.latencyShow == true then
			GUI_DashLatency:Show()
			GUI_DashFPS:Show()
			GUI_DashLatency:ClearAllPoints()
			GUI_DashLatency:SetPoint('TOPRIGHT', GUI_DashMail, 'BOTTOMRIGHT', 0, 0)
			GUI_DashFPS:SetPoint('RIGHT', GUI_DashLatency, 'LEFT')
		elseif addon.settings.latencyShow == false then
			GUI_DashLatency:Hide()
			GUI_DashFPS:Hide()
		end
	else
		DashBoardFrame:ClearAllPoints()
		DashBoardFrame:SetPoint('TOP', UIParent, 'TOP', 0, 0)
		DashBoardFrame:SetHeight(20)
		DBFbg:SetTexture(0, 0, 0, .7)
		GUI_DashClock:SetPoint('TOPRIGHT', DashBoardFrame, 'TOPRIGHT', 0, 0)
		GUI_DashGuild:SetPoint('RIGHT', GUI_DashSocial, 'LEFT', 0, 0)
		GUI_DashQuest:SetPoint('RIGHT', GUI_DashGuild, 'LEFT', -5, 0)
		GUI_DashDurability:SetPoint('RIGHT', GUI_DashQuest, 'LEFT', -5, 0)
		GUI_DashInventory:SetPoint('RIGHT', GUI_DashDurability, 'LEFT')
		GUI_DashMoney:SetPoint('RIGHT', GUI_DashInventory, 'LEFT')
		if addon.settings.latencyShow == true and addon.settings.speedShow == false then
			DashBoardFrame:SetWidth(570)
		elseif addon.settings.latencyShow == false and addon.settings.speedShow == true then
			DashBoardFrame:SetWidth(520)
		elseif addon.settings.latencyShow == false and addon.settings.speedShow == false then
			DashBoardFrame:SetWidth(475)
		else
			DashBoardFrame:SetWidth(620)
		end
		if addon.settings.speedShow == true then
			GUI_DashSpeed:Show()
			GUI_DashSpeed:SetPoint('RIGHT', GUI_DashMail, 'LEFT', 0, 0)	
			GUI_DashSocial:SetPoint('RIGHT', GUI_DashSpeed, 'LEFT', 0, 0)
		elseif addon.settings.speedShow == false then
			GUI_DashSpeed:Hide()
			GUI_DashSocial:SetPoint('RIGHT', GUI_DashMail, 'LEFT', -5, 0)
		end
		if addon.settings.latencyShow == true then
			GUI_DashLatency:Show()
			GUI_DashFPS:Show()
			GUI_DashLatency:ClearAllPoints()
			GUI_DashLatency:SetPoint('RIGHT', GUI_DashClock, 'LEFT', 0, 0)
			GUI_DashFPS:SetPoint('RIGHT', GUI_DashLatency, 'LEFT')
			GUI_DashMail:ClearAllPoints()
			GUI_DashMail:SetPoint('RIGHT', GUI_DashFPS, 'LEFT', 0, -2)
		elseif addon.settings.latencyShow == false then
			GUI_DashMail:ClearAllPoints()
			GUI_DashMail:SetPoint('RIGHT', GUI_DashClock, 'LEFT', 0, -2)
			GUI_DashLatency:Hide()
			GUI_DashFPS:Hide()
		end
	end
	-- set scale
	DashBoardFrame:SetScale(addon.settings.dashboardScale)
end

	addon.RegisterEvent("DashBoard-Initialize", 'PLAYER_LOGIN', function(self, event)
	addon.UnregisterEvent(self, event)
	addon:DashLayout()
	GUI_DashMoney_Init(event)
	GUI_DashMoney_OnEvent()
	GUI_DashClock_Init(event)
	GUI_DashGuild_OnEvent()
	GUI_DashSocial_OnEvent()
	GUI_DashInventory_OnEvent()
	GUI_DashMail_Init()
	GUI_DashMail_OnEvent(event)
	GUI_DashQuest_OnEvent()
	GUI_DashDurability_OnEvent()
end)

addon.RegisterEvents("DashBoardFrame", GUI_DashMail_OnEvent, 'MAIL_INBOX_UPDATE', 'UPDATE_PENDING_MAIL')
addon.RegisterEvents("DashBoardFrame", GUI_DashQuest_OnEvent, 'QUEST_LOG_UPDATE')
addon.RegisterEvents("DashBoardFrame", GUI_DashDurability_OnEvent, 'UPDATE_INVENTORY_ALERTS', 'UPDATE_INVENTORY_DURABILITY', 'UNIT_INVENTORY_CHANGED', 'MERCHANT_CLOSED', 'PLAYER_DEAD', 'PLAYER_REGEN_ENABLED')
addon.RegisterEvents("DashBoardFrame", GUI_DashInventory_OnEvent, 'UNIT_INVENTORY_CHANGED', 'BAG_UPDATE')
addon.RegisterEvents("DashBoardFrame", GUI_DashMoney_OnEvent, 'PLAYER_MONEY')
addon.RegisterEvents("DashBoardFrame", GUI_DashClock_OnEvent, 'CALENDAR_UPDATE_PENDING_INVITES', 'CALENDAR_UPDATE_EVENT_LIST')
addon.RegisterEvents("DashBoardFrame", GUI_DashSocial_OnEvent, 'FRIENDLIST_UPDATE', 'BN_FRIEND_ACCOUNT_ONLINE', 'BN_FRIEND_ACCOUNT_OFFLINE')
addon.RegisterEvents("DashBoardFrame", GUI_DashGuild_OnEvent, 'GUILD_ROSTER_UPDATE', 'PLAYER_GUILD_UPDATE')

--[[-----------------------------------------------------------------------------
Money tooltip overrides
-------------------------------------------------------------------------------]]
addon.RegisterEvent("DashBoard-MoneyTooltip-Update", 'PLAYER_MONEY', function()
	local money = GetMoney()
	local diff = money - addon.settings.money
	if diff > 0 then
		moneyGained = moneyGained + diff
	else
		moneySpent = moneySpent - diff
	end
	addon.settings.money = money
	if LDBObj then
		LDBObj.text = addon:MoneyToString(money, true)
	end
end)
-- Simple bag frame support:
-- 	true means multiple frames and reanchoring
-- 	false means a single frame
local bagNames = {
	['ContainerFrame1MoneyFrame'] = true,			-- Blizzard Backpack
	['MerchantMoneyFrame'] = true,					-- Blizzard Merchant Frame
	['OneBagFrameMoneyFrame'] = true,				-- OneBag
	['BagginsMoneyFrame'] = false,					-- Baggins
	['CombuctorFrame1MoneyFrameClick'] = false,	-- Combuctor Bag
	['CombuctorFrame2MoneyFrameClick'] = false,	-- Combuctor Bank
	['ARKINV_Frame1StatusGold'] = true,				-- ArkInventory Bag
	['ARKINV_Frame3StatusGold'] = true,				-- ArkInventory Bank
	['BBCont1_1MoneyFrame'] = true,					-- BaudBag bag
	['BBCont2_1MoneyFrame'] = true,					-- BaudBag bank
	['FBoH_BagViewFrame_1_GoldFrame'] = true,		-- FBoH
	['FBoH_BagViewFrame_2_GoldFrame'] = true,		-- FBoH
	['BagnonMoney0'] = true,							-- Bagnon
	['BagnonMoney1'] = true,							-- Bagnon
	['TokenFrameMoneyFrame'] = true,					-- GUI
}
local cargBagsHooked, frames = false, {}
addon.RegisterEvent("DashBoard-MoneyTooltipHooks", 'ADDON_LOADED', function(self, event)
	if cargBags and not cargBagsHooked then
		cargBagsHooked = true
		for _, object in pairs(cargBags.Objects) do
			if object.Money then
				bagNames[object.Money:GetName()] = true
			end
		end
	end
	for name, hasCoins in pairs(bagNames) do
		if _G[name] then
			frames[#frames + 1] = _G[name]
			if hasCoins then
				frames[#frames + 1] = _G[name .. 'CopperButton']
				frames[#frames + 1] = _G[name .. 'SilverButton']
				frames[#frames + 1] = _G[name .. 'GoldButton']
				_G[name .. 'CopperButton'].tooltipAnchor = _G[name]
				_G[name .. 'SilverButton'].tooltipAnchor = _G[name]
				_G[name .. 'GoldButton'].tooltipAnchor = _G[name]
			end
			bagNames[name] = nil
		end
	end
	for index = #frames, 1, -1 do
		local frame = frames[index]
		frame:EnableMouse(true)
		frame:HookScript('OnEnter', GUI_DashMoney_OnEnter)
		frame:HookScript('OnLeave', addon.HideTooltip)
		frames[index] = nil
	end
	if not LDBObj and LibStub and LibStub('LibDataBroker-1.1', true) then
		LDBObj = LibStub('LibDataBroker-1.1'):NewDataObject(addonName .. "Money", {
			type = 'data source',
			label = addonName .. "Money",
			OnEnter = OnEnter,
			OnLeave = addon.HideTooltip
		})
	end
	if next(bagNames) then return end
	addon.UnregisterEvent(self, event)
end)