--[[

 "FastQuest Classic" is a free software; you can redistribute it and/or modify it under the terms of the
 GNU General Public License as published by the Free Software Foundation; either version 2 of the License,
 or (at your option) any later version.

--]]

FASTQUEST_CLASSIC_VERSION = GetAddOnMetadata("FastQuest_Classic", "Version");

hQuestLog_Update = QuestLog_Update;
hQuestWatch_Update = QuestWatch_Update;

FQ_player = UnitName("player");
FQ_server = GetCVar("realmName");
if (FQ_player == nil or FQ_player == UNKNOWNBEING or FQ_player == UKNOWNBEING or FQ_player == UNKNOWNOBJECT) then
	FQ_player = "DEFAULT";
end

-- Number of the format styles
FQ_nFormats = 4;

-- Default chat channel
FQ_CHATTYPE = "SAY";

local DefaultFQDOptions = {
	["FastQuest_Classic_Version"] = FASTQUEST_CLASSIC_VERSION,
	["AutoNotify"] 		= false,
	["NotifyParty"]		= true,
	["NotifyRaid"] 		= false,
	["NotifyGuild"] 	= false,
	["NotifyNearby"] 	= false,
	["AutoAdd"] 		= true,
	["AutoComplete"] 	= false,
	["Color"] 			= true,
	["Detail"] 			= true,
	["Format"] 			= 4,
	["Lock"] 			= true,
	["MemberInfo"] 		= true,
	["NoDrag"] 			= false,
	["NotifyDiscover"] 	= true,
	["NotifyExp"] 		= true,
	["NotifyLevelUp"]	= true,
	["Tag"] 			= true,
};

function FastQuest_FreshOptions()
	FQD = FQ_CloneTable(DefaultFQDOptions);
end

--Code by Grayhoof (SCT)
function FQ_CloneTable(t)			-- return a copy of the table t
	local new = {};					-- create a new table
	local i, v = next(t, nil);		-- i is an index of t, v = t[i]
	while i do
		if type(v) == "table" then
			v = FQ_CloneTable(v);
		end
		new[i] = v;
		i, v = next(t, i);			-- get next index
	end
	return new;
end

function FastQuest_OnLoad()
-- Register for events
	this:RegisterEvent("ADDON_LOADED");
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("UI_INFO_MESSAGE");
	this:RegisterEvent("QUEST_PROGRESS");
	this:RegisterEvent("QUEST_COMPLETE");
	this:RegisterEvent("CHAT_MSG_SYSTEM");
	this:RegisterEvent("ADDON_LOADED");
	this:RegisterEvent("PLAYER_LEVEL_UP");

	SLASH_FQ1 = "/fastquest";
	SLASH_FQ2 = "/fq";
	SlashCmdList["FQ"] = FastQuest_SlashCmd;
end


function FastQuest_OnEvent(event, message)
	if	((event == "QUEST_PROGRESS") and (FQD.AutoComplete == true)) then
		CompleteQuest();
	elseif	((event == "QUEST_COMPLETE") and (FQD.AutoComplete == true)) then
		if (GetNumQuestChoices() == 0) then
			GetQuestReward(QuestFrameRewardPanel.itemChoice);
		end
	elseif(event == "VARIABLES_LOADED") then
		-- initialize all the default options parameters
		if (FQD == nil or FQD["FastQuest_Classic_Version"] ~= FASTQUEST_CLASSIC_VERSION) then
			FastQuest_FreshOptions();
		end

		UpdatePlayer();
		FastQuestOptions_Init();
		qOut(FQ_LOADED);

		FastQuest_LinkFrame(dQuestWatchDragButton:GetName(), QuestWatchFrame:GetName(), "RIGHT");
		FastQuest_LockMovableParts();

	elseif (event == "UI_INFO_MESSAGE" and message) then
		-- Here the quest progress like you have picked up 2/20 xxx items will be detected.
		local uQuestText = gsub(message, FQ_QUEST_TEXT, "%1", 1);
		if ( uQuestText ~= message) then
			-- Only when Auto Notify is set to true and Detail also set to true, then FQ will do the notification
			if (FQD.AutoNotify == true and FQD.Detail == true) then
