local me={}
local SM = LibStub:GetLibrary("LibSharedMedia-3.0")
local Events = LibStub("AceEvent-3.0")
local AceLocale = LibStub("AceLocale-3.0")
local L = AceLocale:GetLocale( "Recount" )

local revision = tonumber(string.sub("$Revision: 79898 $", 12, -3))
if Recount.Version < revision then Recount.Version = revision end

local string_format = string.format
local tinsert = table.insert
local tremove = table.remove

local _, _, _, tocversion =  GetBuildInfo()

-- Based on cck's numeric Short code in DogTag-3.0.
function Recount.ShortNumber(value)
	if value >= 10000000 or value <= -10000000 then
		return ("%.1fm"):format(value / 1000000)
	elseif value >= 1000000 or value <= -1000000 then
		return ("%.2fm"):format(value / 1000000)
	elseif value >= 100000 or value <= -100000 then
		return ("%.0fk"):format(value / 1000)
	elseif value >= 10000 or value <= -10000 then
		return ("%.1fk"):format(value / 1000)
	else
		return math.floor(value+0.5)..''
	end
end

-- This is comma_value() by Richard Warburton from: http://lua-users.org/wiki/FormattingNumbers with slight modifications (and a bug fix)
function Recount.CommaNumber(n)
	n = ("%.0f"):format(n)
   	local left,num,right = string.match(n,'^([^%d]*%d)(%d+)(.-)$')
   	return left and left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse()) or n --..right
end

local NumFormats =
{
	function(value) return ("%.0f"):format(value) end,
	Recount.CommaNumber,
	Recount.ShortNumber
}

function Recount:FormatLongNums(value)
        return NumFormats[Recount.db.profile.MainWindow.BarText.NumFormat](value)
end

local function GetMainWindowState()
        return Recount:GetWindow("main")
end

local function GetHealingMode()
        if not Recount.MainWindowData then
                return
        end

        for _, mode in ipairs(Recount.MainWindowData) do
                if mode[1] == L["Healing Done"] then
                        return mode
                end
        end
end

local function ResetMainWindowDisplayCache()
        local window = GetMainWindowState()
        window.DispTableSorted={}
        window.DispTableLookup={}
        Recount:ResetHealingWindowDisplayCache()
        return window
end

local function GetRowWindowContext(windowID)
	if windowID == "main" then
		return GetMainWindowState(), Recount.MainWindow
	end

	local window = Recount:GetWindow(windowID)
	return window, window and window.Frame
end

local function GetWindowFrameName(windowID)
	if windowID == "main" then
		return "Recount_MainWindow"
	end

	return "Recount_"..windowID.."_Window"
end

local function GetWindowTitle(windowID)
	if windowID == "main" then
		return L["Main"]
	end

	return string_format("Recount (%s)", windowID)
end

function me:SetFontSize(string, size)
	local Font, Height, Flags = string:GetFont()
	string:SetFont(Font, size, Flags)
end

function Recount:BarDropDownOpen(myframe)
	Recount_BarDropDownMenu = CreateFrame("Frame", "Recount_BarDropDownMenu", myframe);
	Recount_BarDropDownMenu.displayMode = "MENU";
	Recount_BarDropDownMenu.initialize	= Recount_CreateBarDropdown;
	local leftPos = myframe:GetLeft() -- Elsia: Side code adapted from Mirror
	local rightPos = myframe:GetRight()
	local side
	local oside
	if not rightPos then
		rightPos = 0
	end
	if not leftPos then
		leftPos = 0
	end

	local rightDist = GetScreenWidth() - rightPos

	if leftPos and rightDist < leftPos then
		side = "TOPLEFT"
		oside = "TOPRIGHT"
	else
		side = "TOPRIGHT"
		oside = "TOPLEFT"
	end
	if tocversion == 30000 then
		UIDropDownMenu_SetAnchor(Recount_BarDropDownMenu , 0, 0, oside, myframe, side)
	else
		UIDropDownMenu_SetAnchor(0, 0, Recount_BarDropDownMenu , oside, myframe, side)
	end
end

function Recount:SetupBar(row)
	row.StatusBar=CreateFrame("StatusBar",nil,row)
	row.StatusBar:SetAllPoints(row)

	local BarTexture

	if not BarTexture then
		BarTexture=Recount.db.profile.BarTexture
	end

	if BarTexture==nil then
		BarTexture=SM:Fetch("statusbar","BantoBar")
	else
		BarTexture=SM:Fetch("statusbar",BarTexture)
	end
	row.StatusBar:SetStatusBarTexture(BarTexture)
	row.StatusBar:SetStatusBarColor(.5, .5, .5, 1)
	row.StatusBar:SetMinMaxValues(0,100)
	row.StatusBar:SetValue(100)
	row.StatusBar:Show()

	row.LeftText=row.StatusBar:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall")
	row.LeftText:SetPoint("LEFT", row.StatusBar,"LEFT",2)
	row.LeftText:SetJustifyH("LEFT")
	row.LeftText:SetText("Test")
	row.LeftText:SetTextColor(1,1,1,1)
	me:SetFontSize(row.LeftText,math.max(Recount.db.profile.MainWindow.RowHeight*0.75,Recount.db.profile.MainWindow.RowHeight-3))
	Recount:AddFontString(row.LeftText)
	
	row.RightText=row.StatusBar:CreateFontString(nil,"OVERLAY","GameFontHighlightSmall")
	row.RightText:SetPoint("RIGHT", row.StatusBar,"RIGHT",-2)
	row.RightText:SetJustifyH("RIGHT")
	row.RightText:SetText("0")
	row.RightText:SetTextColor(1,1,1,1)
	me:SetFontSize(row.RightText,math.max(Recount.db.profile.MainWindow.RowHeight*0.75,Recount.db.profile.MainWindow.RowHeight-3))
	Recount:AddFontString(row.RightText)

	Recount.Colors:RegisterFont("Bar","Bar Text",row.LeftText)
	Recount.Colors:RegisterFont("Bar","Bar Text",row.RightText)
end

--Violation was my reference (I like the basic look of violation just not the backend)
--Make sure to start with row 1 and go upwards when creating though should be safe if you don't just more function calls
local function AttachRowMouseScripts(row, frame)
        row:SetScript("OnClick", function()
                if arg1=="RightButton" then
                        Recount:BarDropDownOpen(this)
                        CloseDropDownMenus(1)
                        ToggleDropDownMenu(1, nil, Recount_BarDropDownMenu)
                elseif type(this.clickFunc)=="function" and this.clickData then
                        this:clickFunc(this.clickData)
                end
        end)
        row:SetScript("OnEnter", function()
                GameTooltip:SetOwner(this, "ANCHOR_TOPRIGHT")
                local tooltipFunc = frame and frame.TooltipFunc
                if tooltipFunc then
                        tooltipFunc(frame, this.Name, this.TooltipData)
                end
                GameTooltip:Show()
        end)
        row:SetScript("OnLeave", function() GameTooltip:Hide() end)
        row:EnableMouse(true)
        row:RegisterForClicks("LeftButtonDown","RightButtonUp")
end

local function CreateWindowRow(windowID, num, options)
	options = options or {}
	local window, frame = GetRowWindowContext(windowID)
	if not window or not frame then
		return
	end

	window.Rows = window.Rows or {}
	local rows = window.Rows
	local rowmin = 1
	local offs = 0

	if not Recount.db.profile.MainWindow.HideTotalBar then
		offs = 1
		rowmin = 0
	end

	if num < rowmin or rows[num] then
		return
	end

	local parentName = frame:GetName() or ("RecountWindow_"..windowID)
	local row=CreateFrame("Button",parentName.."_Bar"..num,frame)

	row:SetPoint("TOPLEFT",frame,"TOPLEFT",2,-32-(Recount.db.profile.MainWindow.RowHeight+Recount.db.profile.MainWindow.RowSpacing)*(num-1+offs))
	row:SetHeight(Recount.db.profile.MainWindow.RowHeight)
	row:SetWidth(frame:GetWidth()-4)
	if num ~= 0 and options.interactive ~= false then
		AttachRowMouseScripts(row, frame)
	else
		row:EnableMouse(false)
	end

	Recount:SetupBar(row)

	if options.blank then
		row.LeftText:SetText("")
		row.RightText:SetText("")
		row.StatusBar:SetValue(0)
	end

	rows[num]=row
	window.RowsCreated=math.max(window.RowsCreated or 0,num)

	row.id=num

	return row
end

function me:CreateRow(num)
	return CreateWindowRow("main", num)
end

