--[[
************************************************************************

tracker.lua

File date: 2010-07-13T14:36:51Z
File revision: 237
Project revision: 237
Project version: Locale update


Author: Angelike

************************************************************************
]]--

local beql = LibStub("AceAddon-3.0"):GetAddon("beql")
local L = LibStub("AceLocale-3.0"):GetLocale("beql")

local beqlQuestWatchFrame = beqlQuestWatchFrame

function beql:QuestTracker_OnMouseUp(button)
	if button == "LeftButton" and (GetTime() - self.leftclicktime) < 1 then
		if not beql.db.char.QuestWatchMinimized then
			beql:QuestTracker_Click(self, button)
		end
	elseif button == "RightButton" and (GetTime() - self.rightclicktime) < 1 then
		if not beql.db.char.QuestWatchMinimized then
			beql:QuestTracker_Click(self, button)
		end
	end
end

-- minimize questtracker
function beql:QuestTracker_TrackerMinimize()
	beql.db.char.QuestWatchMinimized = true
	beqlQuestWatchFrame.TitleFrame.Minimize:SetNormalTexture("Interface\\AddOns\\beql\\Images\\restore_up")
	beqlQuestWatchFrame.TitleFrame.Minimize:SetPushedTexture("Interface\\AddOns\\beql\\Images\\restore_down")

	-- Hide Lines
	beqlQuestWatchFrame.LineFrame:Hide();

	local minWidth = beqlQuestWatchFrame.TitleFrame.Text:GetStringWidth()+32
	beqlQuestWatchFrame:SetHeight(1)
	beqlQuestWatchFrame:SetWidth(minWidth)
	beqlQuestWatchFrame.Backdrop:Hide()
end

-- maximze questtracker
function beql:QuestTracker_TrackerMaximize()
	beql.db.char.QuestWatchMinimized = false
	beqlQuestWatchFrame.TitleFrame.Minimize:SetNormalTexture("Interface\\AddOns\\beql\\Images\\minimize_up")
	beqlQuestWatchFrame.TitleFrame.Minimize:SetPushedTexture("Interface\\AddOns\\beql\\Images\\minimize_down")

	beqlQuestWatchFrame.LineFrame:Show()
	beqlQuestWatchFrame.Backdrop:Show()
	beql:QuestTracker_SceduleUpdate()
	beqlQuestWatchAnchor.updateTime = 0.002;
end

-- Toggles Questtracker status between active and inactive
function beql:QuestTracker_ToggleStatus(inactive)

	-- unhook old scripts
	local hooks = {'AddQuestWatch','RemoveQuestWatch','IsQuestWatched','GetNumQuestWatches','GetQuestIndexForWatch',}
	for k in ipairs(hooks) do
		beql:Unhook(hooks[k]);
	end

	-- unregister Callbacks
	local callbacks = {'Quest_Gained','Update','Ready','Quest_Lost',}
	for k in ipairs(callbacks) do
		beqlQ.UnregisterCallback(beql, callbacks[k]);
	end

	WatchFrame_AddObjectiveHandler(WatchFrame_DisplayTrackedQuests);
	--WatchFrame_RemoveObjectiveHandler(beql.DisplayTrackedQuests);


	beqlQuestWatchFrame:Hide();

	WATCHFRAME_MAXQUESTS = 10;
	MAX_WATCHABLE_QUESTS = 10;
	
	if (not inactive) then
		beql:debugprint("load questtracker")

		-- Callbacks
		for k in ipairs(callbacks) do
			beqlQ.RegisterCallback(beql, callbacks[k], beql['Quixote_' .. callbacks[k]]);
		end

		WatchFrame_RemoveObjectiveHandler(WatchFrame_DisplayTrackedQuests);
		--WatchFrame_AddObjectiveHandler(beql.DisplayTrackedQuests);

		-- make some hooks
		for k in ipairs(hooks) do
			beql:RawHook(hooks[k], 'Hooks_' .. hooks[k], true);
		end

		WATCHFRAME_MAXQUESTS = 25;
		MAX_WATCHABLE_QUESTS = 25;

		beql:debugprint("questracker loaded")
		
		beql:QuestTracker_SceduleUpdate()
	end

	QuestLog_Update();
	WatchFrame_ClearDisplay();
	WatchFrame_Update(WatchFrame);

end

local nametable, playerlevel, showzones = {}