--				if(GetNumPartyMembers() > 0 or FQD.NotifyNearby == true) then
--					FastQuest_CheckDefaultChat(false);
--					SendChatMessage(FQ_QUEST_PROGRESS..message, FQ_CHATTYPE);
--				end
				FastQuest_SendNotification(FQ_QUEST_PROGRESS..message);
			end
			if (FQD.AutoAdd == true and GetNumQuestWatches() < MAX_WATCHABLE_QUESTS) then
				local qID = FastQuest_GetQuestID(uQuestText);
				if (qID) then
					if (not IsQuestWatched(qID)) then
						FastQuest_Watch(qID, true);
					end
				end
			end
		else
			FastQuest_CheckPatterns(message);
		end
	elseif (event == "CHAT_MSG_SYSTEM" and message) then
		FastQuest_CheckPatterns(message);
	-- When player is level up, notify the party member
	elseif (event == "PLAYER_LEVEL_UP") then
		if ((FQD.AutoNotify == true) and (FQD.NotifyLevelUp == true)) then
--			if(GetNumPartyMembers()>0 or FQD.NotifyNearby == true) then
--				FastQuest_CheckDefaultChat(false);
--				SendChatMessage(PLAYER_LEVEL_UP, FQ_CHATTYPE);
--			end
			FastQuest_SendNotification(PLAYER_LEVEL_UP);
		end
	end
end

function FastQuest_SlashCmd(msg)
	if (msg) then
		local cmd = gsub(msg, "%s*([^%s]+).*", "%1");
		local info = FQ_INFO;
		-- Display the quest type like Elite, Dungeon, PvP, etc., info in the QuestTracker window
		if( cmd == "tag" ) then FastQuest_Toggle_Tag(); return;
		-- Auto Add, automatically add the quest items / progress into QuestTracker window
		elseif( cmd == "autoadd" ) then FastQuest_Toggle_AutoAdd(); return;
		-- Auto Notify the party members regarding to your quest progress
		elseif( cmd == "autonotify" ) then 	FastQuest_Toggle_AutoNotify(); 	return;
		-- Auto Complete, automatically hands out the quest
		elseif( cmd == "autocomplete" ) then FastQuest_Toggle_AutoComplete(); return;
		-- Allow to notify the guild members regarding to your quest progress
		elseif( cmd == "notifyguild" ) then FastQuest_Toggle_NotifyGuild(); return;
		-- Allow to notify the party members regarding to your quest progress
		elseif( cmd == "notifyparty" ) then FastQuest_Toggle_NotifyParty(); return;
		-- Allow to notify the raid members regarding to your quest progress
		elseif( cmd == "notifyraid" ) then FastQuest_Toggle_NotifyRaid(); return;
		-- Always notify your quest progress even you are not in any party
		elseif( cmd == "notifynearby" ) then FastQuest_Toggle_NotifyNearby(); return;
		-- Allow to notify your detail quest progress
		elseif( cmd == "detail" ) then FastQuest_Toggle_NotifyDetails(); return;
		-- Lock the QuestTracker window
		elseif( cmd == "lock" and FQD.NoDrag == false) then FastQuest_Toggle_Lock(); return;
		-- Unlock the QuestTracker
 		elseif( cmd == "unlock" and FQD.NoDrag == false) then FastQuest_Toggle_Unlock(); return;
		elseif( cmd == "nodrag" ) then FastQuest_Toggle_Nodrag(); return;
		-- Reset the QuestTracker window's position to default
		elseif( cmd == "reset" and FQD.NoDrag == false) then FastQuest_Toggle_Reset(); return;
		elseif( cmd == "format" )then FastQuest_Toggle_Format(); return;
		elseif( cmd == "clear" ) then FastQuest_Toggle_Clear(); return;
		elseif( cmd == "color" ) then FastQuest_Toggle_Color(); return;
		elseif( cmd == "memberinfo" ) then FastQuest_Toggle_MemberInfo(); return;
		elseif( cmd == "notifyexp" ) then FastQuest_Toggle_NotifyExp(); return;
		elseif( cmd == "notifydiscover" ) then FastQuest_Toggle_NotifyDiscover(); return;
		elseif( cmd == "notifylevelup" ) then FastQuest_Toggle_NotifyLevelUp(); return;
		elseif( cmd == "options" ) then FastQuestOptions_Init(); FastQuestOptions_Toggle(); return;
		elseif( cmd == "status" ) then
			qOut("|cfffffffffq autonotify     - "..FastQuest_ShowBoolean(FQD.AutoNotify));
			qOut("|cfffffffffq notifyguild    - "..FastQuest_ShowBoolean(FQD.NotifyGuild));
			qOut("|cfffffffffq notifyraid     - "..FastQuest_ShowBoolean(FQD.NotifyRaid));
			qOut("|cfffffffffq notifynearby   - "..FastQuest_ShowBoolean(FQD.NotifyNearby));
			qOut("|cfffffffffq autoadd        - "..FastQuest_ShowBoolean(FQD.AutoAdd));
			qOut("|cfffffffffq autocomplete   - "..FastQuest_ShowBoolean(FQD.AutoComplete));
			qOut("|cfffffffffq color          - "..FastQuest_ShowBoolean(FQD.Color));
			qOut("|cfffffffffq detail         - "..FastQuest_ShowBoolean(FQD.Detail));
			qOut("|cfffffffffq lock(unlock)   - "..FastQuest_ShowLock(FQD.Lock));
			qOut("|cfffffffffq memberinfo     - "..FastQuest_ShowBoolean(FQD.MemberInfo));
			qOut("|cfffffffffq nodrag         - "..FastQuest_ShowBoolean(FQD.NoDrag));
			qOut("|cfffffffffq notifyexp      - "..FastQuest_ShowBoolean(FQD.NotifyExp));
			qOut("|cfffffffffq notifydiscover - "..FastQuest_ShowBoolean(FQD.NotifyDiscover));
			qOut("|cfffffffffq notifylevelup  - "..FastQuest_ShowBoolean(FQD.NotifyLevelUp));
			qOut("|cfffffffffq tag            - "..FastQuest_ShowBoolean(FQD.Tag));
			return;
		else
			qOut(info..FQ_INFO_USAGE);
			qOut("|cffffffff/fq autonotify     - "..FQ_USAGE_AUTONOTIFY);
			qOut("|cffffffff/fq notifyguild    - "..FQ_USAGE_NOTIFYGUILD);
			qOut("|cffffffff/fq notifyraid     - "..FQ_USAGE_NOTIFYRAID);
			qOut("|cffffffff/fq notifynearby   - "..FQ_USAGE_NOTIFYNEARBY);
			qOut("|cffffffff/fq autoadd        - "..FQ_USAGE_AUTOADD);
			qOut("|cffffffff/fq autocomplete   - "..FQ_USAGE_AUTOCOMPLETE);
			qOut("|cffffffff/fq clear          - "..FQ_USAGE_CLEAR);
			qOut("|cffffffff/fq color          - "..FQ_USAGE_COLOR);
			qOut("|cffffffff/fq detail         - "..FQ_USAGE_DETAIL);
			qOut("|cffffffff/fq format         - "..FQ_USAGE_FORMAT);
			qOut("|cffffffff/fq lock(unlock)   - "..FQ_USAGE_LOCK);
			qOut("|cffffffff/fq memberinfo     - "..FQ_USAGE_MEMBERINFO);
			qOut("|cffffffff/fq nodrag         - "..FQ_USAGE_NODRAG);
			qOut("|cffffffff/fq notifyexp      - "..FQ_USAGE_NOTIFYEXP);
			qOut("|cffffffff/fq notifydiscover - "..FQ_USAGE_NOTIFYDISCOVER);
			qOut("|cffffffff/fq options        - "..FQ_USAGE_OPTIONS);
			qOut("|cffffffff/fq reset          - "..FQ_USAGE_RESET);
			qOut("|cffffffff/fq status         - "..FQ_USAGE_STATUS);
			qOut("|cffffffff/fq tag            - "..FQ_USAGE_TAG);
			return;
		end
	end