local function UpdateAuxWindowRowLayout(windowID)
	if windowID == "main" then
		return
	end

	local window, frame = GetRowWindowContext(windowID)
	if not window or not frame or not window.Rows then
		return
	end

	local width = frame:GetWidth() - 4
	for _, row in pairs(window.Rows) do
		row:SetWidth(width)
	end

	local scrollBar = frame.ScrollBar
	if not scrollBar then
		return
	end

	local minIndex = Recount.db.profile.MainWindow.HideTotalBar and 1 or 0
	local maxIndex = window.RowsCreated or minIndex
	local firstRow = window.Rows[minIndex]
	if not firstRow then
		for i = minIndex, maxIndex do
			if window.Rows[i] then
				firstRow = window.Rows[i]
				break
			end
		end
	end

	local lastRow = window.Rows[maxIndex]
	if not lastRow then
		for i = maxIndex, minIndex, -1 do
			if window.Rows[i] then
				lastRow = window.Rows[i]
				break
			end
		end
	end

	if firstRow and lastRow then
		scrollBar:SetPoint("TOPLEFT", firstRow, "TOPLEFT", -4, 0)
		scrollBar:SetPoint("BOTTOMRIGHT", lastRow, "BOTTOMRIGHT", -4, 0)
	end
end

local function DuplicateMainWindowRows(windowID)
	local mainWindow = GetMainWindowState()
	local maxIndex = mainWindow.RowsCreated or 0
	local minIndex = Recount.db.profile.MainWindow.HideTotalBar and 1 or 0

	if maxIndex < minIndex then
		return
	end

	local options = {interactive = false, blank = true}
	for i = minIndex, maxIndex do
		CreateWindowRow(windowID, i, options)
	end

	local window = Recount:GetWindow(windowID)
	if window then
		window.CurRows = maxIndex
	end

	UpdateAuxWindowRowLayout(windowID)
end
local info = {}
function Recount_CreateBarDropdown(level)
	if (not level) then return end
	for k in pairs(info) do info[k] = nil end
	if (level == 1) then
	if this and this.LeftText then
		info.isTitle		= 1
		info.text		= this.LeftText:GetText()
		info.notCheckable	= 1
		UIDropDownMenu_AddButton(info, level)

		info = {}
		
		info.isTitle		= nil
		info.notCheckable	= 1
		info.disabled		= nil

		info.text		= L["Show Details (Left Click)"]
		info.notCheckable	= 1
		info.func = me.ShowDetail
		info.arg1 = me
		info.arg2 = this.name
		UIDropDownMenu_AddButton(info, level)

		info.text		= L["Show Graph (Shift Click)"]
		info.notCheckable	= 1
		info.func = me.ShowGraphWindow
		info.arg1 = me
		info.arg2 = this.name
		UIDropDownMenu_AddButton(info, level)
		
		info.text		= L["Add to Current Graph (Alt Click)"]
		info.notCheckable	= 1
		info.func = me.AddCombatantToGraph
		info.arg1 = me
		info.arg2 = this.name
		UIDropDownMenu_AddButton(info, level)

		local Settings=Recount.MainWindow.RealtimeSettings
		if Settings then
			info.text		= L["Show Realtime Graph (Ctrl Click)"]
			info.notCheckable	= 1
			info.func = me.ShowRealtime
			info.arg1 = me
			info.arg2 = this.name
			UIDropDownMenu_AddButton(info, level)
		end

		info.text		= L["Delete Combatant (Ctrl-Alt Click)"]
		info.notCheckable	= 1
		info.func = me.DeleteCombatant
		info.arg1 = me
		info.arg2 = this.name
		UIDropDownMenu_AddButton(info, level)
	end
	end
end

function Recount:DeleteCombatant(name)

	if not Recount.db2.combatants[name] then return end

	if Recount.db2.combatants[name].Owner then
		local owner = Recount.db2.combatants[name].Owner
		if Recount.db2.combatants[owner] and Recount.db2.combatants[owner].Pet then
			for k,v in pairs(Recount.db2.combatants[owner].Pet) do
				if v == name then
					table.remove(Recount.db2.combatants[owner].Pet,k) -- Elsia: Remove deleted pet
				end
			end
		end
	end
	
	if Recount.db2.combatants[name].Pet then
		for k,v in pairs(Recount.db2.combatants[name].Pet) do
			me:DeleteCombatant(v) -- Elsia: Delete all pets with owner
		end
	end
	
	Recount:DeleteGuardianOwnerByGUID(Recount.db2.combatants[name])
	
	Recount.db2.combatants[name]=nil
	
	Recount.NewData = true
end

function me:DeleteCombatant(name) -- Elsia: Add delete combatant feature
	Recount:DeleteCombatant(name)

	Recount:SetMainWindowMode(Recount.db.profile.MainWindowMode)
	Recount:FullRefreshMainWindow()
end

function Recount:FullRefreshMainWindow()
	local window = GetMainWindowState()
	Recount:FreeTableRecurseLimit(window.DispTableSorted,1)
	Recount:FreeTable(window.DispTableLookup)
	window.DispTableSorted=Recount:GetTable()
	window.DispTableLookup=Recount:GetTable()
end