function beql:QuestTracker_SortWatchedQuests()
	local GetQuestLogTitle = GetQuestLogTitle;
	local NumQuestLogEntries = GetNumQuestLogEntries();
	if NumQuestLogEntries == 0 then
		return;
	end

	if playerlevel ~= UnitLevel("player") or beql.db.profile.QuestTracker.ShowZones ~= showzones then
		showzones = beql.db.profile.QuestTracker.ShowZones;
		playerlevel = UnitLevel("player");
		table.wipe(nametable);
	end

	-- cleanup unused uid's
	local changed, rebuild
	while ( not changed ) do
		changed = 1;
		for i=1, #beql.db.char.QuestWatchIDs do
			-- rebuild table if key not exist
			if not nametable[beql.db.char.QuestWatchIDs[i]] then
				rebuild = true;
				--break;
			end
			if not beql.uID_2_index[beql.db.char.QuestWatchIDs[i]] then
				tremove(beql.db.char.QuestWatchIDs,i);
				changed = nil;
				break;
			end
		end
	end

	if rebuild then
		local curheader, uID;
		for i=1, NumQuestLogEntries do
			uID = select(9,GetQuestLogTitle(i));
			if uID == 0 then
				curheader = beql.db.profile.QuestTracker.ShowZones and (GetQuestLogTitle(i) .. ".") or "";
			else
				for k in ipairs(beql.db.char.QuestWatchIDs) do
					if beql.db.char.QuestWatchIDs[k] == uID and not nametable[uID] then
						local name, level = GetQuestLogTitle(i);
						tinsert(nametable, uID, curheader .. level .. "." .. name);
					end
				end
			end
		end
	end

	table.sort(beql.db.char.QuestWatchIDs, function(a,b)
		beql:debugprint('string a: ' .. tostring(a) .. ' - ' .. tostring(nametable[a]))
		beql:debugprint('string b: ' .. tostring(b) .. ' - ' .. tostring(nametable[b]))
		if nametable[a] < nametable[b] then
			return true;
		end
		return false;
	end)
end

-- Update Base Stats of the Frame like Color etc...
local FontHeight, FontSpacing, QuestSpacing, ZoneSpacing
function beql:QuestTracker_UpdateFrame()
	
	FontHeight, FontSpacing, QuestSpacing, ZoneSpacing = nil, nil, nil, nil
	local QuestTrackerOptions = beql.db.profile.QuestTracker

	beql:debugprint("beql:QuestTracker_UpdateFrame");

	-- movability
	if QuestTrackerOptions.locked then
		beqlQuestWatchFrame:RegisterForDrag(0)
		beqlQuestWatchAnchor:SetMovable(nil);
	else
		beqlQuestWatchFrame:RegisterForDrag("LeftButton")
		beqlQuestWatchAnchor:SetMovable(true);
	end

	-- Title
	local title = beqlQuestWatchFrame.TitleFrame
	if QuestTrackerOptions.ShowHeader then
		title:Show();
	else
		title:Hide();
	end

	if QuestTrackerOptions.locked then
		beqlQuestWatchFrameTitle:RegisterForDrag(0);
		title:EnableMouse(nil);
	else
		beqlQuestWatchFrameTitle:RegisterForDrag("LeftButton");
		title:EnableMouse(true);
	end

	if QuestTrackerOptions.UseBgColors then
		if QuestTrackerOptions.CustomBgColor then
			title:SetBackdropColor(
				QuestTrackerOptions.Colors.Bg.r,
				QuestTrackerOptions.Colors.Bg.g,
				QuestTrackerOptions.Colors.Bg.b,
				QuestTrackerOptions.Colors.Bg.a
			)
			title:SetBackdropBorderColor(
				QuestTrackerOptions.Colors.BgBorder.r,
				QuestTrackerOptions.Colors.BgBorder.g,
				QuestTrackerOptions.Colors.BgBorder.b,
				QuestTrackerOptions.Colors.BgBorder.a
			)
		else
			title:SetBackdropBorderColor(
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.r,
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.g,
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.b,
				1
			)
			title:SetBackdropColor(
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.r,
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.g,
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.b,
				1
			)
		end
	else
		title:SetBackdropColor(0,0,0,0)
		title:SetBackdropBorderColor(0,0,0,0)
	end

	local titletext = title.Text
	local t1, _, t2 = titletext:GetFont();
	titletext:SetFont(t1, QuestTrackerOptions.FontHeight+2, t2)
	titletext:SetHeight(QuestTrackerOptions.FontHeight+2)


	-- Frame
	if QuestTrackerOptions.UseBgColors then
		if QuestTrackerOptions.CustomBgColor then
			beqlQuestWatchFrame.Backdrop:SetBackdropColor(
				QuestTrackerOptions.Colors.Bg.r,
				QuestTrackerOptions.Colors.Bg.g,
				QuestTrackerOptions.Colors.Bg.b,
				QuestTrackerOptions.Colors.Bg.a
			)
			beqlQuestWatchFrame.Backdrop:SetBackdropBorderColor(
				QuestTrackerOptions.Colors.BgBorder.r,
				QuestTrackerOptions.Colors.BgBorder.g,
				QuestTrackerOptions.Colors.BgBorder.b,
				QuestTrackerOptions.Colors.BgBorder.a
			)
		else
			beqlQuestWatchFrame.Backdrop:SetBackdropBorderColor(
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.r,
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.g,
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.b,
				1
			)
			beqlQuestWatchFrame.Backdrop:SetBackdropColor(
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.r,
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.g,
				TOOLTIP_DEFAULT_BACKGROUND_COLOR.b,
				1
			)
		end
	else
		beqlQuestWatchFrame.Backdrop:SetBackdropColor(0,0,0,0)
		beqlQuestWatchFrame.Backdrop:SetBackdropBorderColor(0,0,0,0)
	end

	-- Alpha
	beqlQuestWatchFrame:SetAlpha(beql.db.profile.QuestTracker.Alpha)
	
	if beqlQuestWatchFrame:IsVisible() then
		WatchFrame_Update();
	end

	return 1;