end

function FastQuest_CheckPatterns(message)
--	if (FQD.Detail == false) then
--		return;
--	end
	-- 2006/08/21: If AutoNotify is set to false, then the party members should not be notified.
	if (FQD.AutoNotify == false) then
		return;
	end
	if (GetNumPartyMembers() == 0 and FQD.NotifyNearby == false) then
		return;
	end
	for index, value in pairs(EPA_TestPatterns) do
		if ( string.find(message, value) ) then
			FastQuest_CheckDefaultChat(false);
			-- if the message type is experience gained, and user set not to notify
			if (value == EPA_TestPatterns[5] and FQD.NotifyExp == false) then
				break;
			-- if the message type is zone discovered, and user set not to notify
			elseif (value == EPA_TestPatterns[6] and FQD.NotifyDiscover == false) then
				break;
			else
				FastQuest_SendNotification(message);
				--SendChatMessage(message, FQ_CHATTYPE);
			end
			break;
		end
	end
end

function QuestLogTitleButton_OnClick(button)
	local qIndex = this:GetID() + FauxScrollFrame_GetOffset(QuestLogListScrollFrame);
	local qTitle, qLevel, qTag, suggestedGroup, isHeader, isCollapsed, isComplete = GetQuestLogTitle(qIndex);
	local LevelTag = "";
	if (suggestedGroup == 0) then 
		suggestedGroup = ""; 
	else
		suggestedGroup = "("..suggestedGroup..")";
	end
	if ( isHeader ) then
		if ( isCollapsed ) then
			ExpandQuestHeader(qIndex);
		else
			CollapseQuestHeader(qIndex);
		end
		return;
	end

	if (qTag) then
		if (qTag == LFG_TYPE_DUNGEON ) then
			LevelTag = "d";
		elseif (qTag == RAID ) then
			LevelTag = "r";
		elseif (qTag == PVP ) then
			Leveltag = "p";
		else
			LevelTag = "+";
		end
	end

	if ( button == "LeftButton" ) then
		QuestLog_SetSelection(qIndex);
		if ( IsShiftKeyDown() and ChatFrameEditBox:IsVisible() ) then
			if (FQD.Format == 2) then
				ChatFrameEditBox:Insert("["..qLevel.."] "..qTitle.." ");
			elseif (FQD.Format == 1) then
				ChatFrameEditBox:Insert(" "..qTitle.." ");
			elseif (FQD.Format == 3) then
				ChatFrameEditBox:Insert("["..qLevel..LevelTag.."] "..qTitle..suggestedGroup);
			elseif (FQD.Format == 4) then
				if (qTag) then qTag = (" ("..qTag..")  ") else qTag = "";end
				ChatFrameEditBox:Insert("["..qLevel..LevelTag.."] "..qTitle..suggestedGroup..qTag);
			else	FQD.Format = 2;	end
		elseif ( IsShiftKeyDown() ) then
			FastQuest_Watch(qIndex,false);
		--elseif (IsControlKeyDown() and ChatFrameEditBox:IsVisible()) then
		elseif IsControlKeyDown() then
			--FastQuest_CheckDefaultChat(true);
			if (FQD.Format == 2) then
				SendChatMessage("["..qLevel.."] "..qTitle, FQ_CHATTYPE);
				--ChatFrameEditBox:Insert("["..qLevel.."] "..qTitle);
			elseif (FQD.Format == 1) then
				SendChatMessage(" "..qTitle.." ", FQ_CHATTYPE);
				--ChatFrameEditBox:Insert(" "..qTitle.." ");
			elseif (FQD.Format == 3) then
				SendChatMessage("["..qLevel..LevelTag.."] "..qTitle, FQ_CHATTYPE);
				--ChatFrameEditBox:Insert("["..qLevel..LevelTag.."] "..qTitle..suggestedGroup);
			elseif (FQD.Format == 4) then
				if (qTag) then qTag = (" ("..qTag..")  ") else qTag="";end
					SendChatMessage("["..qLevel..LevelTag.."] "..qTitle..qTag, FQ_CHATTYPE);
					--ChatFrameEditBox:Insert("["..qLevel..LevelTag.."] "..qTitle..suggestedGroup..qTag);
			else	FQD.Format = 2;	end
			local nObjectives = GetNumQuestLeaderBoards(qIndex);
			if ( nObjectives > 0 ) then
				for i=1, nObjectives do
					oText, oType, oDone = GetQuestLogLeaderBoard(i, qIndex);
					if ( not oText or strlen(oText) == 0 or oText == "" ) then oText = oType;end
					if ( oDone ) then
						SendChatMessage("  X "..oText, FQ_CHATTYPE);
						--ChatFrameEditBox:Insert("  X "..oText);
					else
						SendChatMessage("  -  "..oText, FQ_CHATTYPE);
						--ChatFrameEditBox:Insert("  -  "..oText);
					end
				end
			end
		end
		QuestLog_Update();
	elseif ( button == "RightButton" ) then
		--if ( IsControlKeyDown() and ChatFrameEditBox:IsVisible()) then
		if IsControlKeyDown() then
			QuestLog_SetSelection(qIndex);
			local qDescription, qObjectives = GetQuestLogQuestText();
			local n_qObjectives = string.gsub(qObjectives, "\n", "");
			FastQuest_CheckDefaultChat(true);
			if (qObjectives) then
				if (FQD.Format == 2) then
					SendChatMessage("["..qLevel.."] "..qTitle..": "..n_qObjectives, FQ_CHATTYPE);
					--ChatFrameEditBox:Insert("["..qLevel.."] "..qTitle..": "..n_qObjectives);
				elseif (FQD.Format == 1) then
					SendChatMessage(" "..qTitle.." "..": "..n_qObjectives, FQ_CHATTYPE);
					--ChatFrameEditBox:Insert(" "..qTitle.." "..": "..n_qObjectives);
				elseif (FQD.Format == 3) then
					SendChatMessage("["..qLevel..LevelTag.."] "..qTitle..": "..n_qObjectives, FQ_CHATTYPE);
					--ChatFrameEditBox:Insert("["..qLevel..LevelTag.."] "..qTitle..suggestedGroup..": "..n_qObjectives);
				elseif (FQD.Format == 4) then
					if (qTag) then qTag = (" ("..qTag..")  ") else qTag="";end
					SendChatMessage("["..qLevel..LevelTag.."] "..qTitle..qTag..": "..n_qObjectives, FQ_CHATTYPE);
					--ChatFrameEditBox:Insert("["..qLevel..LevelTag.."] "..qTitle..suggestedGroup..qTag..": "..n_qObjectives);
				else	FQD.Format = 2;	end
			end
			return;
		end
		FastQuest_Watch(qIndex,false);
	end