function me:FixRow(i)
	local row=GetMainWindowState().Rows[i]
	local MaxNameWidth=row:GetWidth()-row.RightText:GetStringWidth()-4
	
	if MaxNameWidth<16 then
		MaxNameWidth=16
	end

	local LText=row.LeftText:GetText()
	
	while row.LeftText:GetStringWidth()>MaxNameWidth do
		LText=strsub(LText,1,#LText-1)
		row.LeftText:SetText(LText.."...")
	end
end

function Recount:BarsChanged()
	local offs = 0
	if not Recount.db.profile.MainWindow.HideTotalBar then
		offs = 1
	end

	local rows = GetMainWindowState().Rows
	for k, v in pairs(rows) do
		v:SetHeight(Recount.db.profile.MainWindow.RowHeight)
		v:SetPoint("TOPLEFT",Recount.MainWindow,"TOPLEFT",2,-32-(Recount.db.profile.MainWindow.RowHeight+Recount.db.profile.MainWindow.RowSpacing)*(k-1+offs))
		me:SetFontSize(v.LeftText,math.max(Recount.db.profile.MainWindow.RowHeight*0.75,Recount.db.profile.MainWindow.RowHeight-3))
		me:SetFontSize(v.RightText,math.max(Recount.db.profile.MainWindow.RowHeight*0.75,Recount.db.profile.MainWindow.RowHeight-3))
	end
	Recount:ResizeMainWindow()
end



function Recount:UpdateBarTextures()
	local window = GetMainWindowState()
	for _, v in pairs(window.Rows) do
		v.StatusBar:SetStatusBarTexture(SM:Fetch(SM.MediaType.STATUSBAR, Recount.db.profile.BarTexture))
	end

	if Recount.db.profile.Font then
		Recount:SetFont(Recount.db.profile.Font)
	end
end

function Recount:SetBarTextures(handle)
	local Texture=SM:Fetch(SM.MediaType.STATUSBAR,handle) -- "statusbar"
	Recount.db.profile.BarTexture=handle
	for _, v in pairs(GetMainWindowState().Rows) do
		v.StatusBar:SetStatusBarTexture(Texture)
	end
end

function me:SetBar(num,left,right,value,colorgroup, colorclass ,clickData,clickFunc,tooltipData)
        local rowmin = 1
        local rows = GetMainWindowState().Rows

        if not Recount.db.profile.MainWindow.HideTotalBar then
                rowmin = 0
        end

        if num<rowmin or not rows[num] then
                return
        end

        local Row=rows[num]
        Row:Show()
        Row.StatusBar:SetValue(value)
        Row.LeftText:SetText(left)
        Row.RightText:SetText(right)
        Row.Name=left
        Row.TooltipData=tooltipData
        Row.clickData=clickData
        Row.clickFunc=clickFunc

        if colorgroup and colorclass and type(colorclass)=="string" then
                Recount.Colors:UnregisterItem(Row.StatusBar)
                Recount.Colors:RegisterTexture(colorgroup,Recount:FixUnitString(colorclass),Row.StatusBar)
                --Row.StatusBar:SetStatusBarColor(color.r,color.g,color.b,1)
        end

        Row.LeftText:SetTextColor(Recount.db.profile.Colors.Bar["Bar Text"].r,Recount.db.profile.Colors.Bar["Bar Text"].g,Recount.db.profile.Colors.Bar["Bar Text"].b,1);
        Row.RightText:SetTextColor(Recount.db.profile.Colors.Bar["Bar Text"].r,Recount.db.profile.Colors.Bar["Bar Text"].g,Recount.db.profile.Colors.Bar["Bar Text"].b,1);
end

local function SetHealingBar(window, num, left, right, value, colorgroup, colorclass)
        local rowmin = 1
        local rows = window.Rows

        if not Recount.db.profile.MainWindow.HideTotalBar then
                rowmin = 0
        end

        if num < rowmin or not rows or not rows[num] then
                return
        end

        local Row = rows[num]
        Row:Show()
        Row.StatusBar:SetValue(value)
        Row.LeftText:SetText(left)
        Row.RightText:SetText(right)
	Row.Name = left
	Row.TooltipData = nil
	Row.clickData = nil
	Row.clickFunc = nil

	if colorgroup and colorclass and type(colorclass) == "string" then
	Recount.Colors:UnregisterItem(Row.StatusBar)
	Recount.Colors:RegisterTexture(colorgroup, Recount:FixUnitString(colorclass), Row.StatusBar)
	end

        Row.LeftText:SetTextColor(Recount.db.profile.Colors.Bar["Bar Text"].r,Recount.db.profile.Colors.Bar["Bar Text"].g,Recount.db.profile.Colors.Bar["Bar Text"].b,1);
        Row.RightText:SetTextColor(Recount.db.profile.Colors.Bar["Bar Text"].r,Recount.db.profile.Colors.Bar["Bar Text"].g,Recount.db.profile.Colors.Bar["Bar Text"].b,1);
	end

local function FixHealingRow(window, i)
        local rows = window.Rows
        if not rows or not rows[i] then
                return
        end

        local row = rows[i]
        local MaxNameWidth=row:GetWidth()-row.RightText:GetStringWidth()-4

        if MaxNameWidth<16 then
                MaxNameWidth=16
        end

        local LText=row.LeftText:GetText()

        while row.LeftText:GetStringWidth()>MaxNameWidth do
                LText=strsub(LText,1,#LText-1)
                row.LeftText:SetText(LText.."...")
        end
end

--[[function me:SetBarColors(r,g,b)
	
	self:SetStatusBarColor(r,g,b,1)
end]]

function Recount:ResizeMainWindow()
	--How many bars do we have now?
	local Bars=math.floor((Recount.MainWindow:GetHeight()-32.95)/(Recount.db.profile.MainWindow.RowHeight+Recount.db.profile.MainWindow.RowSpacing))
	local window = GetMainWindowState()
	local rows = window.Rows

	local minbar

	if not Recount.db.profile.MainWindow.HideTotalBar then
		minbar = 0
		Bars = Bars - 1
	else
		minbar = 1
		if rows[0] then rows[0]:Hide() end
	end

	if not Recount.db.profile.MainWindow.HideTotalBar and not rows[0] then -- Elsia: Create Total Bar
		me:CreateRow(0)
	end

	if Bars<window.CurRows then
		for i=Bars+1,window.CurRows do
			rows[i]:Hide()
		end
	elseif Bars>window.RowsCreated then
		for i=window.RowsCreated+1,Bars do
			me:CreateRow(i)
		end
	end

	--Update all the bar widths
	local CurWidth=Recount.MainWindow:GetWidth()-4
	for i=minbar,Bars do
		rows[i]:Show()
		rows[i]:SetWidth(CurWidth)
	end

	window.CurRows=Bars

	if rows[1] and rows[Bars] then
		Recount.MainWindow.ScrollBar:SetPoint("TOPLEFT", rows[1], "TOPLEFT", -4, 0)
		Recount.MainWindow.ScrollBar:SetPoint("BOTTOMRIGHT", rows[Bars], "BOTTOMRIGHT", -4, 0)
	end

	Recount:RefreshMainWindow()
end

function Recount:CreateMainWindowFrame(windowID)
        windowID = windowID or "main"
        local frame
        local frameName = GetWindowFrameName(windowID)
        local titleText = GetWindowTitle(windowID)
	local showFunc
	local hideFunc

	if windowID == "main" then
		showFunc = function()
			if not frame then
				return
			end
			frame.timeid=Recount:ScheduleRepeatingTimer("RefreshMainWindow",1,true)
			Recount.db.profile.MainWindowVis=true
		end
		hideFunc = function()
			if not frame then
				return
			end
			if frame.timeid then
				Recount:CancelTimer(frame.timeid)
				frame.timeid=nil
			end
			Recount.db.profile.MainWindowVis=false
		end
	end

        frame = Recount:CreateFrame(frameName,titleText,140,200,showFunc,hideFunc)
        frame.windowID = windowID

        frame:SetMovable(true)
        frame:EnableMouse(true)
        frame:RegisterForDrag("LeftButton")
        frame:SetScript("OnDragStart", function(self)
                if (self.isLocked and self.isLocked ~= 0) then
                        return
                end
                Recount:SetWindowTop(self)
                self:StartMoving()
                self.isMoving = true
        end)
        frame:SetScript("OnDragStop", function(self)
                self:StopMovingOrSizing()
                self.isMoving = false
                if self.SaveMainWindowPosition then
                        self:SaveMainWindowPosition()
                elseif self.SavePosition then
                        self:SavePosition()
                end
        end)

	frame:SetResizable(true)
	frame:SetMinResize(140,63)
	frame:SetMaxResize(400,520)

	frame.TitleClick=CreateFrame("FRAME",nil,frame)
	frame.TitleClick:SetAllPoints(frame.Title)
	frame.TitleClick:EnableMouse(true)
	frame.TitleClick:SetScript("OnMouseDown",function()
		local parent=this:GetParent()
		if ( ( ( not parent.isLocked ) or ( parent.isLocked == 0 ) ) and ( arg1 == "LeftButton" ) ) then
			Recount:SetWindowTop(parent)
			parent:StartMoving();
			parent.isMoving = true;
		end
	end)
	frame.TitleClick:SetScript("OnMouseUp", function()
		local parent=this:GetParent()
		if ( parent.isMoving ) then
			parent:StopMovingOrSizing();
			parent.isMoving = false;
			if parent.SaveMainWindowPosition then
				parent:SaveMainWindowPosition()
			elseif parent.SavePosition then
				parent:SavePosition()
			end
		end
	end)
	frame.TitleClick.BaseOnMouseDown = frame.TitleClick:GetScript("OnMouseDown")
	frame.TitleClick.BaseOnMouseUp = frame.TitleClick:GetScript("OnMouseUp")

	local rightGripName = windowID == "main" and "RecountResizeGripRight" or ("RecountResizeGripRight_"..windowID)
	local leftGripName = windowID == "main" and "RecountResizeGripLeft" or ("RecountResizeGripLeft_"..windowID)

	frame.DragBottomRight = CreateFrame("Button", rightGripName, frame)
	frame.DragBottomRight:Show()
	frame.DragBottomRight:SetFrameLevel( frame:GetFrameLevel() + 10)
	frame.DragBottomRight:SetNormalTexture("Interface\\AddOns\\Recount\\ResizeGripRight")
	frame.DragBottomRight:SetHighlightTexture("Interface\\AddOns\\Recount\\ResizeGripRight")
	frame.DragBottomRight:SetWidth(16)
	frame.DragBottomRight:SetHeight(16)
	frame.DragBottomRight:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0)
	frame.DragBottomRight:EnableMouse(true)
	frame.DragBottomRight:SetScript("OnMouseDown", function() if ((( not this:GetParent().isLocked ) or ( this:GetParent().isLocked == 0 ) ) and ( arg1 == "LeftButton" ) ) then this:GetParent().isResizing = true; this:GetParent():StartSizing("BOTTOMRIGHT") end end )
	frame.DragBottomRight:SetScript("OnMouseUp", function() if this:GetParent().isResizing == true then this:GetParent():StopMovingOrSizing(); if this:GetParent().SaveMainWindowPosition then this:GetParent():SaveMainWindowPosition(); elseif this:GetParent().SavePosition then this:GetParent():SavePosition(); end; this:GetParent().isResizing = false; end end )

	frame.DragBottomLeft = CreateFrame("Button", leftGripName, frame)
	frame.DragBottomLeft:Show()
	frame.DragBottomLeft:SetFrameLevel( frame:GetFrameLevel() + 10)
	frame.DragBottomLeft:SetNormalTexture("Interface\\AddOns\\Recount\\ResizeGripLeft")
	frame.DragBottomLeft:SetHighlightTexture("Interface\\AddOns\\Recount\\ResizeGripLeft")
	frame.DragBottomLeft:SetWidth(16)
	frame.DragBottomLeft:SetHeight(16)
	frame.DragBottomLeft:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 0)
	frame.DragBottomLeft:EnableMouse(true)
	frame.DragBottomLeft:SetScript("OnMouseDown", function() if ((( not this:GetParent().isLocked ) or ( this:GetParent().isLocked == 0 ) ) and ( arg1 == "LeftButton" ) ) then this:GetParent().isResizing = true; this:GetParent():StartSizing("BOTTOMLEFT") end end )
	frame.DragBottomLeft:SetScript("OnMouseUp", function() if this:GetParent().isResizing == true then this:GetParent():StopMovingOrSizing(); if this:GetParent().SaveMainWindowPosition then this:GetParent():SaveMainWindowPosition(); elseif this:GetParent().SavePosition then this:GetParent():SavePosition(); end; this:GetParent().isResizing = false; end end )

	local window = Recount:GetWindow(windowID)
	window.Frame = frame

	return frame