end

function beql:QuestTracker_SceduleUpdate()
	if not beqlQuestWatchAnchor.updateTime or beqlQuestWatchAnchor.updateTime < 0 or not beqlQuestWatchAnchor.doUpdate then
		beqlQuestWatchAnchor.updateTime = 0.2;
		beqlQuestWatchAnchor.doUpdate = true;
	end
end
--
-- Events
--

function beql:QuestWatchAnchor_OnUpdate(elapsed)
	if self.UIScale ~= UIParent:GetScale() then
		beql:RestoreFramePosition(self);
	end
	if not self.UpdateFrame then
		self.UpdateFrame = beql:QuestTracker_UpdateFrame()
	end
	if not self.updateTime then
		-- first time here
		self.updateTime = -1;
	elseif self.updateTime > 0 and self.doUpdate then
		self.updateTime = self.updateTime - elapsed
	elseif self.updateTime < 0 and self.doUpdate then
		self.doUpdate = nil;
		beql:QuestTracker_DisplayQuests();
	end

end

function beql:Quixote_Ready()
	WatchFrame_Update()
end

function beql:Quixote_Update()
	beql:QuestTracker_SortWatchedQuests()
	--WatchFrame_Update()
	beql:QuestTracker_SceduleUpdate()
end

function beql:QuestTracker_QuestGained( questname, uID, objectives, category, provider, player)
	local _ , id, _ ,_ , _ ,_ , complete ,_ , _ ,_ = beqlQ:GetQuestByUid(uID)

	if(complete == 1) and uID == beql.db.char.newquestid then
		beql:Quixote_Quest_Complete(questname, uID)
	end

	if beql.db.profile.QuestTracker.AddNew and uID == beql.db.char.newquestid then
		AddQuestWatch(id)
		QuestLog_Update()
		WatchFrame_Update()
	end
	beql.WatchQueue = nil
end

--
-- Hooks
--

function beql:Hooks_AddQuestWatch(questIndex)
	local uID
	if questIndex and type(questIndex) == 'string' and strfind(questIndex, 'uID:') then
		uID = tonumber(string.match(questIndex, '%d+'))
		if not uID or not beql.uID_2_index[uID] then
			assert(false, "usage: AddQuestWatch(index or 'uID:uID') - invalid uID");
			return;
		end
	elseif questIndex and type(questIndex) == 'number' then
		uID = select(9, GetQuestLogTitle(questIndex))
		if uID == 0 then
			assert(false, "usage: AddQuestWatch(index or 'uID:uID') - invalid index");
			return;
		end
	else
		assert(false, "usage: AddQuestWatch(index or 'uID:uID')")
		return;
	end

	for k in pairs(beql.db.char.QuestWatchIDs) do
		if beql.db.char.QuestWatchIDs[k] == uID then
			return;
		end
	end
	tinsert(beql.db.char.QuestWatchIDs, uID)
	beql:QuestTracker_SortWatchedQuests()
	beql:QuestTracker_SceduleUpdate()
end

function beql:Hooks_RemoveQuestWatch(questIndex)
	local uID
	if questIndex and type(questIndex) == 'string' and strfind(questIndex, 'uID:') then
		uID = tonumber(string.match(questIndex, '%d+'))
		if not uID or not beql.uID_2_index[uID] then
			assert(false, "usage: RemoveQuestWatch(index or 'uID:uID') - invalid uID");
			return;
		end
	elseif questIndex and type(questIndex) == 'number' then
		uID = select(9, GetQuestLogTitle(questIndex))
		if uID == 0 then
			assert(false, "usage: RemoveQuestWatch(index or 'uID:uID') - invalid index");
			return;
		end
	else
		assert(false, "usage: RemoveQuestWatch(index or 'uID:uID')")
		return;
	end
	local numQuestWatches = #beql.db.char.QuestWatchIDs
	for i=1, numQuestWatches do
		if beql.db.char.QuestWatchIDs[i] == uID then
			tremove(beql.db.char.QuestWatchIDs, i)
			beql:QuestTracker_SortWatchedQuests()
			beql:QuestTracker_SceduleUpdate()
			return
		end
	end
end

function beql:Hooks_IsQuestWatched(questIndex)
	local uID
	if questIndex and type(questIndex) == 'string' and strfind(questIndex, 'uID:') then
		uID = tonumber(string.match(questIndex, '%d+'))
		if not uID or not beql.uID_2_index[uID] then
			assert(false, "usage: IsQuestWatched(index or 'uID:uID') - invalid uID");
			return;
		end
	elseif questIndex and type(questIndex) == 'number' then
		uID = select(9, GetQuestLogTitle(questIndex))
		local questname = GetQuestLogTitle(questIndex)
		if uID == 0 and questname == nil then
			assert(false, "usage: IsQuestWatched(index or 'uID:uID') - invalid index");
			return;
		end
	else
		assert(false, "usage: IsQuestWatched(index or 'uID:uID')")
		return;
	end

	local numQuestWatches = #beql.db.char.QuestWatchIDs
	for i=1, numQuestWatches do
		if beql.db.char.QuestWatchIDs[i] == uID then
			return true;
		end
	end
	return false;