end

function QuestLog_Update()
	if (FQ_player == "DEFAULT" or FQD[FQ_server][FQ_player].tQuests == nil) then UpdatePlayer();end;
	FastQuest_LockMovableParts();
	local nEntries, nQuests = GetNumQuestLogEntries();
	if (GetNumQuestWatches() < 1 and FQD[FQ_server][FQ_player].nQuests > 0) then
		for i=1, nEntries do
			SelectQuestLogEntry(i);
 			local qTitle, qLevel, qTag, suggestedGroup, isHeader, isCollapsed = GetQuestLogTitle(i + FauxScrollFrame_GetOffset(QuestLogListScrollFrame));
			for j = 1, FQD[FQ_server][FQ_player].nQuests do
				if (qTitle == FQD[FQ_server][FQ_player].tQuests[j] and (not IsQuestWatched(i))) then
					AddQuestWatch(i);
				end
			end
		end
	end
	hQuestLog_Update();
	for i=1, QUESTS_DISPLAYED, 1 do
		if ( i <= nEntries ) then
			local qTitle, qLevel, qTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily = GetQuestLogTitle(i + FauxScrollFrame_GetOffset(QuestLogListScrollFrame));
			local qLogTitle = getglobal("QuestLogTitle"..i);
			local qCheck = getglobal("QuestLogTitle"..i.."Check");
			qCheck:SetPoint("LEFT", qLogTitle:GetName(), "LEFT", 0, 0);
			FastQuest_ChangeTitle(qLogTitle, qTitle, qLevel, qTag, suggestedGroup, isHeader, isDaily, false);
			if (FQD.Color == true) then
				local cQuestLevel = FQ_GetDifficultyColor(qLevel);
				local questTitleTag = getglobal("QuestLogTitle"..i.."Tag");
				questTitleTag:SetTextColor(cQuestLevel.r, cQuestLevel.g, cQuestLevel.b);
			end
		end
	end
