Quantcast
--[[
##############################################################################
_____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_       #
 ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__      #
  __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____     #
   ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____    #
    ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____   #
     _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____  #
      __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ #
       _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_#
        ___\///////////___________\///___________\/////////_____\///////////_#
##############################################################################
S U P E R - V I L L A I N - U I   By: Munglunch                              #
##############################################################################
##########################################################
LOCALIZED LUA FUNCTIONS
##########################################################
]]--
--[[ GLOBALS ]]--
local _G = _G;
local unpack 	= _G.unpack;
local select 	= _G.select;
local pairs 	= _G.pairs;
local type 		= _G.type;
local tinsert 	= _G.tinsert;
local string 	= _G.string;
local math 		= _G.math;
local table 	= _G.table;
--[[ STRING METHODS ]]--
local format = string.format;
--[[ MATH METHODS ]]--
local floor = math.floor;
--[[ TABLE METHODS ]]--
local twipe,tcopy,tsort = table.wipe, table.copy, table.sort;
--[[
##########################################################
GET ADDON DATA
##########################################################
]]--
local SVUIAddOnName, LOG = ...;
local SuperVillain, L = unpack(SVUI);
local NewHook = hooksecurefunc;
local SVUILogEventHandler = CreateFrame("Frame", nil)
local version = GetAddOnMetadata(..., "Version");

LOG = SuperVillain:Prototype(SVUIAddOnName, version)

_G["LogVillain"] = LOG;
local CHAT = SuperVillain.SVChat;
--[[
##########################################################
LOCAL VARIABLES
##########################################################
]]--
local nameKey = UnitName("player");
local realmKey = GetRealmName();
local NewHook = hooksecurefunc;
local LoggingEvents = {
	"CHAT_MSG_CHANNEL",
	"CHAT_MSG_EMOTE",
	"CHAT_MSG_GUILD_ACHIEVEMENT",
	"CHAT_MSG_RAID_WARNING",
	"CHAT_MSG_SAY",
	"CHAT_MSG_YELL",
	"CHAT_MSG_WHISPER_INFORM",
	"CHAT_MSG_WHISPER",
	"CHAT_MSG_GUILD",
	"CHAT_MSG_OFFICER",
	"CHAT_MSG_PARTY",
	"CHAT_MSG_PARTY_LEADER",
	"CHAT_MSG_RAID",
	"CHAT_MSG_RAID_LEADER",
	"CHAT_MSG_INSTANCE_CHAT",
	"CHAT_MSG_INSTANCE_CHAT_LEADER",
	"CHAT_MSG_BN_CONVERSATION",
	"CHAT_MSG_BN_WHISPER",
	"CHAT_MSG_BN_WHISPER_INFORM"
};
--[[
##########################################################
CORE DATA
##########################################################
]]--
LOG.stash = {};
LOG.myStash = {};
LOG.BagItemCache = {};
LOG.HasAltInventory = false;
LOG.OptionsCache = {};
--[[
##########################################################
LOCAL FUNCTIONS
##########################################################
]]--
local RefreshLoggedSlot = function(self, bag, slotID, save)
	if self.Bags[bag] and self.Bags[bag].numSlots ~= GetContainerNumSlots(bag) or not self.Bags[bag] or not self.Bags[bag][slotID] then return end
	local slot, _ = self.Bags[bag][slotID], nil;
	local bagType = self.Bags[bag].bagFamily;
	local texture, count, locked = GetContainerItemInfo(bag, slotID)
	local itemLink = GetContainerItemLink(bag, slotID);
	local key;
	slot:Show()
	slot.questIcon:Hide()
	slot.name, slot.rarity = nil, nil;
	local start, duration, enable = GetContainerItemCooldown(bag, slotID)
	CooldownFrame_SetTimer(slot.cooldown, start, duration, enable)
	if duration > 0 and enable == 0 then
		SetItemButtonTextureVertexColor(slot, 0.4, 0.4, 0.4)
	else
		SetItemButtonTextureVertexColor(slot, 1, 1, 1)
	end
	if bagType then
		local r, g, b = bagType[1], bagType[2], bagType[3];
		slot:SetBackdropColor(r, g, b, 0.5)
		slot:SetBackdropBorderColor(r, g, b, 1)
	elseif itemLink then
		local class, subclass, maxStack;
		key, _, slot.rarity, _, _, class, subclass, maxStack = GetItemInfo(itemLink)
		slot.name = key
		local z, A, C = GetContainerItemQuestInfo(bag, slotID)
		if A and not isActive then
			slot:SetBackdropBorderColor(1.0, 0.3, 0.3)
			slot.questIcon:Show()
		elseif A or z then
			slot:SetBackdropBorderColor(1.0, 0.3, 0.3)
		elseif slot.rarity and slot.rarity>1 then
			local D, E, F = GetItemQualityColor(slot.rarity)
			slot:SetBackdropBorderColor(D, E, F)
		else
			slot:SetBackdropBorderColor(0, 0, 0)
		end
		if (key and save) then
			local id = GetContainerItemID(bag,slotID)
			if id ~= 6948 then LOG.myStash[bag][key] = GetItemCount(id,true) end
		end
	else
		slot:SetBackdropBorderColor(0, 0, 0)
	end
	if C_NewItems.IsNewItem(bag, slotID)then
		ActionButton_ShowOverlayGlow(slot)
	else
		ActionButton_HideOverlayGlow(slot)
	end
	SetItemButtonTexture(slot, texture)
	SetItemButtonCount(slot, count)
	SetItemButtonDesaturated(slot, locked, 0.5, 0.5, 0.5)