end

function beql:Hooks_GetNumQuestWatches()
	return table.getn(beql.db.char.QuestWatchIDs)
end

function beql:Hooks_GetQuestIndexForWatch(watchindex)
	if not watchindex or type(watchindex) ~= 'number' then
		assert(false, "usage: GetQuestIndexForWatch(index)");
		return 0;
	end

	if watchindex > table.getn(beql.db.char.QuestWatchIDs) then
		assert(false, "usage: GetQuestIndexForWatch(index) - invalid index");
		return 0;
	end

	local uID, questIndex

	uID = beql.db.char.QuestWatchIDs[watchindex]
	questIndex = beql.uID_2_index[uID] or 0

	return questIndex, uID
end

local WATCHFRAMELINES_FONTSPACING = 0

function beql:QuestTracker_DisplayQuests()
	if not beql:IsEnabled() or beql.db.profile.disabledtracker then
		return
	end
	
	beqlDebug.q = (beqlDebug.q or 0) + 1
	beqlDebugQuest:SetText("QuestNr: " .. beqlDebug.q)
	-- Don't do anything before Quixote gets his data
	if not beqlQ.firstDone then
		return 0,0
	end

	-- HACK 3.3
	local WATCHFRAME_QUEST_WITH_ITEM_HEIGHT = 48;
	
	-- beql locales
	local questIndex,isRemoved,isCollapsed
	local qTitle,qLvl,qTag,qRec,qStat,qObj,qZone,qID, qdaily
	local oText, oType, oNumP, oNumN, oComp, numObjectives, objText
	local temp,curZone
	local zoneid = 0
	local Color = {}
	local tempwidth = 0
	local tempColor,tempColor2,tempColor3
	local markerID = 0
	local completedQuests = 0
	local questWatchMaxWidth = 0
	local qObjectives, oItems