end

function Recount:CreateMainWindow()
		local theFrame = Recount:CreateMainWindowFrame("main")
	Recount.MainWindow = theFrame
	local window = GetMainWindowState()

	if theFrame.TitleClick and theFrame.TitleClick.BaseOnMouseDown then
		local OriginalTitleMouseDown = theFrame.TitleClick.BaseOnMouseDown
		theFrame.TitleClick:SetScript("OnMouseDown", function()
			if arg1=="RightButton" then
				Recount:ModeDropDownOpen(this)
				ToggleDropDownMenu(1, nil, Recount_ModeDropDownMenu)
				return
			end

			OriginalTitleMouseDown()
		end)
	end

	theFrame.SaveMainWindowPosition = Recount.SaveMainWindowPosition
	
	theFrame:SetScript("OnSizeChanged", function()
						if ( this.isResizing ) then
							Recount:ResizeMainWindow()
							
							Recount.db.profile.MainWindowHeight=this:GetHeight()
							Recount.db.profile.MainWindowWidth=this:GetWidth()
						end
					end)

	theFrame.ScrollBar=CreateFrame("SCROLLFRAME","Recount_MainWindow_ScrollBar",theFrame,"FauxScrollFrameTemplate")
	theFrame.ScrollBar:SetScript("OnVerticalScroll", function() FauxScrollFrame_OnVerticalScroll(20, Recount.RefreshMainWindow) end)
	Recount:SetupScrollbar("Recount_MainWindow_ScrollBar")

	if not Recount.db.profile.MainWindow.ShowScrollbar then
		Recount:HideScrollbarElements("Recount_MainWindow_ScrollBar")
	end

	--Recount:ShowGrips(not Recount.db.profile.Locked)
	
	theFrame.RightButton=CreateFrame("Button",nil,theFrame)
	theFrame.RightButton:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up.blp")
	theFrame.RightButton:SetPushedTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Down.blp")	
	theFrame.RightButton:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight.blp")
	theFrame.RightButton:SetWidth(16)
	theFrame.RightButton:SetHeight(18)
	theFrame.RightButton:SetPoint("TOPRIGHT",theFrame,"TOPRIGHT",-38+16,-12)
	theFrame.RightButton:SetScript("OnClick",function() Recount:MainWindowNextMode() end)
	theFrame.RightButton:SetFrameLevel(theFrame.RightButton:GetFrameLevel()+1)

	theFrame.LeftButton=CreateFrame("Button",nil,theFrame)
	theFrame.LeftButton:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-PrevPage-Up.blp")
	theFrame.LeftButton:SetPushedTexture("Interface\\Buttons\\UI-SpellbookIcon-PrevPage-Down.blp")
	theFrame.LeftButton:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight.blp")
	theFrame.LeftButton:SetWidth(16)
	theFrame.LeftButton:SetHeight(18)
	theFrame.LeftButton:SetPoint("RIGHT",theFrame.RightButton,"LEFT",0,0)
	theFrame.LeftButton:SetScript("OnClick",function() Recount:MainWindowPrevMode() end)
	theFrame.LeftButton:SetFrameLevel(theFrame.LeftButton:GetFrameLevel()+1)

	theFrame.ResetButton=CreateFrame("Button",nil,theFrame)
	theFrame.ResetButton:SetNormalTexture("Interface\\Addons\\Recount\\Textures\\icon-reset")
	theFrame.ResetButton:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight.blp")
	theFrame.ResetButton:SetWidth(16)
	theFrame.ResetButton:SetHeight(16)
	theFrame.ResetButton:SetPoint("RIGHT",theFrame.LeftButton,"LEFT",0,0)
	theFrame.ResetButton:SetScript("OnClick",function() Recount:ShowReset() end)
	theFrame.ResetButton:SetFrameLevel(theFrame.ResetButton:GetFrameLevel()+1)

	theFrame.FileButton=CreateFrame("Button",nil,theFrame)
	theFrame.FileButton:SetNormalTexture("Interface\\Buttons\\UI-GuildButton-PublicNote-Up.blp")
	theFrame.FileButton:SetPushedTexture("Interface\\Buttons\\UI-GuildButton-PublicNote-Down.blp")	
	theFrame.FileButton:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight.blp")
	theFrame.FileButton:SetWidth(16)
	theFrame.FileButton:SetHeight(16)
	theFrame.FileButton:SetPoint("RIGHT",theFrame.ResetButton,"LEFT",0,0)
	theFrame.FileButton:SetScript("OnClick",function() 
						Recount:FightDropDownOpen(this)
						ToggleDropDownMenu(1, nil, Recount_FightDropDownMenu) 
						end)
	theFrame.FileButton:SetFrameLevel(theFrame.FileButton:GetFrameLevel()+1)

	theFrame.ConfigButton=CreateFrame("Button",nil,theFrame)
	theFrame.ConfigButton:SetNormalTexture("Interface\\Addons\\Recount\\Textures\\icon-config")
	theFrame.ConfigButton:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight.blp")
	theFrame.ConfigButton:SetWidth(16)
	theFrame.ConfigButton:SetHeight(16)
	theFrame.ConfigButton:SetPoint("RIGHT",theFrame.FileButton,"LEFT",0,0)
	theFrame.ConfigButton:SetScript("OnClick",function() Recount:ShowConfig() end)
	theFrame.ConfigButton:SetFrameLevel(theFrame.ConfigButton:GetFrameLevel()+1)

	theFrame.ReportButton=CreateFrame("Button",nil,theFrame)
	theFrame.ReportButton:SetNormalTexture("Interface\\Buttons\\UI-GuildButton-MOTD-Up.blp")
	theFrame.ReportButton:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight.blp")
	theFrame.ReportButton:SetWidth(16)
	theFrame.ReportButton:SetHeight(16)
	theFrame.ReportButton:SetPoint("RIGHT",theFrame.ConfigButton,"LEFT",0,0)
	theFrame.ReportButton:SetScript("OnClick",function() Recount:ShowReport("Main",Recount.ReportData) end)
	theFrame.ReportButton:SetFrameLevel(theFrame.ReportButton:GetFrameLevel()+1)

	window.Rows={}
	window.CurRows=0
	window.RowsCreated=0

	window.DispTableSorted={}
	window.DispTableLookup={}

	theFrame.SavePosition=Recount.SaveMainWindowPosition
	Recount:RestoreMainWindowPosition(Recount.db.profile.MainWindow.Position.x,Recount.db.profile.MainWindow.Position.y,Recount.db.profile.MainWindow.Position.w,Recount.db.profile.MainWindow.Position.h)
	--Recount:ResizeMainWindow()
	Recount:SetupMainWindowButtons()
	Recount:ScheduleRepeatingTimer("RefreshMainWindow",1,true)

	if not Recount.db.profile.MainWindowVis then
		theFrame:Hide()
	end
end

function Recount:CreateHealingWindowShell()
	local window = Recount:GetWindow("healing")
	if window.Frame then
		return window.Frame
	end

	local frame = Recount:CreateMainWindowFrame("healing")
	window.Frame = frame
	frame.SavePosition = Recount.SaveNamedWindowPosition

	local scrollName = (frame:GetName() or "Recount_HealingWindow").."_ScrollBar"
	frame.ScrollBar=CreateFrame("SCROLLFRAME",scrollName,frame,"FauxScrollFrameTemplate")
	frame.ScrollBar:ClearAllPoints()
	frame.ScrollBar:SetPoint("TOPLEFT",frame,"TOPLEFT",2,-32)
	frame.ScrollBar:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-6,4)
	Recount:SetupScrollbar(scrollName)
	if not Recount.db.profile.MainWindow.ShowScrollbar then
		Recount:HideScrollbarElements(scrollName)
	end

	frame:SetScript("OnSizeChanged", function()
		UpdateAuxWindowRowLayout("healing")
	end)

	frame:ClearAllPoints()
	if not Recount:RestoreNamedWindowPosition("healing", frame) then
		if Recount.MainWindow then
			local left = Recount.MainWindow:GetLeft()
			local top = Recount.MainWindow:GetTop()
			if left and top then
				frame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", left + 40, top - 40)
			else
				frame:SetPoint("CENTER", UIParent, "CENTER", 40, -40)
			end
		else
			frame:SetPoint("CENTER", UIParent, "CENTER", 40, -40)
		end
	end

	Recount.HealingWindow = frame
	DuplicateMainWindowRows("healing")
	return frame