end

function FastQuest_ChangeTitle(qLogTitle, qTitle, qLevel, qTag, suggestedGroup, isHeader, isDaily, Watch)
	local ColorTag = "";
	local DifTag = "";
	local LevelTag = "";
	local cQuestLevel = FQ_GetDifficultyColor(qLevel);
	if (qTitle and not isHeader) then
		if (FQD.Color == true) then
			ColorTag = string.format("|cff%02x%02x%02x", cQuestLevel.r * 255, cQuestLevel.g * 255, cQuestLevel.b * 255);
		else
			ColorTag = "";
		end
		if (FQD.Tag == true) then
			if (qTag ~= nil) then
				if (isDaily) then
					qTag = format(DAILY_QUEST_TAG_TEMPLATE, qTag);
				end
				DifTag = (" ("..qTag..") ");

				if (qTag == LFG_TYPE_DUNGEON ) then
					LevelTag = "d";
				elseif (qTag == RAID ) then
					LevelTag = "r";
				elseif (qTag == PVP ) then
					LevelTag = "p";
				else
					LevelTag = "+";
				end

			elseif (isDaily) then
				DifTag = (" ("..DAILY..") ");
			end
		end

		if (Watch) then
			qLogTitle:SetText(ColorTag.."["..qLevel..LevelTag.."] "..qTitle..DifTag);
		else
			if (suggestedGroup > 0 and FQD.MemberInfo == true) then
				qLogTitle:SetText(ColorTag.." ["..qLevel..LevelTag.."] "..qTitle.."  ("..suggestedGroup..")  ");
			else
				qLogTitle:SetText(ColorTag.." ["..qLevel..LevelTag.."] "..qTitle.."  ");
			end
		end
	end
end

function FastQuest_LinkFrame(dButton, pFrame)
	if (FQD.NoDrag == false) then
		getglobal(pFrame):ClearAllPoints();
		getglobal(pFrame):SetPoint("TOPLEFT", dButton, "TOPRIGHT");
	else
		qOut(FQ_DRAG_DISABLED);
		FQD.Lock = true;
	end