--	local zoneoffset = 5
--	local questoffset = 3.5

	beql.db.char.TrackerQuests = {}

	-- blizz locales
	local lineFrame = beqlQuestWatchFrame.LineFrame
	local _;
	local text, finished;
	local questTitle;
	local watchItemIndex = 0;

	local line;
	local lastLine;
	local HIGHLIGHT_FONT_COLOR = HIGHLIGHT_FONT_COLOR;
	local NORMAL_FONT_COLOR = NORMAL_FONT_COLOR;
	local WATCHFRAMELINES_FONTHEIGHT = beql.db.profile.QuestTracker.FontHeight

	local maxWidth = 0;
	local questwidth = 0

	local iconHeightLeft = 0;
	local questLogTitleText

	local maxtrackerwidth, maxheaderwidth, maxiconwidth

	if not beql.db.profile.QuestTracker.AutoResize then
		maxtrackerwidth = beql.db.profile.QuestTracker.FixedWidth
		if ( WatchFrame.showObjectives ) then
			maxheaderwidth = beql.db.profile.QuestTracker.FixedWidth - WATCHFRAME_MAP_BUTTON_WIDTH - 8
		else
			maxheaderwidth = beql.db.profile.QuestTracker.FixedWidth
		end
	end

	for i = 1, GetNumQuestWatches() do
		questWidth = 0;
		questIndex = GetQuestIndexForWatch(i);

		qID = nil;
		if questIndex then
			questLogTitleText = beql:GetTaggedQuestLogTitle(questIndex)
			-- Fix submitted by Ben Schreiber for MarsQuestOrganizer
			if questLogTitleText then
				qID, _ , qTitle, qLvl, qTag, qObj, qStat, qRec, qdaily, qZone = beqlQ:GetQuestById(questIndex)
				-- _ is questIndex in Questlog
			end
		end

		if qID then
			isRemoved = false

			if beql.db.profile.QuestTracker.RemoveFinished and qStat == 1 then
				isRemoved = true
				completedQuests = completedQuests +1
			end

			--
			-- Zone !
			--
			if beql.db.profile.QuestTracker.ShowZones and (curZone == nil or curZone ~= qZone) and not isRemoved then
				curZone = qZone

				line = beql:QuestTracker_GetLine(lineFrame:GetName());
				line.text:SetText(curZone);
				line.mouseover:SetWidth(line.text:GetStringWidth())
				if ((line.text:GetStringWidth() + 10) > questWatchMaxWidth) then
					questWatchMaxWidth = line.text:GetStringWidth() +10
				end
				line:Show();
				if ( not lastLine ) then -- First line
					line:SetPoint("TOPRIGHT", lineFrame, "TOPRIGHT", 0, 0);
					line:SetPoint("TOPLEFT", lineFrame, "TOPLEFT", 0, 0);
				else
					local yOffset = 0;
					if ( iconHeightLeft > 0 ) then
						yOffset = -iconHeightLeft;
						iconHeightLeft = 0;
					end

					line:SetPoint("TOPRIGHT", lastLine, "BOTTOMRIGHT", 0, yOffset - ZoneSpacing);
					line:SetPoint("TOPLEFT", lastLine, "BOTTOMLEFT", 0, yOffset - ZoneSpacing);
				end

				if beql.db.profile.QuestTracker.CustomZoneColor then
					Color = beql.db.profile.QuestTracker.Colors.Zone
				else
					Color = {r = 0.8,g = 0.8,b = 1}
				end

				line.text:SetTextColor(Color.r, Color.g, Color.b)
				if not(tempwidth == nil) and tempwidth > questWatchMaxWidth then
					questWatchMaxWidth = tempwidth
				end

				maxWidth = max(maxWidth, line.text:GetStringWidth())
				lastLine = line;
			end

			--
			-- Quest !
			--
			if qID > 0 and not isRemoved then
				-- Colores
				if qStat == 1 then
					--Completed
					completedQuests = completedQuests +1
					if beql.db.profile.QuestTracker.CustomHeaderColor then
						if beql.db.profile.QuestTracker.HeaderQuestLevelColor then
							Color = GetQuestDifficultyColor(qLvl)
						else
							Color = beql.db.profile.QuestTracker.Colors.HeaderComplete
						end
					else
						Color = NORMAL_FONT_COLOR
					end
				elseif qStat == -1 then
					-- Failed
					if beql.db.profile.QuestTracker.CustomHeaderColor then
						Color = beql.db.profile.QuestTracker.Colors.HeaderFailed
					else
						Color = NORMAL_FONT_COLOR
					end
				else
					-- Normal
					if beql.db.profile.QuestTracker.CustomHeaderColor then
						if beql.db.profile.QuestTracker.HeaderQuestLevelColor then
							Color = GetQuestDifficultyColor(qLvl)
						else
							Color = beql.db.profile.QuestTracker.Colors.HeaderNormal
						end
					else
						Color = { r = 0.75, g = 0.61, b = 0 }
					end
				end

				qTitle = questLogTitleText;-- Levels

				line = beql:QuestTracker_GetLine(lineFrame:GetName());
				if beql.db.profile.QuestTracker.ShowZones then
					line.dash:SetText("  ")
					-- add space for zone offset
					--qTitle = "  " .. qTitle
				end
				questTitle = line;
				line.isHeader = true;
				line.text:SetText(qTitle);
				line.qID = qID;
				line.text:SetTextColor(Color.r, Color.g, Color.b)
				line:Show();
				if ( not lastLine ) then -- First line
					line:SetPoint("TOPRIGHT", lineFrame, "TOPRIGHT", 0, 0);
					line:SetPoint("TOPLEFT", lineFrame, "TOPLEFT", 0, 0);
				else
					local yOffset = 0;
					if ( iconHeightLeft > 0 ) then
						yOffset = -iconHeightLeft;
					end

					line:SetPoint("TOPRIGHT", lastLine, "BOTTOMRIGHT", 0, yOffset - QuestSpacing);
					line:SetPoint("TOPLEFT", lastLine, "BOTTOMLEFT", 0, yOffset - QuestSpacing);
				end
				iconHeightLeft = 0;
				local stringWidth = line.text:GetStringWidth();
				line.mouseover:SetWidth(line.text:GetStringWidth())

				--
				-- ItemButton
				--
				local item, charges = select(2,GetQuestLogSpecialItemInfo(questIndex));
				local itemButton;
				if ( item ) then
					watchItemIndex = watchItemIndex + 1;
					itemButton = _G["beqlItem"..watchItemIndex];
					if ( not itemButton ) then
						beql.QuestItems = watchItemIndex
						itemButton = CreateFrame("BUTTON", "beqlItem" .. watchItemIndex, lineFrame, "WatchFrameItemButtonTemplate");
					end
					line.hasItem = itemButton;
					itemButton:Show();
					itemButton:ClearAllPoints();
					itemButton:SetID(questIndex);
					SetItemButtonTexture(itemButton, item);
					SetItemButtonCount(itemButton, charges);
					itemButton.charges = charges;
					WatchFrameItem_UpdateCooldown(itemButton);
					itemButton.rangeTimer = -1;
					if ( not WatchFrame.showObjectives ) then
						line.text:SetPoint("RIGHT", itemButton, "LEFT", -4, 0);
					end
					iconHeightLeft = itemButton:GetHeight() - WATCHFRAMELINES_FONTHEIGHT - WATCHFRAMELINES_FONTSPACING; -- We've already displayed a line for this
					if ( WatchFrame.showObjectives ) then
						itemButton.maxStringWidth = stringWidth + (WATCHFRAME_MAP_BUTTON_WIDTH or line.mapButton:GetWidth());
					else
						itemButton.maxStringWidth = stringWidth
					end
				end

				lastLine = line;

				--
				-- Map Button (not active now, but maybe in future)
				--
				if ( WatchFrame.showObjectives ) then
					stringWidth = stringWidth + (WATCHFRAME_MAP_BUTTON_WIDTH or line.mapButton:GetWidth());
					line.mapButton:Show();
					line.mapButton.questID = qID;
					--line.text:ClearAllPoints();
					--line.text:SetPoint("TOPLEFT");
					--line.text:SetPoint("BOTTOM");
					local lineWidth = line:GetWidth();
					if maxtrackerwidth and ( line.text:GetWidth() + 4 + (WATCHFRAME_MAP_BUTTON_WIDTH or line.mapButton:GetWidth()) > maxtrackerwidth ) then -- 25 = button (22) + Buttonofset (3)
						line.text:SetWidth(maxtrackerwidth - (4 + (WATCHFRAME_MAP_BUTTON_WIDTH or line.mapButton:GetWidth())));
					end
				end
				questWidth = max(stringWidth, questWidth);

				--
				-- Objectives
				--

				numObjectives = qObj
				if (beql.db.profile.QuestTracker.MinimizeFinished or beql.db.profile.QuestTracker.HideCompletedOnly) and qStat == 1 then
					-- hide questobjectives on complete quest
					numObjectives = 0;
				end

				markerID = 0


				local _, qObjectives = beqlQ:IterateObjectivesForQuest(qID)
				if  numObjectives > 0 and qObjectives then
					for oText, oItems in pairs(qObjectives) do
						oComp = false;
						oNumP, oNumN, oType = unpack(oItems)
						if oNumN == nil then oNumN = 1 end
						if oNumP == nil then oNumP = 1 end
						if oText == nil then oText = "" end

						if oNumP == oNumN then
							oComp = true
						end

						-- only display complete
						if (oComp and not beql.db.profile.QuestTracker.MinimizeFinished) or (not oComp) then

							-- colores
							if beql.db.profile.QuestTracker.CustomObjetiveColor then
										tempColor = { r=beql.db.profile.QuestTracker.Colors.ObjectiveNormal.r, g=beql.db.profile.QuestTracker.Colors.ObjectiveNormal.g, b=beql.db.profile.QuestTracker.Colors.ObjectiveNormal.b }
										tempColor2 = { r=beql.db.profile.QuestTracker.Colors.ObjectiveComplete.r, g=beql.db.profile.QuestTracker.Colors.ObjectiveComplete.g, b=beql.db.profile.QuestTracker.Colors.ObjectiveComplete.b }
							else
										tempColor = {r=0.8, g=0.8, b=0.8}
										tempColor2 = {r=HIGHLIGHT_FONT_COLOR.r, g=HIGHLIGHT_FONT_COLOR.g, b=HIGHLIGHT_FONT_COLOR.b}
							end
							if oComp then
								Color = tempColor2
							else
								if beql.db.profile.QuestTracker.FadeColor then
									if oType == "reputation" then
										if oNumN == oNumP then
											Color = beql:FadeColors(tempColor, tempColor2, 1,1)
										else
											Color = beql:FadeColors(tempColor, tempColor2, 0,1)
										end
									else
										Color = beql:FadeColors(tempColor, tempColor2, oNumP,oNumN)
									end
								else
									Color = tempColor
								end
							end

							-- markers
							if  beql.db.profile.QuestTracker.ShowObjectiveMarkers  then
								if beql.db.profile.QuestTracker.UseTrackerListing then
									objText = " "..BEQL_TrackerLists[beql.db.profile.QuestTracker.TrackerList][markerID]..") "

								else
									objText = " "..BEQL_TrackerSymbols[beql.db.profile.QuestTracker.TrackerSymbol].." "
								end
							else
								if IsAddOnLoaded("Mobmap") then
									objText = "- "
								else
									objText = "  "
								end
							end


							objText = objText..oText
							if oType == "item" or oType == "monster" or oType == "reputation" or oType == "object"then
								objText = objText ..": "..oNumP.."/"..oNumN
							end

							-- create line
							line = beql:QuestTracker_GetLine(lineFrame:GetName());
							if beql.db.profile.QuestTracker.ShowZones then
								line.dash:SetText("  ")
								-- add space for zone offset
								--objText = "  " .. objText
							end
							line.text:SetText(objText);
							line.qID = qID;
							line.text:SetTextColor(Color.r, Color.g, Color.b)
							line:SetPoint("TOPRIGHT", lastLine, "BOTTOMRIGHT", 0, WATCHFRAMELINES_FONTSPACING);
							line:SetPoint("TOPLEFT", lastLine, "BOTTOMLEFT", 0, WATCHFRAMELINES_FONTSPACING);
							line:Show();
							stringWidth = line.text:GetStringWidth();
							line.mouseover:SetWidth(line.text:GetStringWidth())
							questWidth = max(stringWidth, questWidth);
							if ( iconHeightLeft > 0 ) then
								line.text:SetPoint("RIGHT", itemButton, "LEFT", -4, 0);
								itemButton.maxStringWidth = max(stringWidth, itemButton.maxStringWidth)
							end
							lastLine = line;
							iconHeightLeft = iconHeightLeft - WATCHFRAMELINES_FONTHEIGHT - WATCHFRAMELINES_FONTSPACING;