end

function Recount:SetupMainWindowButtons()
	for k, v in pairs(Recount.db.profile.MainWindow.Buttons) do
		if v then
			Recount.MainWindow[k]:Show()
			Recount.MainWindow[k]:SetWidth(16)
		else
			--Have to use width of 1 since 0 is invalid but you can't tell the diff really
			Recount.MainWindow[k]:SetWidth(1)
			Recount.MainWindow[k]:Hide()
			
		end
	end
end


--Actual Data Functions
local function sortFunc(a, b)
	if a[2]>b[2] then
		return true
	elseif a[2]==b[2] then
		if a[1]<b[1] then
			return true
		end
	end
	return false
end

function Recount:LoadMainWindowData(DataTable)
	Recount.MainWindowData=DataTable
	Recount:SetMainWindowMode(Recount.db.profile.MainWindowMode or 1)
end

local ConvertName={
	OverallData="(Overall)",
	CurrentFightData="(Current)",
	LastFightData="(Last)",
}


function Recount:SetMainWindowMode(mode)
if not mode or mode > #Recount.MainWindowData then
mode = 1
end

Recount.db.profile.MainWindowMode=mode
Recount.DetailMode=1
local data=Recount.MainWindowData[mode]
Recount.MainWindow.Title:SetText(data[1])
Recount.MainWindow.GetData=data[2]
Recount.MainWindow.TooltipFunc=data[3]
Recount.MainWindow.SpecialTotal=data[4]
Recount.MainWindow.RealtimeSettings=data[5]
local window = GetMainWindowState()
Recount:FreeTableRecurseLimit(window.DispTableSorted,1)
Recount:FreeTable(window.DispTableLookup)
window.DispTableSorted=Recount:GetTable()
window.DispTableLookup=Recount:GetTable()
Recount:RefreshMainWindow()
end

function me:UpdateDetailData()
	if Recount.DetailWindow:IsVisible() and Recount.MainWindow.Selected then
		local _, Data=Recount.MainWindow:GetData(Recount.db2.combatants[Recount.MainWindow.Selected])
		local mode=Recount.DetailMode

		if type(Data)=="table" then
			if type(Data[mode][2])~="function" then
				Recount:SetupDetailTitles(Recount.MainWindow.Selected,Data[mode][2],Data[mode][3])
				Recount:FillUpperDetailTable(Data[mode][1])
			else
				Data[mode][2](Recount,Recount.MainWindow.Selected,Data[mode][1])
			end
		end
	end
end

function Recount:MainWindowNextMode()
	local mode=Recount.db.profile.MainWindowMode+1
	if mode>table.maxn(Recount.MainWindowData) then
		mode=1
	end
	Recount:SetMainWindowMode(mode)

	me:UpdateDetailData()
end

function Recount:MainWindowPrevMode()
	local mode=Recount.db.profile.MainWindowMode-1
	if mode==0 then
		mode=table.maxn(Recount.MainWindowData)
	end
	Recount:SetMainWindowMode(mode)

	me:UpdateDetailData()
end

function Recount:DetailWindowNextMode()
	local _, Data=Recount.MainWindow:GetData(Recount.db2.combatants[Recount.MainWindow.Selected])
	
	local mode=Recount.DetailMode+1
	if not Data or type(Data)~="table" or mode>table.maxn(Data) then
		mode=1
	end
	Recount.DetailMode=mode
	Recount.DetailWindow.Locked=false

	me:MainWindowSelectPlayer(Recount.MainWindow.Selected)
end

function Recount:DetailWindowPrevMode()
	local _, Data=Recount.MainWindow:GetData(Recount.db2.combatants[Recount.MainWindow.Selected])
	local mode=Recount.DetailMode-1
	if mode==0 then
		mode=Data and type(Data)=="table" and table.maxn(Data) or 1
	end
	Recount.DetailMode=mode
	Recount.DetailWindow.Locked=false
	
	me:MainWindowSelectPlayer(Recount.MainWindow.Selected)
end

function me:MainWindowSelectPlayer(name)
	if IsShiftKeyDown() then
		me:ShowGraphWindow(name)
		return
	end
	
	if IsControlKeyDown() and IsAltKeyDown() then -- Elsia: Add delete combatant feature
		me:DeleteCombatant(name)
		return
	end
	
	local Settings=Recount.MainWindow.RealtimeSettings
	if IsControlKeyDown() and Settings then
		Recount:CreateRealtimeWindow(name,Settings[1],Settings[2])
		return
	end

	if IsAltKeyDown() then
		me:AddCombatantToGraph(name)
		return
	end

	me:ShowDetail(name)
end

function me:ShowGraphWindow(name)
	Recount:SetGraphData(name,Recount.db2.combatants[name].TimeData,Recount.db2.CombatTimes)
	Recount.GraphCompare=false
end

function me:ShowRealtime(name)
	local Settings=Recount.MainWindow.RealtimeSettings
	if Settings then
		Recount:CreateRealtimeWindow(name,Settings[1],Settings[2])
	end
end

function me:ShowDetail(name)
	local _, Data=Recount.MainWindow:GetData(Recount.db2.combatants[name])
	
	if type(Data)=="table" then
		Recount.MainWindow.Selected=name
		local mode=Recount.DetailMode

		if type(Data[mode][2])~="function" then
			Recount:SetupDetailTitles(name,Data[mode][2],Data[mode][3])
			Recount:FillUpperDetailTable(Data[mode][1])
			Recount:SelectUpperDetailTable(1)
		else
			Data[mode][2](Recount,name,Data[mode][1])
			Data[mode][3](Recount,1)
		end

		Recount:UpdateSummaryMode(name)
		Recount:SetWindowTop(Recount.DetailWindow)
	end
end

function Recount:CheckShowPet(mob)
	if mob.type == "Pet" then
		return Recount.db.profile.Filters.Show[DetermineType(mob.Owner)]
	else
		return true
	end
end

local MaxValue = 0

function Recount:RefreshMainWindow(datarefresh)
local MainWindow = Recount.MainWindow
local window = GetMainWindowState()
if not MainWindow.GetData or not MainWindow:IsShown() then
return
end
	
	-- For periodic data refreshes, only refresh if we actually got new stored data.
	if datarefresh and not Recount.NewData then
		return
	else
		Recount.NewData = nil
	end
	
	local data=Recount.db2.combatants
	local i
local dispTable=window.DispTableSorted
local lookup=window.DispTableLookup
	local Total=0
	local TotalPerSec=0
	local Value,PerSec

	if type(Recount.MainWindowData[Recount.db.profile.MainWindowMode][6])=="function" then
		MainWindow.Title:SetText(Recount.MainWindowData[Recount.db.profile.MainWindowMode][6]())
	end

	for k,v in pairs(lookup) do
		if v[4].Fights[Recount.db.profile.CurDataSet] then
			Value=MainWindow:GetData(v[4],1)
		else
			Value=0
		end
		if Value<=0 then
			lookup[k]=nil
					
			for k2,v2 in pairs(dispTable) do
				if v2[1]==v[4] then
					table.remove(dispTable,k2)
					break
				end
			end
		end

	end

	local noUpdates = true
	local FiltersShow = Recount.db.profile.Filters.Show
	local Combatants = Recount.db2.combatants
	local ClassColors = Recount.db.profile.Colors.Class

	if data and type(data)=="table" then
		for k,v in pairs(data) do
			--[[if not v then Recount:Print("Unit: "..k.." has nil data, please report")
			elseif not v.type then
				Recount:Print("Unit: "..k.." has nil type: "..(v.LastFlags or "nil").." "..(v.enClass or "nil"))
				--Recount:Print(name.." "..Recount.db2.combatants[name].type.." "..Recount.db2.combatants[name].enClass)
			elseif v.type == "Pet" and not v.Owner then  Recount:Print("Unit: "..k.." has nil owner, please report")
			end]]
			if v and v.type and FiltersShow[v.type] and not (v.type == "Pet" and v.Owner and Combatants[v.Owner] and not FiltersShow[Combatants[v.Owner].type]) then -- Elsia: Added owner inheritance filtering for pets
				if v.Fights and v.Fights[Recount.db.profile.CurDataSet] then
					Value,PerSec=MainWindow:GetData(v,1)
					
					if Value>0 then
						if v.type ~= "Pet" or not Recount.db.profile.MergePets then -- Elsia: Only add to total if not merging pets.
							Total=Total+Value
							if type(PerSec)=="number" then
								TotalPerSec=TotalPerSec + PerSec
							end
						end
						
						if type(lookup[k])=="table" then
							if Value~=lookup[k][2] then
								lookup[k][1]=k
								lookup[k][2]=Value
								lookup[k][3]=v.enClass -- ClassColors[v.enClass]
								lookup[k][4]=v
								lookup[k][5]=PerSec
								noUpdates = false
							end
						else
							lookup[k]={k,Value,v.enClass,v,PerSec} -- Recount.Colors:GetColor("Class",v.enClass)
							tinsert(dispTable,lookup[k])
							noUpdates = false
						end
					elseif type(lookup[k])=="table" then
						lookup[k] = nil
						
						for k2,v2 in ipairs(dispTable) do
							if v2[1]==k then
								tremove(dispTable,k2)
								break
							end
						end
					end
				end
			end
		end
	end

	local MainWindow_Settings = Recount.db.profile.MainWindow
	
	if noUpdates==false and table.maxn(dispTable)>0 then
		table.sort(dispTable,sortFunc)
		MaxValue=dispTable[1][2]
	end

	local RowWidth=MainWindow:GetWidth()-4