end

local RefreshLoggedBagSlots = function(self, bag, save)
	if(not bag) then return end
	for i = 1, GetContainerNumSlots(bag)do
		local container = self
		if not self.RefreshSlot then
			container = self:GetParent()
		end
		RefreshLoggedSlot(container, bag, i, save)
	end
end

local RefreshLoggedBagsSlots = function(self)
	for _,bag in ipairs(self.BagIDs)do
		local container = self.Bags[bag]
		if container then
			if LOG.myStash[bag] then
				twipe(LOG.myStash[bag])
			else
				LOG.myStash[bag] = {};
			end
			RefreshLoggedBagSlots(container, bag, true)
		end
	end
	for bag,items in pairs(LOG.myStash) do
		for id,amt in pairs(items) do
			LOG.BagItemCache[id] = LOG.BagItemCache[id] or {}
			LOG.BagItemCache[id][nameKey] = amt
		end
	end
end

local GameTooltip_LogTooltipSetItem = function(self)
	local key,itemID = self:GetItem()
	if LOG.BagItemCache[key] then
		self:AddLine(" ")
		self:AddDoubleLine("|cFFFFDD3C[Character]|r","|cFFFFDD3C[Count]|r")
		for alt,amt in pairs(LOG.BagItemCache[key]) do
			local hexString = SVLOG_Data[realmKey]["info"][alt]
			local name = ("%s%s|r"):format(hexString, alt)
			local result = ("%s%s|r"):format(hexString, amt)
			self:AddDoubleLine(name,result)
		end
		self:AddLine(" ")
	end
	self.itemLogged = true
end
--[[
##########################################################
CORE FUNCTIONS
##########################################################
]]--
function CHAT:LoadSavedChatLog()
	local temp, data = {}
	for id, _ in pairs(SVLOG_Cache["chat"]) do
		tinsert(temp, tonumber(id))
	end
	tsort(temp, function(a, b)
		return a < b
	end)
	for i = 1, #temp do
		data = SVLOG_Cache["chat"][tostring(temp[i])]
		if type(data) == "table" and data[20] ~= nil then
			self.timeOverride = temp[i]
			ChatFrame_MessageEventHandler(DEFAULT_CHAT_FRAME, data[20], unpack(data))
		end
	end
end

function CHAT:LogCurrentChat(event, ...)
	local temp = {}
	for i = 1, select('#', ...) do
		temp[i] = select(i, ...) or false
	end
	if #temp > 0 then
	  temp[20] = event
	  local randomTime = select(2, ("."):split(GetTime() or "0."..random(1, 999), 2)) or 0;
	  local timeForMessage = time().."."..randomTime;
	  SVLOG_Cache["chat"][timeForMessage] = temp
		local c, k = 0
		for id, data in pairs(SVLOG_Cache["chat"]) do
			c = c + 1
			if (not k) or k > id then
				k = id
			end
		end
		if c > 128 then
			SVLOG_Cache["chat"][k] = nil
		end
	end
end

function CHAT:PLAYER_ENTERING_WORLD()
	local temp, data = {}
	for id, _ in pairs(SVLOG_Cache["chat"]) do
		tinsert(temp, tonumber(id))
	end
	tsort(temp, function(a, b)
		return a < b
	end)
	for i = 1, #temp do
		data = SVLOG_Cache["chat"][tostring(temp[i])]
		if type(data) == "table" and data[20] ~= nil then
			ChatFrame_MessageEventHandler(DEFAULT_CHAT_FRAME, data[20], unpack(data))
		end
	end
	self:UnregisterEvent("PLAYER_ENTERING_WORLD")
end