--							if tempwidth > questWatchMaxWidth then
--								questWatchMaxWidth = tempwidth
--							end
							--beql.db.char.TrackerQuests[(beqlFrameCache.QuestLineIndex - 1)] = qID
							markerID = markerID + 1
						end
						--break -- testhack
					end
				end

				if beql.questtimers[qID] then
					line = beql:QuestTracker_GetLine(lineFrame:GetName());
					line.text:SetText(" ");
					line.qID = qID;
					line.statusBar:Show();
					line.statusBar.text:SetText(SecondsToTime(select(beql.questtimers[qID], GetQuestTimers())));
					--beql:debugprint(tostring(beql.db.global.questtimes[qID]) .. ' - ' .. tostring(select(beql.questtimers[qID], GetQuestTimers())))
					line.statusBar:SetMinMaxValues(0, beql.db.global.questtimes[qID])
					line.statusBar:SetValue(select(beql.questtimers[qID], GetQuestTimers()));
					line:SetPoint("TOPRIGHT", lastLine, "BOTTOMRIGHT", 0, WATCHFRAMELINES_FONTSPACING);
					line:SetPoint("TOPLEFT", lastLine, "BOTTOMLEFT", 0, WATCHFRAMELINES_FONTSPACING);
					line:Show();
					stringWidth = line.text:GetStringWidth();
					line.mouseover:SetWidth(line.text:GetStringWidth())
					questWidth = max(stringWidth, questWidth);
					if ( iconHeightLeft > 0 ) then
						line.text:SetPoint("RIGHT", itemButton, "LEFT", -4, 0);
						itemButton.maxStringWidth = max(stringWidth, itemButton.maxStringWidth)
					end
					lastLine = line;
				end

							-- adjust item button
				local itemButtonXOffset = 8;
				if ( WatchFrame.showObjectives ) then
					questWidth = questWidth + (WATCHFRAME_MAP_BUTTON_WIDTH or line.mapButton:GetWidth());
					itemButtonXOffset = itemButtonXOffset + (WATCHFRAME_MAP_BUTTON_WIDTH or line.mapButton:GetWidth());
				end

				if ( itemButton ) then
					questWidth = questWidth + WATCHFRAME_ITEM_WIDTH + itemButtonXOffset;
					if maxtrackerwidth then
						-- we have a absolute tracker width
						itemButtonXOffset = min(itemButton.maxStringWidth + itemButtonXOffset, maxtrackerwidth - WATCHFRAME_ITEM_WIDTH);
					else
						itemButtonXOffset = itemButton.maxStringWidth + itemButtonXOffset;
					end
					itemButton:SetPoint("TOPLEFT", questTitle, "TOPLEFT", itemButtonXOffset, -WATCHFRAMELINES_FONTSPACING);
					itemButton:Show();
					if ( WatchFrame.showObjectives and (questTitle.text:GetWidth() + (WATCHFRAME_MAP_BUTTON_WIDTH or line.mapButton:GetWidth())) > itemButtonXOffset ) then
						questTitle.text:SetPoint("RIGHT", itemButton, "LEFT", -(WATCHFRAME_MAP_BUTTON_WIDTH or line.mapButton:GetWidth()), 0);
					end
				end
				maxWidth = max(questWidth, maxWidth);

			end
		end

	end

	-- hide unused buttons
	for i = watchItemIndex + 1, beql.QuestItems do
		_G["beqlItem" .. i]:Hide();
	end

	beql:QuestTracker_ReleaseUnusedLines();

	-- Handle Frame Visibility

	if lastLine then
		beqlQuestWatchFrame:Show()
	else
		beqlQuestWatchFrame:Hide()
		return
	end


	-- Set Title Text
	local questnums = GetNumQuestWatches()
	local _,questEntries = GetNumQuestLogEntries()
	if beql.db.profile.QuestTracker.RemoveFinished then
		beqlQuestWatchFrame.TitleFrame.Text:SetText(L["Quest Tracker"].. " ("..questnums - completedQuests.."/"..questEntries..")")
	else
		beqlQuestWatchFrame.TitleFrame.Text:SetText(L["Quest Tracker"].. " ("..questnums.."/"..questEntries..")")
	end

	--Minimize the Tracker if its state is set to minimized
	if beql.db.char.QuestWatchMinimized then
		beql:QuestTracker_TrackerMinimize()
		return 0,0
	end

	-- set Tracker Width
	if not beql.db.profile.QuestTracker.AutoResize then
		beqlQuestWatchFrame:SetWidth(beql.db.profile.QuestTracker.FixedWidth)
	else
		if maxWidth > (beqlQuestWatchFrame.TitleFrame.Text:GetStringWidth()+32) then
			beqlQuestWatchFrame:SetWidth(maxWidth);
		else
			beqlQuestWatchFrame:SetWidth(beqlQuestWatchFrame.TitleFrame.Text:GetStringWidth()+32);
		end
	end

	-- Tracker height
	local height = 0
	local width = beqlQuestWatchFrame.TitleFrame.Text:GetStringWidth() + 32
	local linewidth, heightleft, lineheight = 0 , 0 
	local questwidth = 0
	local nextoffset = 0
	local previousLine
	for k, line in pairs(beqlFrameCache.QuestLines) do
		if previousLine then
			if not line.qID then
				nextoffset = 5
				if heightleft > 0 then
					nextoffset = nextoffset + heightleft
					heightleft = 0
				end
			elseif line.isHeader then
				nextoffset = 3
				if heightleft > 0 then
					nextoffset = nextoffset + heightleft
					heightleft = 0
				end
			else
				nextoffset = 1.5
			end
 			line:SetPoint("TOPRIGHT", previousLine, "BOTTOMRIGHT", 0, -nextoffset);
 			line:SetPoint("TOPLEFT", previousLine, "BOTTOMLEFT", 0, -nextoffset);
		else 
 			line:SetPoint("TOPRIGHT", lineFrame, "TOPRIGHT", 0, 0);
 			line:SetPoint("TOPLEFT", lineFrame, "TOPLEFT", 0, 0);
		end
			
		lineheight = line:GetHeight() + nextoffset;
		height = height + lineheight
		
		linewidth = line.dash:GetWidth() + line.text:GetStringWidth();
		if line.mapButton:IsShown() then
			beql:debugprint(line:GetName() .. " has map button shown")
			linewidth = linewidth + 6 + line.mapButton:GetWidth()
		end
		
		if line.hasItem then
			heightleft = beqlItem1:GetHeight() + 6
		end
		
		if heightleft > 0 then
			beql:debugprint(line:GetName() .. " has item button shown")
			heightleft = heightleft - lineheight
			linewidth = linewidth + beqlItem1:GetWidth() + 6
		end
		
		if line.isHeader then
			width = max(width, questwidth)
			questwidth = linewidth
			if heightleft > 0 then
				height = height + heightleft
			end
		else
			questwidth = max(questwidth,linewidth)
		end
		
		-- last line
		if k == #beqlFrameCache.QuestLines then
			width = max(width, questwidth)
			if heightleft > 0 then
				height = height + heightleft
			end
		end
		previousLine = line
	end
	
	beql:debugprint("o: " .. maxWidth .. " - n: " .. width)
	
	beqlQuestWatchFrame:SetHeight(height)
	beqlQuestWatchFrame:SetWidth(width)

	-- last item is an icon, expand size to it
	if ( iconHeightLeft > 0 ) then
		beqlQuestWatchFrame:SetHeight(beqlQuestWatchFrame:GetHeight() + iconHeightLeft + 2)
		--yOffset = -iconHeightLeft;
	end


	-- we use a own Frame, so we return a used hight of zero
	return 0, maxWidth;