end

function FastQuest_DragFrame(pFrame, mode)
	if (FQD.NoDrag == false) then
		if (mode == 0) then
			pFrame:StartMoving();
		else
			pFrame:StopMovingOrSizing();
		end
	end
end

function qOut (msg)
	if( DEFAULT_CHAT_FRAME and msg) then
		DEFAULT_CHAT_FRAME:AddMessage(msg);
	end
end

function FastQuest_LockMovableParts()
	if ((FQD[FQ_server][FQ_player].nQuests > 0) and QuestWatchFrame:IsVisible() and (FQD.Lock == false) and (FQD.NoDrag == false)) then
		dQuestWatchDragButton:Show();
	else
		dQuestWatchDragButton:Hide();
	end;
end

function UpdatePlayer()
	if ( FQD[FQ_server] == nil ) then
		FQD[FQ_server] = {};
	end
	--if ( FQD[FQ_server][FQ_player] == nil or FQD[FQ_server][FQ_player].tQuests == nil ) then
	if ( FQD[FQ_server][FQ_player] == nil) then
		FQD[FQ_server][FQ_player] = {
			["nQuests"] = 0;
			["tQuests"] = { };
		};
		for i=1, MAX_WATCHABLE_QUESTS, 1 do
			FQD[FQ_server][FQ_player].tQuests[i] = " ";
		end;
	end
end

function FQ_GetDifficultyColor(level)
	local lDiff = level - UnitLevel("player");
	if (lDiff >= 0) then
		for i= 1.00, 0.10, -0.10 do
			color = {r = 1.00, g = i, b = 0.00};
			if ((i/0.10)==(10-lDiff)) then return color; end
		end
	elseif ( -lDiff < GetQuestGreenRange() ) then
		for i= 0.90, 0.10, -0.10 do
			color = {r = i, g = 1.00, b = 0.00};
			if ((9-i/0.10)==(-1*lDiff)) then return color; end
		end
	elseif ( -lDiff == GetQuestGreenRange() ) then
		color = {r = 0.50, g = 1.00, b = 0.50};
	else
		color = {r = 0.75, g = 0.75, b = 0.75};
	end
	return color;
end

function QuestWatch_Update()
	hQuestWatch_Update();
	local qDone; wID=1; oID=1; DoneID = -1;

--	FQD[FQ_server][FQ_player].nQuests = GetNumQuestWatches();
	for i = 1, GetNumQuestWatches() do
		FQD[FQ_server][FQ_player].tQuests[i] = " ";
		local qID = GetQuestIndexForWatch(i);
		if (qID) then
			local qTitle, qLevel, qTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily = GetQuestLogTitle(qID);
			FQD[FQ_server][FQ_player].tQuests[i]= qTitle;
			qLogTitle = getglobal( "QuestWatchLine"..wID);
			FastQuest_ChangeTitle(qLogTitle, qTitle, qLevel, qTag, suggestedGroup, isHeader, isDaily, true);
			qDone = true; oID = 1;
			for j = 1, GetNumQuestLeaderBoards(qID) do
				oID = j;
				qLogTitle = getglobal( "QuestWatchLine" ..(wID+j));
				local oTitle, oType, oDone = GetQuestLogLeaderBoard(j,qID);
				if (oDone) then
					qLogTitle:SetText("|cFFC0FFCF   X "..oTitle.." ");
				else
					qLogTitle:SetText("|cFFFFFFFF   - "..oTitle.." ");
					qDone = false;
				end
			end
			wID= wID+oID+1;
			if (qDone) then DoneID = qID;end
		end
	end
	if (DoneID>0) then
		PlaySoundFile("sound/interface/igplayerBind.wav");
		UIErrorsFrame:AddMessage("|cff00ffff"..GetQuestLogTitle(DoneID)..FQ_QUEST_COMPLETED, 1.0, 1.0, 1.0, 1.0, 2);
		if (FQD.AutoNotify == true) then
--			if(GetNumPartyMembers()>0 or FQD.NotifyNearby==true) then
--				FastQuest_CheckDefaultChat(false);
--				SendChatMessage(FQ_QUEST.." ["..GetQuestLogTitle(DoneID).."] "..FQ_QUEST_ISDONE,  FQ_CHATTYPE)
--			end
			FastQuest_SendNotification(FQ_QUEST.." ["..GetQuestLogTitle(DoneID).."] "..FQ_QUEST_ISDONE);
		end
		RemoveQuestWatch(DoneID);
		QuestWatch_Update();
	end
	FQD[FQ_server][FQ_player].nQuests = GetNumQuestWatches();
	FastQuest_LockMovableParts();