if table.getn(dispTable)>window.CurRows and MainWindow_Settings.ShowScrollbar == true then
RowWidth=MainWindow:GetWidth()-23
end

FauxScrollFrame_Update(MainWindow.ScrollBar, table.getn(dispTable), window.CurRows, 20)
	local offset = FauxScrollFrame_GetOffset(MainWindow.ScrollBar)

	if type(MainWindow.SpecialTotal)=="function" then
		Total=MainWindow:SpecialTotal()
	end

local rows = window.Rows
	
	local MainWindow_BarText_RankNum = MainWindow_Settings.BarText.RankNum
	local MainWindow_BarText_PerSec = MainWindow_Settings.BarText.PerSec
	local MainWindow_BarText_Percent = MainWindow_Settings.BarText.Percent

if not MainWindow_Settings.HideTotalBar and window.CurRows > 0 and Total > 0 then
		if TotalPerSec > 0 then
			PerSec=string_format("%.1f", TotalPerSec)
		else
			PerSec=""
		end
		
		if not rows[0] then
			me:CreateRow(0)
		end
		
		local lefttext = MainWindow_BarText_RankNum and "0. "..L["Total"] or L["Total"]
		local righttext = Recount:FormatLongNums(Total) --string_format("%.0f",Total)
		if MainWindow_BarText_PerSec and PerSec ~= "" then
			righttext = string_format("%s (%s", righttext, PerSec)
			if MainWindow_BarText_Percent then
				righttext = string_format("%s, %.1f%%)", righttext, 100.0)
			else
				righttext = righttext .. ")"
			end
		elseif MainWindow_BarText_Percent then
			righttext = string_format("%s (%.1f%%)", righttext, 100.0)
		end
			
		me:SetBar(0,lefttext,righttext,100,"Bar","Total Bar",L["Total"],nil,nil)	-- Recount.db.profile.Colors.Bar["Total Bar"]
		me:FixRow(0)
		rows[0].name="Total"
		rows[0]:SetWidth(RowWidth)
		--offset = offset+1 -- Add a row
	else
		if rows[0] then rows[0]:Hide() end
	end
	
        for i=1, window.CurRows do
                local v=dispTable[i+offset]

                if v then
                        local percent=100*v[2]/Total
                        if v[5] then
                                if type(v[5])=="number" then
                                        PerSec=string_format("%.1f",v[5])
                                else
                                        PerSec=v[5]
                                end
                        else
                                PerSec=""
                        end
                        local lefttext = MainWindow_BarText_RankNum and i+offset..". "..v[1] or v[1]
                        local righttext = Recount:FormatLongNums(v[2]) --string_format("%.0f",v[2])
                        if MainWindow_BarText_PerSec and PerSec~="" then
                                righttext =  string_format("%s (%s", righttext, PerSec)
                                if MainWindow_BarText_Percent then
                                        righttext = string_format("%s, %.1f%%)", righttext, percent)
                                else
                                        righttext = righttext .. ")"
                                end
                        elseif MainWindow_BarText_Percent then
                                righttext = string_format("%s (%.1f%%)", righttext, percent)
                        end

                        me:SetBar(i,lefttext,righttext,100*v[2]/MaxValue,"Class",v[3],v[1],me.MainWindowSelectPlayer,v[4])
                        me:FixRow(i)
                        rows[i].name=v[1]
                else
                        rows[i]:Hide()
                end

                rows[i]:SetWidth(RowWidth)
        end

        me:UpdateDetailData()
        Recount:RefreshHealingWindow()
end



function Recount:RefreshHealingWindow()
        local modeData = GetHealingMode()
        local window, frame = GetRowWindowContext("healing")
        local curDataSet = Recount.db.profile.CurDataSet

        if not modeData or not frame or not frame:IsShown() then
                return
        end

	local w = Recount.Windows["healing"]
	if w then
		for k in pairs(w.DispTableSorted) do w.DispTableSorted[k] = nil end
		for k in pairs(w.DispTableLookup) do w.DispTableLookup[k] = nil end
	end

        local modeFunc = modeData.EvalFunc or modeData[2]

        if not modeFunc then
                return
        end

        frame.GetData = modeFunc
        frame.TooltipFunc = modeData[3]
        frame.Title:SetText(modeData[1])

        local data=Recount.db2.combatants
        local dispTable=window.DispTableSorted
        local lookup=window.DispTableLookup
        local Total=0
        local TotalPerSec=0
        local Value,PerSec

        for k,v in pairs(lookup) do
                if v[4].Fights and v[4].Fights[curDataSet] then
                        Value=modeFunc(frame, v[4], 1)
                else
                        Value=0
                end
                if Value<=0 then
                        lookup[k]=nil

                        for k2,v2 in pairs(dispTable) do
                                if v2[1]==v[4] then
                                        table.remove(dispTable,k2)
                                        break
                                end
                        end
                end

        end

        local noUpdates = true
        local FiltersShow = Recount.db.profile.Filters.Show
        local Combatants = Recount.db2.combatants

        if data and type(data)=="table" then
                for k,v in pairs(data) do
                        if v and v.type and FiltersShow[v.type] and not (v.type == "Pet" and v.Owner and Combatants[v.Owner] and not FiltersShow[Combatants[v.Owner].type]) then
                                if v.Fights and v.Fights[curDataSet] then
                                        Value,PerSec=modeFunc(frame, v, 1)

                                        if Value>0 then
                                                if v.type ~= "Pet" or not Recount.db.profile.MergePets then
                                                        Total=Total+Value
                                                        if type(PerSec)=="number" then
                                                                TotalPerSec=TotalPerSec + PerSec
                                                        end
                                                end

                                                if type(lookup[k])=="table" then
                                                        if Value~=lookup[k][2] then
                                                                lookup[k][1]=k
                                                                lookup[k][2]=Value
                                                                lookup[k][3]=v.enClass
                                                                lookup[k][4]=v
                                                                lookup[k][5]=PerSec
                                                                noUpdates = false
                                                        end
                                                else
                                                        lookup[k]={k,Value,v.enClass,v,PerSec}
                                                        tinsert(dispTable,lookup[k])
                                                        noUpdates = false
                                                end
                                        elseif type(lookup[k])=="table" then
                                                lookup[k] = nil

                                                for k2,v2 in ipairs(dispTable) do
                                                        if v2[1]==k then
                                                                tremove(dispTable,k2)
                                                                break
                                                        end
                                                end
                                        end
                                end
                        end
                end
        end

        local MaxValueHealing=0
        if noUpdates==false and table.maxn(dispTable)>0 then
                table.sort(dispTable,sortFunc)
                MaxValueHealing=dispTable[1][2]
        end

        local RowWidth=frame:GetWidth()-4
        local MainWindow_Settings = Recount.db.profile.MainWindow
        if table.getn(dispTable)>window.CurRows and MainWindow_Settings.ShowScrollbar == true then
                RowWidth=frame:GetWidth()-23
        end

        FauxScrollFrame_Update(frame.ScrollBar, table.getn(dispTable), window.CurRows, 20)
        local offset = FauxScrollFrame_GetOffset(frame.ScrollBar)

        local rows = window.Rows

        local MainWindow_BarText_RankNum = MainWindow_Settings.BarText.RankNum
        local MainWindow_BarText_PerSec = MainWindow_Settings.BarText.PerSec
        local MainWindow_BarText_Percent = MainWindow_Settings.BarText.Percent

        if not MainWindow_Settings.HideTotalBar and window.CurRows > 0 and Total > 0 then
                if TotalPerSec > 0 then
                        PerSec=string_format("%.1f", TotalPerSec)
                else
                        PerSec=""
                end

                if not rows[0] then
                        DuplicateMainWindowRows("healing")
                end

                local lefttext = MainWindow_BarText_RankNum and "0. "..L["Total"] or L["Total"]
                local righttext = Recount:FormatLongNums(Total)
                if MainWindow_BarText_PerSec and PerSec ~= "" then
                        righttext = string_format("%s (%s", righttext, PerSec)
                        if MainWindow_BarText_Percent then
                                righttext = string_format("%s, %.1f%%)", righttext, 100.0)
                        else
                                righttext = righttext .. ")"
                        end
                elseif MainWindow_BarText_Percent then
                        righttext = string_format("%s (%.1f%%)", righttext, 100.0)
                end

                SetHealingBar(window,0,lefttext,righttext,100,"Bar","Total Bar")
                FixHealingRow(window,0)
                rows[0].name="Total"
                rows[0]:SetWidth(RowWidth)
        else
                if rows[0] then rows[0]:Hide() end
        end

        for i=1, window.CurRows do
                local v=dispTable[i+offset]

                if v then
                        local percent=Total>0 and 100*v[2]/Total or 0
                        if v[5] then
                                if type(v[5])=="number" then
                                        PerSec=string_format("%.1f",v[5])
                                else
                                        PerSec=v[5]
                                end
                        else
                                PerSec=""
                        end
                        local lefttext = MainWindow_BarText_RankNum and i+offset..". "..v[1] or v[1]
                        local righttext = Recount:FormatLongNums(v[2])
                        if MainWindow_BarText_PerSec and PerSec~="" then
                                righttext =  string_format("%s (%s", righttext, PerSec)
                                if MainWindow_BarText_Percent then
                                        righttext = string_format("%s, %.1f%%)", righttext, percent)
                                else
                                        righttext = righttext .. ")"
                                end
                        elseif MainWindow_BarText_Percent then
                                righttext = string_format("%s (%.1f%%)", righttext, percent)
                        end

                        local barValue = MaxValueHealing>0 and 100*v[2]/MaxValueHealing or 0
                        SetHealingBar(window,i,lefttext,righttext,barValue,"Class",v[3])
                        FixHealingRow(window,i)
                        rows[i].name=v[1]
                else
                        if rows[i] then
                                rows[i]:Hide()
                        end
                end

                if rows[i] then
                        rows[i]:SetWidth(RowWidth)
                end
        end