end

function beql:QuestTracker_GetLine (frameparent)
	if not FontHeight or not FontSpacing or not QuestSpacing or not ZoneSpacing then
		FontHeight = beql.db.profile.QuestTracker.FontHeight
		FontSpacing = FontHeight / 6
		QuestSpacing = (FontHeight + FontSpacing) / 4
		ZoneSpacing = FontHeight/2.4
	end




	local line = beqlFrameCache.QuestLines[beqlFrameCache.QuestLineIndex];
	if ( not line ) then
		beqlFrameCache.QuestLines[beqlFrameCache.QuestLineIndex] = beqlFrameCache.Lines:GetFrame();
		line = beqlFrameCache.QuestLines[beqlFrameCache.QuestLineIndex];
	end

	line:Reset();
	line:SetParent(frameparent);
	line.type = 'q'

	local t1,_ , t2 = line.text:GetFont()
	line.text:SetFont(t1, FontHeight, t1)
	line:SetHeight(FontHeight + FontSpacing)

	beqlFrameCache.QuestLineIndex = beqlFrameCache.QuestLineIndex + 1;
	return line;
end

function beql:QuestTracker_StatusBar_OnUpdate(elapsed)
	if not self.statusBar:IsShown() then
		-- stausbar not shown, exit
		return;
	end
	
	self.time = (self.time or 0) + elapsed
	if self.time < 0.1 then
		-- only update every 0.1 seconds
		return;
	end
	
	if not beql.questtimers[self.qID] then
		self:Hide();
		-- ToDo: Update WatchFrame
		return;
	end
	
	local questtimeleft = select(beql.questtimers[self.qID], GetQuestTimers());
	
	if not questtimeleft or type(questtimeleft) ~= 'number' then
		self:Hide();
		
		return;
	end
	
	self.statusBar.text:SetText(SecondsToTime(questtimeleft));
	self.statusBar:SetValue(questtimeleft);
	self.time = 0
end
-- EOF --

function beql:QuestTracker_ReleaseUnusedLines ()
	local line
	for i = beqlFrameCache.QuestLineIndex, #beqlFrameCache.QuestLines do
		line = beqlFrameCache.QuestLines[i];
		line:Hide();
		line.frameCache:ReleaseFrame(line);
		beqlFrameCache.QuestLines[i] = nil;
	end

	beqlFrameCache.QuestLineIndex = 1;
end

-- EOF --