end

function FastQuest_Watch(qID, auto)
	if (qID) then
		if ((IsQuestWatched(qID)) and (auto == false)) then
			RemoveQuestWatch(qID);
			QuestWatch_Update();
			QuestLog_Update();
		else
			if ((GetNumQuestLeaderBoards(qID) == 0) and (auto == false)) then
				UIErrorsFrame:AddMessage(QUEST_WATCH_NO_OBJECTIVES, 1.0, 0.1, 0.1, 1.0, UIERRORS_HOLD_TIME);
				return;
			end
			if (GetNumQuestWatches() >= MAX_WATCHABLE_QUESTS ) then
				UIErrorsFrame:AddMessage(format(QUEST_WATCH_TOO_MANY, MAX_WATCHABLE_QUESTS), 1.0, 0.1, 0.1, 1.0, UIERRORS_HOLD_TIME);
				return;
			end
			AddQuestWatch(qID);
			QuestWatch_Update();
 			QuestLog_Update();
		end
	end
end

function FastQuest_GetQuestID(str)
	local qSelected = GetQuestLogSelection();
	for i=1, GetNumQuestLogEntries(), 1 do
		SelectQuestLogEntry(i);
		local qTitle, qLevel, qTag, suggestedGroup, isHeader, isCollapsed, isComplete = GetQuestLogTitle(i);
		if (qTitle == str ) then return i; end
		if(not isHeader) then
			for j = 1, GetNumQuestLeaderBoards() do
				local oText, oType, oDone = GetQuestLogLeaderBoard(j);
				if ((oText==nil) or (oText=="")) then
					oText = oType;
				end
				if (string.find(gsub(oText,"(.*): %d+/%d+","%1",1),gsub(str,"(.*): %d+/%d+","%1",1))) then
					SelectQuestLogEntry(qSelected);
					return i;
				end
			end
			local qDescription, qObjectives = GetQuestLogQuestText();
			if(string.find(qObjectives, str)) then
				SelectQuestLogEntry(qSelected);
				return i;
			end
		end
	end
	SelectQuestLogEntry(qSelected);
	return nil;
end

function FastQuest_CheckDefaultChat(NotifyGuild)
	if (GetNumPartyMembers() == 0) then
		FQ_CHATTYPE = "SAY";
	else
		if (FQD.NotifyGuild == true) then
			FQ_CHATTYPE = "GUILD";
		elseif (FQD.NotifyRaid == true and GetNumRaidMembers()>0) then
			FQ_CHATTYPE = "RAID";
		else
			FQ_CHATTYPE = "PARTY";
		end
	end
end

-- This function will deal with all the condition to notify quest event
function FastQuest_SendNotification(message)
	-- If NotifyNearby is set to true, then quest event will be send via "SAY" channel
	if (FQD.NotifyNearby == true) then
		SendChatMessage(message, "SAY");
	end
	if (FQD.NotifyParty == true and GetNumPartyMembers() > 0) then
		SendChatMessage(message, "PARTY");
	end
	if (FQD.NotifyRaid == true and GetNumRaidMembers() > 0) then
		SendChatMessage(message, "RAID");
	end
	if (FQD.NotifyGuild == true and IsInGuild() == true) then
		SendChatMessage(message, "GUILD");
	end
end

function FastQuest_ToggleBoolean ( bool, msg )
	if( bool == false ) then
		qOut(msg..FQ_ENABLED);
		bool = true;
	else
		qOut(msg..FQ_DISABLED);
		bool = false;
	end
	return bool;
end

function FastQuest_ShowBoolean ( bool )
	if( bool == true ) then
		return FQ_ENABLED;
	else
		return FQ_DISABLED;
	end
end

function FastQuest_ShowLock ( bool )
	if( bool == true ) then
		return FQ_LOCK;
	else
		return FQ_UNLOCK;
	end
end