end

local ConvertDataSet2={}
ConvertDataSet2["OverallData"]="a_overall"
ConvertDataSet2["CurrentFightData"]="b_current"
ConvertDataSet2["LastFightData"]="c_last"

function Recount:FightDropDownOpen(myframe)
	Recount_FightDropDownMenu = CreateFrame("Frame", "Recount_FightDropDownMenu", myframe);
	Recount_FightDropDownMenu.displayMode = "MENU";
	Recount_FightDropDownMenu.initialize	= me.CreateFightDropdown;
	local leftPos = myframe:GetLeft() -- Elsia: Side code adapted from Mirror
	local rightPos = myframe:GetRight()
	local side
	local oside
	if not rightPos then
		rightPos = 0
	end
	if not leftPos then
		leftPos = 0
	end

	local rightDist = GetScreenWidth() - rightPos

	if leftPos and rightDist < leftPos then
		side = "TOPLEFT"
		oside = "TOPRIGHT"
	else
		side = "TOPRIGHT"
		oside = "TOPLEFT"
	end

	if tocversion == 30000 then
		UIDropDownMenu_SetAnchor(Recount_FightDropDownMenu , 0, 0, oside, myframe, side)
	else
		UIDropDownMenu_SetAnchor(0, 0, Recount_FightDropDownMenu , oside, myframe, side)
	end
end



--Should add saved datasets here
function me:CreateFightDropdown(level)
		local info = {}

		info.checked = nil
		info.text		= L["Overall Data"]
		if Recount.db.profile.CurDataSet == "OverallData" then
			info.checked = 1
		end
		info.func = function()
			Recount.db.profile.CurDataSet="OverallData"
			me:UpdateDetailData()
			ResetMainWindowDisplayCache()
			Recount.FightName="Overall Data"
			Recount:RefreshMainWindow()
		end
		UIDropDownMenu_AddButton(info, level)

		info.checked = nil
		
		info.text = L["Current Fight"]
		if Recount.db.profile.CurDataSet == "CurrentFightData" or Recount.db.profile.CurDataSet == "LastFightData" then
			info.checked = 1
		end
		info.func = function()
			if Recount.InCombat then
				Recount.db.profile.CurDataSet="CurrentFightData"
			else
				Recount.db.profile.CurDataSet="LastFightData"
			end
			me:UpdateDetailData()
			ResetMainWindowDisplayCache()
			Recount.FightName="Current Fight"
			Recount:RefreshMainWindow()
		end
		UIDropDownMenu_AddButton(info, level)

		for k, v in pairs(Recount.db2.FoughtWho) do
			info.checked = nil
			info.text = L["Fight"].." "..k.." - "..v
			if Recount.db.profile.CurDataSet == "Fight"..k then
				info.checked = 1
			end
			info.func = function()
				Recount.db.profile.CurDataSet="Fight"..k
				me:UpdateDetailData()
				ResetMainWindowDisplayCache()
				Recount.FightName=v
				Recount:RefreshMainWindow()
			end
			UIDropDownMenu_AddButton(info, level)
		end
end

function Recount:ModeDropDownOpen(myframe)
	Recount_ModeDropDownMenu = CreateFrame("Frame", "Recount_ModeDropDownMenu", myframe);
	Recount_ModeDropDownMenu.displayMode = "MENU";
	Recount_ModeDropDownMenu.initialize	= me.CreateModeDropdown;
	local leftPos = myframe:GetLeft() -- Elsia: Side code adapted from Mirror
	local rightPos = myframe:GetRight()
	local side
	local oside
	if not rightPos then
		rightPos = 0
	end
	if not leftPos then
		leftPos = 0
	end

	local rightDist = GetScreenWidth() - rightPos

	if leftPos and rightDist < leftPos then
		side = "TOPLEFT"
		oside = "TOPRIGHT"
	else
		side = "TOPRIGHT"
		oside = "TOPLEFT"
	end
	if tocversion == 30000 then
		UIDropDownMenu_SetAnchor(Recount_ModeDropDownMenu , 0, 0, oside, myframe, side)
	else
		UIDropDownMenu_SetAnchor(0, 0, Recount_ModeDropDownMenu , oside, myframe, side)
	end
end

function me:CreateModeDropdown(level)
	local info = {}
	for k,v in pairs(Recount.MainWindowData) do

		info.checked = nil
		info.text = v[1]
		info.func = function() Recount:SetMainWindowMode(k) end
		if Recount.db.profile.MainWindowMode==k then
			info.checked = 1
		else
			info.checked = nil
		end
		UIDropDownMenu_AddButton(info, level)
	end
end

local ConvertDataSet={}
ConvertDataSet["OverallData"] = L["Overall Data"]
ConvertDataSet["CurrentFightData"]= L["Current Fight"]
ConvertDataSet["LastFightData"] = L["Last Fight"]