function LOG:AppendBankFunctions()
	local BAGS = SuperVillain.SVBag;
	if(BAGS.BankFrame) then
		BAGS.BankFrame.RefreshBagsSlots = RefreshLoggedBagsSlots
	end
end

function LOG:AppendChatFunctions()
	if SuperVillain.db.SVChat.enable and SuperVillain.db.SVChat.saveChats then
		for _,event in pairs(LoggingEvents) do
			SuperVillain.SVChat:RegisterEvent(event, "LogCurrentChat")
		end
		SuperVillain.SVChat:RegisterEvent("PLAYER_ENTERING_WORLD")
	end
end
--[[
##########################################################
CORE FUNCTIONS
##########################################################
]]--
local function SetConfigOptions()
	SuperVillain.Options.args.SVLogs = {
		type = "group",
		name = L["Logging"],
		childGroups = "tree",
		args = {
			common = {
				order = 100,
				type = "group",
				name = "Logging",
				guiInline = true,
				args = {}
			}
		}
	};
	for key, options in pairs(LOG.OptionsCache) do
		SuperVillain.Options.args.SVLogs.args.common.args[key] = options;
	end
end

local function ResetAllLogs()
	if SVLOG_Data[realmKey]["bags"][nameKey] then SVLOG_Data[realmKey]["bags"][nameKey] = {} end
	if SVLOG_Data[realmKey]["gold"][nameKey] then SVLOG_Data[realmKey]["gold"][nameKey] = 0 end
	if SVLOG_Cache then SVLOG_Cache = {} end
end
--[[
##########################################################
BUILD FUNCTION
##########################################################
]]--
local function LoadLogOMatic()
	local toonClass = select(2,UnitClass("player"));
	local r,g,b = RAID_CLASS_COLORS[toonClass].r, RAID_CLASS_COLORS[toonClass].g, RAID_CLASS_COLORS[toonClass].b
	local hexString = ("|cff%02x%02x%02x"):format(r * 255, g * 255, b * 255)
	if not SVLOG_Cache then SVLOG_Cache = {} end
	SVLOG_Data = SVLOG_Data or {}
	SVLOG_Data[realmKey] = SVLOG_Data[realmKey] or {}
	SVLOG_Data[realmKey]["bags"] = SVLOG_Data[realmKey]["bags"] or {};
	SVLOG_Data[realmKey]["info"] = SVLOG_Data[realmKey]["info"] or {};
	SVLOG_Data[realmKey]["info"][nameKey] = hexString;
	SVLOG_Data[realmKey]["bags"][nameKey] = SVLOG_Data[realmKey]["bags"][nameKey] or {};

	LOG.stash = SVLOG_Data[realmKey]["bags"];
	LOG.myStash = SVLOG_Data[realmKey]["bags"][nameKey];

	SVLOG_Data[realmKey]["quests"] = SVLOG_Data[realmKey]["quests"] or {};
	SVLOG_Data[realmKey]["quests"][nameKey] = SVLOG_Data[realmKey]["quests"][nameKey] or {};

	LOG.chronicle = SVLOG_Data[realmKey]["quests"][nameKey];

	NewHook(SuperVillain, "ResetAllUI", ResetAllLogs);

	local uselog = SuperVillain.db.SVChat.saveChats;
	if not SVLOG_Cache["chat"] then SVLOG_Cache["chat"] = {} end

	for alt,_ in pairs(SVLOG_Data[realmKey]["bags"]) do
		for bag,items in pairs(SVLOG_Data[realmKey]["bags"][alt]) do
			for id,amt in pairs(items) do
				LOG.BagItemCache[id] = LOG.BagItemCache[id] or {}
				LOG.BagItemCache[id][alt] = amt
			end
		end
	end

	--[[ OVERRIDE DEFAULT FUNCTIONS ]]--
	if SuperVillain.db.SVBag.enable then
		local BAGS = SuperVillain.SVBag;
		if BAGS.BagFrame then
			BAGS.BagFrame.RefreshBagsSlots = RefreshLoggedBagsSlots;
			NewHook(BAGS, "MakeBank", LOG.AppendBankFunctions);
		end
	end
	if SuperVillain.db.SVTip.enable then
		GameTooltip:HookScript("OnTooltipSetItem", GameTooltip_LogTooltipSetItem)
	end

	--[[ APPLY HOOKS ]]--
	LOG:AppendChatFunctions()
	NewHook(CHAT, "ReLoad", LOG.AppendChatFunctions);
end

SuperVillain.Registry:NewScript(LoadLogOMatic)
SuperVillain.Registry:NewPlugin(SVUIAddOnName, SetConfigOptions)