function FastQuest_Toggle_NotifyParty()
	info = FQ_INFO..FQ_INFO_NOTIFYPARTY;
	FQD.NotifyParty = FastQuest_ToggleBoolean(FQD.NotifyParty,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_NotifyGuild()
	info = FQ_INFO..FQ_INFO_NOTIFYGUILD;
	FQD.NotifyGuild = FastQuest_ToggleBoolean(FQD.NotifyGuild,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_NotifyRaid()
	info = FQ_INFO..FQ_INFO_NOTIFYRAID;
	FQD.NotifyRaid = FastQuest_ToggleBoolean(FQD.NotifyRaid,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_NotifyNearby()
	info = FQ_INFO..FQ_INFO_NOTIFYNEARBY;
	FQD.NotifyNearby = FastQuest_ToggleBoolean(FQD.NotifyNearby,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_AutoAdd()
	info = FQ_INFO..FQ_INFO_AUTOADD;
	FQD.AutoAdd = FastQuest_ToggleBoolean(FQD.AutoAdd,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_AutoComplete()
	info = FQ_INFO..FQ_INFO_AUTOCOMPLETE;
	FQD.AutoComplete = FastQuest_ToggleBoolean(FQD.AutoComplete,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_AutoNotify()
	info = FQ_INFO..FQ_INFO_AUTONOTIFY;
	FQD.AutoNotify = FastQuest_ToggleBoolean(FQD.AutoNotify,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_Clear()
	for i = GetNumQuestWatches(), 1 , -1 do
		local qID = GetQuestIndexForWatch(i)
		FQD[FQ_server][FQ_player].tQuests[i] = " ";
		RemoveQuestWatch(qID);
	end
	FQD[FQ_server][FQ_player].nQuests = 0;
	QuestWatch_Update();
	qOut(FQ_INFO..FQ_INFO_CLEAR);
end

function FastQuest_Toggle_Color()
	info = FQ_INFO..FQ_INFO_COLOR;
	FQD.Color = FastQuest_ToggleBoolean(FQD.Color,info);
	QuestLog_Update();
	QuestWatch_Update();
	FastQuestOptions_Init();
end

function FastQuest_Toggle_NotifyDetails()
	info = FQ_INFO..FQ_INFO_DETAIL;
	FQD.Detail = FastQuest_ToggleBoolean(FQD.Detail,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_Lock()
	qOut(FQ_INFO..FQ_INFO_LOCK);
	FQD.Lock = true;
	FastQuest_LockMovableParts();
	FastQuestOptions_Init();
end

function FastQuest_Toggle_Unlock()
	qOut(FQ_INFO..FQ_INFO_UNLOCK);
	FQD.Lock = false;
	FastQuest_LockMovableParts();
	FastQuestOptions_Init();
end

function FastQuest_Toggle_Nodrag()
	info = FQ_INFO..FQ_INFO_NODRAG;
	FQD.NoDrag = FastQuest_ToggleBoolean(FQD.NoDrag,info);
	if (FQD.NoDrag == false ) then FQD.Lock = true; end
	qOut(FQ_MUST_RELOAD);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_Reset()
	FastQuestFrame:SetPoint("TOPLEFT", "Minimap", "TOPLEFT", -20, -15);
	dQuestWatchDragButton:SetPoint("TOPLEFT", "UIParent", "TOPRIGHT", -250, -250);
	qOut(FQ_INFO..FQ_INFO_RESET);
end

function FastQuest_Toggle_Format()
	if (FQD.Format == nil) then FQD.Format = 1;end
	if (FQD.Format == (FQ_nFormats-1)) then
		FQD.Format = 1;
	else
		FQD.Format = FQD.Format+1;
	end
	qOut(FQ_SELECT_FORMAT);
	qOut(FQ_INFO_DISPLAY_AS..FQ_Formats[FQD.Format]);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_MemberInfo()
	info = FQ_INFO..FQ_INFO_MEMBERINFO;
	FQD.MemberInfo = FastQuest_ToggleBoolean(FQD.MemberInfo,info);
	QuestLog_Update();
	FastQuestOptions_Init();
end

function FastQuest_Toggle_NotifyExp()
	info = FQ_INFO..FQ_INFO_NOTIFYEXP;
	FQD.NotifyExp = FastQuest_ToggleBoolean(FQD.NotifyExp,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_NotifyLevelUp()
	info = FQ_INFO..FQ_INFO_NOTIFYLEVELUP;
	FQD.NotifyLevelUp = FastQuest_ToggleBoolean(FQD.NotifyLevelUp,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_NotifyDiscover()
	info = FQ_INFO..FQ_INFO_NOTIFYDISCOVER;
	FQD.NotifyDiscover = FastQuest_ToggleBoolean(FQD.NotifyDiscover,info);
	FastQuestOptions_Init();
end

function FastQuest_Toggle_Tag()
	info = FQ_INFO..FQ_INFO_QUEST_TAG;
	FQD.Tag = FastQuest_ToggleBoolean(FQD.Tag,info);
	QuestLog_Update();
	QuestWatch_Update();
	FastQuestOptions_Init();
end