function Recount:ReportData(amount,loc,loc2)
	local dataMode=Recount.MainWindowData[Recount.db.profile.MainWindowMode]
	local data=Recount.db2.combatants
	local i
	local maxValue = 0
	local window = GetMainWindowState()
	local reportTable=window.DispTableSorted
	local lookup=window.DispTableLookup
	local Total=0
	local TotalPerSec=0
	local Value,PerSec
	local send = Recount:CreateReportSender(loc, loc2)

	local MainWindow_Settings = Recount.db.profile.MainWindow

	if type(data)=="table" then
		for k,v in pairs(data) do
			if v and v.type and Recount.db.profile.Filters.Show[v.type]  and not (v.type == "Pet" and v.Owner and not Recount.db.profile.Filters.Show[Recount.db2.combatants[v.Owner].type])  then -- Elsia: Added owner inheritance filtering for pets
				if v.Fights[Recount.db.profile.CurDataSet] then
					Value,PerSec=dataMode[2](this,v,1)
					if Value>0 then
						if (v.type ~= "Pet" or not Recount.db.profile.MergePets) then -- Elsia: Only add to total if not merging pets.
							Total=Total+Value
							if type(PerSec)=="number" then
								TotalPerSec=TotalPerSec + PerSec
							end
					end

						if type(lookup[k])=="table" then
							lookup[k][1]=k
							lookup[k][2]=Value
							lookup[k][5]=PerSec
						else
							lookup[k]={k,Value,Recount.Colors:GetColor("Class",v.enClass),v,PerSec}
							table.insert(reportTable,lookup[k])
						end
					end
				end
			end
		end
	end
	
	if table.maxn(reportTable)>0 then
		table.sort(reportTable,sortFunc)
		maxValue=reportTable[1][2] or 0
	end

	if type(dataMode[4])=="function" then
		Total=Recount.MainWindow:SpecialTotal()
	end
	
	if type(dataMode[6])=="function" then
		send("Recount - "..dataMode[6]())
	else
		if ConvertDataSet[Recount.db.profile.CurDataSet] then
			send("Recount - "..dataMode[1]..L[" for "]..ConvertDataSet[Recount.db.profile.CurDataSet])
		elseif Recount.FightName then -- Elsia: Cover nil error here.
			send("Recount - "..dataMode[1]..L[" for "]..Recount.FightName)
		end
	end

	if not MainWindow_Settings.HideTotalBar and Total > 0 then
		if TotalPerSec > 0 then
			PerSec=string_format("%.1f ", TotalPerSec)
		else
			PerSec=""
		end
		
		send("0. Total  "..(math.floor(10*Total)/10).." ("..PerSec..(math.floor(1000)/10).."%)")
	end

	for i=1,amount do
		if reportTable[i] and reportTable[i][2]>0 then
			if reportTable[i][5] then
				if type(reportTable[i][5])=="number" then
					PerSec=string.format("%.1f, ",reportTable[i][5])
				else
					PerSec=reportTable[i][5]
				end
			else
				PerSec=""
			end
			send(i..". "..reportTable[i][1].."  "..(math.floor(10*reportTable[i][2])/10).." ("..PerSec..(math.floor(1000*reportTable[i][2]/Total)/10).."%)")
		end
	end
end


--Functions for graph data selecting
local GraphName={
	Damage="Damage",
	DamageTaken="Damage Taken",
	Healing="Healing",
	HealingTaken="Healing Taken",
	Overhealing="Overhealing",
}

function Recount:AddGraphNameEntry(k,v)
	GraphName.insert(k,v)
end

function me:AddCombatantToGraph(name)
	local DataComparing=Recount.MainWindowData[Recount.db.profile.MainWindowMode][7]
	if not DataComparing then
		return
	end

	local DataName=GraphName[DataComparing]

	

	if (not Recount.GraphCompare) or (not Recount.GraphWindow:IsShown()) or Recount.GraphCompareMode~=DataComparing then		
		Recount.GraphCompare=true
		Recount.GraphCompareMode=DataComparing

		if not Recount.GraphClass then
			Recount.GraphClass={}
		end

		for k, _ in pairs(Recount.GraphClass) do
			Recount.GraphClass[k]=nil
		end
		Recount.GraphClass[name.."'s "..DataName]=Recount.db2.combatants[name].enClass

		Recount:SetGraphData(DataName.." Comparison",{[name.."'s "..DataName]=Recount.db2.combatants[name].TimeData and Recount.db2.combatants[name].TimeData[DataComparing]},Recount.db2.CombatTimes)
		return
	end
	
	Recount.GraphWindow.Data[name.."'s "..DataName]=Recount.db2.combatants[name].TimeData and Recount.db2.combatants[name].TimeData[DataComparing]
	Recount.GraphClass[name.."'s "..DataName]=Recount.db2.combatants[name].enClass
	Recount:SetGraphData(DataName.." Comparison",Recount.GraphWindow.Data,Recount.db2.CombatTimes)	
end

function me:AddCombatantToGraphData(name)
	local DataComparing=Recount.MainWindowData[Recount.db.profile.MainWindowMode][7]
	if not DataComparing then
		return
	end

	local DataName=GraphName[DataComparing]

	

	if (not Recount.GraphCompare) or (not Recount.GraphWindow:IsShown()) or Recount.GraphCompareMode~=DataComparing then		
		Recount.GraphCompare=true
		Recount.GraphCompareMode=DataComparing

		if not Recount.GraphClass then
			Recount.GraphClass={}
		end

		for k, _ in pairs(Recount.GraphClass) do
			Recount.GraphClass[k]=nil
		end
		Recount.GraphClass[name.."'s "..DataName]=Recount.db2.combatants[name].enClass

		Recount.GraphWindow.Data={}
		Recount.GraphWindow.Data[name.."'s "..DataName]=Recount.db2.combatants[name].TimeData[DataComparing]
		return
	end
	
	if Recount.db2.combatants[name].TimeData then
		Recount.GraphWindow.Data[name.."'s "..DataName]=Recount.db2.combatants[name].TimeData[DataComparing]
		Recount.GraphClass[name.."'s "..DataName]=Recount.db2.combatants[name].enClass
	end
end

function Recount:AddAllToGraph()
	local DataComparing=Recount.MainWindowData[Recount.db.profile.MainWindowMode][7]
	if not DataComparing then
		return
	end
	local dispTable=GetMainWindowState().DispTableSorted
	local DataName=GraphName[DataComparing]
	for _,v in pairs(dispTable) do
		me:AddCombatantToGraphData(v[1])
	end

	Recount:SetGraphData(DataName.." Comparison",Recount.GraphWindow.Data,Recount.db2.CombatTimes)
end

function Recount:SaveMainWindowPosition()
        local xOfs, yOfs = self:GetCenter()  -- Elsia: This is clean code straight from ckknight's pitbull
        local s = self:GetEffectiveScale()
        local uis = UIParent:GetScale()
	xOfs = xOfs*s - GetScreenWidth()*uis/2
	yOfs = yOfs*s - GetScreenHeight()*uis/2
	
	Recount.db.profile.MainWindow.Position.x=xOfs/uis
	Recount.db.profile.MainWindow.Position.y=yOfs/uis
	Recount.db.profile.MainWindow.Position.w=self:GetWidth()
	Recount.db.profile.MainWindow.Position.h=self:GetHeight()
end

local function EnsureWindowProfilePosition(windowID)
        if not windowID or windowID == "main" then
                return
        end
        local profile = Recount.db and Recount.db.profile
        if not profile then
                return
        end
        profile.Windows = profile.Windows or {}
        local windowProfile = profile.Windows[windowID]
        if not windowProfile then
                windowProfile = {}
                profile.Windows[windowID] = windowProfile
        end
        windowProfile.Position = windowProfile.Position or {}
        return windowProfile.Position
end

function Recount:SaveNamedWindowPosition()
        local windowID = self.windowID
        if not windowID or windowID == "main" then
                return Recount.SaveMainWindowPosition(self)
        end
        local pos = EnsureWindowProfilePosition(windowID)
        if not pos then
                return
        end
        local xOfs, yOfs = self:GetCenter()
        local s = self:GetEffectiveScale()
        local uis = UIParent:GetScale()
        xOfs = xOfs * s - GetScreenWidth() * uis / 2
        yOfs = yOfs * s - GetScreenHeight() * uis / 2

        pos.x = xOfs / uis
        pos.y = yOfs / uis
        pos.w = self:GetWidth()
        pos.h = self:GetHeight()
end

function Recount:RestoreNamedWindowPosition(windowID, frame)
        if not windowID or windowID == "main" or not frame then
                return false
        end
        local profile = Recount.db and Recount.db.profile
        local windows = profile and profile.Windows
        local windowProfile = windows and windows[windowID]
        local pos = windowProfile and windowProfile.Position
        if not pos or pos.x == nil or pos.y == nil then
                return false
        end
        local s = frame:GetEffectiveScale()
        local uis = UIParent:GetScale()
        frame:ClearAllPoints()
        frame:SetPoint("CENTER", UIParent, "CENTER", pos.x * uis / s, pos.y * uis / s)
        if pos.w and pos.h then
                frame:SetWidth(pos.w)
                frame:SetHeight(pos.h)
        end
        return true
end

function Recount:RestoreMainWindowPosition(x, y, width, height)
	local f = Recount.MainWindow
	local s = f:GetEffectiveScale() -- Elsia: Fixed position code, with inspiration from ckknight's handing in pitbull
	local uis = UIParent:GetScale()
	f:SetPoint("CENTER", UIParent, "CENTER", x*uis/s, y*uis/s)
	f:SetWidth(width)
	f:SetHeight(height)
	Recount:ResizeMainWindow()
	f:SavePosition()
end
