Quantcast
--
-- report.lua
--
-- Contains the report module that handles the creation of the
-- report window and the sending of selected number of parses
-- to the selected channel.
--

local addonName, addonTable = ...

-- Global functions for faster access
local format = format;
local tinsert = tinsert;
local date = date;
local pairs = pairs;
local ipairs = ipairs;
local min = min;
local strupper = strupper;
local SendChatMessage = SendChatMessage;
local IsInGroup = IsInGroup;
local IsInRaid = IsInRaid;
local IsInGuild = IsInGuild;


-- Set up module
local addon = addonTable[1];
local report = addon:NewModule("report", "AceHook-3.0")
addon.report = report;

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

-- Constants

-- Formats for a parse string
-- [25/02/01] #1. 24.5k - Saniera (Shadow, 680ilvl)
local PARSE_OUTPUT_FORMAT_NO_ILVL_SPEC = "[%s] #%d. %s - %s";
local PARSE_OUTPUT_FORMAT_NO_SPEC = PARSE_OUTPUT_FORMAT_NO_ILVL_SPEC .. " (%d ilvl)";
local PARSE_OUTPUT_FORMAT_NO_ILVL = PARSE_OUTPUT_FORMAT_NO_ILVL_SPEC .. " (%s)";
local PARSE_OUTPUT_FORMAT 		  = PARSE_OUTPUT_FORMAT_NO_ILVL_SPEC .. " (%s, %d ilvl)";

-- The time format used for parses
local PARSE_TIME_FORMAT = "%x";

-- The time format used for the startTime value filter
local FILTER_START_TIME_FORMAT = "%m/%d/%y %H:%M";

-- The channels that can be picked for reporting data to
local SEND_TO_CHANNELS_LIST = {
	SELF = "Self",
	SAY = "Say",
	PARTY = "Party",
	RAID = "Raid",
	GUILD = "Guild",
	INSTANCE_CHAT = "Instance",
	WHISPER = "Whisper"
};
local SEND_TO_CHANNELS_LIST_ORDER = {"SELF", "SAY", "PARTY", "RAID", "GUILD", "INSTANCE_CHAT", "WHISPER"};

-- Max number of parses to send, so we don't spam too too much...
local MAX_PARSES_TO_SEND = 30;


-- Takes a parse and rank and returns a formatted string
-- representing the parse.
local function getParseStringFromParse(rank, parse)
	local dataNum = (parse.role == "HEALER") and parse.hps or parse.dps;
	dataNum = addon.gui:FormatNumber(dataNum);
	local name = parse.name;
	local spec = parse.specName;
	local itemLevel = parse.itemLevel;
	local time = date(PARSE_TIME_FORMAT, parse.startTime);

	if spec and itemLevel then
		return format(PARSE_OUTPUT_FORMAT, time, rank, dataNum, name, spec, itemLevel);
	elseif spec then
		return format(PARSE_OUTPUT_FORMAT_NO_ILVL, time, rank, dataNum, name, spec);
	elseif itemLevel then
		return format(PARSE_OUTPUT_FORMAT_NO_SPEC, time, rank, dataNum, name, itemLevel);
	else
		return format(PARSE_OUTPUT_FORMAT_NO_ILVL_SPEC, time, rank, dataNum, name);
	end
end

-- Takes a list of filters and returns a formatted string
-- representing the filters and their values.
local function createFilterString(filters)
	local filterString;
	for filterKey, filterValue in pairs(filters) do
		if not filterString then
			filterString = "";
		else
			filterString = filterString .. ", ";
		end

		if filterKey == "name" then
			filterString = filterString .. format("Name: %s", filterValue);
		elseif filterKey == "startTime" then
			filterString = filterString .. format("Time: %s", date(FILTER_START_TIME_FORMAT, filterValue));
		else
			filterString = filterString .. format("%s: %s", filterKey, filterValue);
		end
	end
	return filterString;
end

-- Takes a role ID and returns a string representation of
-- what the data will be. For DAMAGER/TANKS this will be DPS
-- and for healers this data will be HPS.
local function createDataTypeName(roleId)
	if roleId == "DAMAGER" then
		return "DPS"
	elseif roleId == "HEALER" then
		return "HPS"
	elseif roleId == "TANK" then
		return "DPS (Tanks)"
	end
end


-- Sends the parses to the channel specified with the title
-- and filterString included.
function report:SendData(channelId, whisperToName, dataTitle, filterString, parses, numParses)
	numParses = min(numParses, MAX_PARSES_TO_SEND);
	channelId = strupper(channelId);

	local lines = {"-- Guild Skada High Score --", dataTitle};

	if filterString then
		tinsert(lines, format("Filtered by [%s]", filterString));
	end

	for rank, parse in ipairs(parses) do
		local parseString = getParseStringFromParse(rank, parse);
		tinsert(lines, parseString);
		if(rank >= numParses) then
			break;
		end
	end

	if channelId == "SELF" then
		for _, line in ipairs(lines) do
			addon:Print(line);
		end
	elseif channelId == "WHISPER" then
		for _, line in ipairs(lines) do
			SendChatMessage(line, "WHISPER", nil, whisperToName);
		end
	else
		if channelId == "PARTY" and not IsInGroup() then
			return
		end
		if channelId == "RAID" and not IsInRaid() then
			return
		end
		if channelId == "GUILD" and not IsInGuild() then
			return
		end

		for _, line in ipairs(lines) do
			SendChatMessage(line, channelId);
		end
	end
end

-- Hides and releases the report frame if it is show,
-- if it is not shown this does nothing.
function report:HideReportFrame()
	if self.reportFrame then
		self.reportFrame:Release();
		self.reportFrame = nil;
	end
end

-- Shows the report frame for the supplied encounter and parses.
function report:ShowReportFrame(guildId, zoneId, difficultyId, encounterId, roleId, parses, filters)
	self:HideReportFrame();

	local channelId = self.lastChannelId or "SELF";
	local guildName = addon.highscore:GetGuildNameById(guildId);
	local zoneName = addon.highscore:GetZoneNameById(zoneId);
	local difficultyName = addon.highscore:GetDifficultyNameById(difficultyId);
	local encounterName = addon.highscore:GetEncounterNameById(encounterId);

	local dataTypeName = createDataTypeName(roleId);
	local filterString = createFilterString(filters);
	local dataTitle = format("<%s> %s (%s) - %s", guildName, encounterName, difficultyName, dataTypeName);

	local frame = AceGUI:Create("Frame")
	frame:Hide();
	frame:EnableResize(false)
	frame:SetWidth(300);
	frame:SetHeight(300);
	frame:SetTitle("Report Data");
	frame:SetLayout("Flow");

	local dataTitleLabel = AceGUI:Create("Label");
	dataTitleLabel:SetText(dataTitle);
	dataTitleLabel:SetFullWidth(true);

	local filteredByLabel = AceGUI:Create("Label");
	filteredByLabel:SetText(format("Filtered by [%s]", filterString or ""));
	filteredByLabel:SetFullWidth(true);

	local channelDropdown = AceGUI:Create("Dropdown");
	channelDropdown:SetLabel("Channel");
	channelDropdown:SetList(SEND_TO_CHANNELS_LIST, SEND_TO_CHANNELS_LIST_ORDER);
	channelDropdown:SetValue(channelId);
	channelDropdown:SetFullWidth(true);
	channelDropdown:SetCallback("OnValueChanged", function(widget, evt, newChanId)
		channelId = newChanId;
		self.lastChannelId = channelId;
	end);

	local whisperToNameEditBox = AceGUI:Create("EditBox");
	whisperToNameEditBox:SetFullWidth(true);
	whisperToNameEditBox:SetLabel("Whisper to");

	local numToSendSlider = AceGUI:Create("Slider");
	numToSendSlider:SetLabel("Number of Parses");
	numToSendSlider:SetFullWidth(true);
	numToSendSlider:SetSliderValues(1, min(#parses, MAX_PARSES_TO_SEND), 1);
	numToSendSlider:SetValue(min(#parses, MAX_PARSES_TO_SEND));

	local sendButton = AceGUI:Create("Button");
	sendButton:SetText("Send");
	sendButton:SetFullWidth(true);
	sendButton:SetCallback("OnClick", function()
		local numParses = numToSendSlider:GetValue();
		local whisperToName = whisperToNameEditBox:GetText();
		self:SendData(channelId, whisperToName, dataTitle, filterString, parses, numParses);
		self:HideReportFrame();
	end);

	frame:AddChild(dataTitleLabel);
	if filterString then
		frame:AddChild(filteredByLabel);
	end
	frame:AddChild(channelDropdown);
	frame:AddChild(whisperToNameEditBox);
	frame:AddChild(numToSendSlider);
	frame:AddChild(sendButton);

	self.reportFrame = frame;
	frame:Show();
end

function report:OnCloseSpecialWindows()
	local found;
	if self.reportFrame then
		self:HideReportFrame()
		found = 1
	end
	return self.hooks["CloseSpecialWindows"]() or found;
end

function report:OnEnable()
	self:RawHook("CloseSpecialWindows", "OnCloseSpecialWindows", true);
end

function report:OnDisable()
	self:HideReportFrame();
	self:UnHook("CloseSpecialWindows");
end