-------------------------------------------------------------------------------
--
--  Mod Name : BlinkQuestHelper v1.4
--  Author   : Blink
--  Date     : 2005/03/28
--  LastUpdate : 2007/05/24
--
-------------------------------------------------------------------------------

BlinkQuestHelper_OriginalQuestLog_Update = nil;
BlinkQuestHelper_OriginalQuestLogTitleButton_OnClick = nil;
BlinkQuestHelper_OriginalGetQuestLogIndexByName = nil;
BlinkQuestHelper_OriginalQuestWatch_Update= nil;
BlinkQuestHelper_OriginalGetQuestText = nil;
BlinkQuestHelper_OriginalGetQuestLogQuestText = nil;

-------------------------------------------------------------------------------
-- BlinkPrint
-------------------------------------------------------------------------------
if( not BlinkPrint ) then
	BlinkPrint = function(msg)
		if(ChatFrame1) then
			ChatFrame1:AddMessage(msg, 1.0, 1.0, 0.0);
		end
	end
end

-------------------------------------------------------------------------------

function BlinkQuestHelper_OnLoad()

	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("UI_INFO_MESSAGE");
	this:RegisterEvent("QUEST_LOG_UPDATE");
	this:RegisterEvent("UPDATE_FACTION");
	this:RegisterEvent("UNIT_QUEST_LOG_CHANGED");

	BQH_CONFIG = {};

	SLASH_BQH1 = "/questhelper";
	SLASH_BQH2 = "/qh";
	SLASH_BQH3 = "/퀘도우미";
	SlashCmdList["BQH"] = function (msg) BlinkQuestHelper_SlashCmd(msg); end;
end

function BlinkQuestHelper_OnEvent(event)
	if( event == "VARIABLES_LOADED" )then
		BlinkQuestHelper_Init();
		BlinkQuestHelper_ToggleQuestLevel(BQH_CONFIG.QuestLevel);
		BlinkQuestHelper_ToggleQuestWatch(BQH_CONFIG.QuestWatch);
		BlinkQuestHelper_Status();
		BQH_BlinkModRegister();
		BQH_BlinkGUIRegister();

		setglobal("MAX_QUEST_WATCH_TIME",nil);

	end
	if( event == "UI_INFO_MESSAGE" )then
		if ( BQH_CONFIG.QuestAnnounceToParty == 1 ) then
			local questUpdateText = gsub(arg1,"(.*): %d+/%d+","%1",1);
			if ( questUpdateText ~= arg1 ) then
				BQH_QuestAnnounceToParty(arg1);
			end
		end
	end
	if ( event == "QUEST_LOG_UPDATE" or event == "UPDATE_FACTION" or (event == "UNIT_QUEST_LOG_CHANGED" and arg1 == "player") ) then
		QuestLog_Update();
		QuestWatch_Update();
		if ( QuestLogFrame:IsVisible() ) then
			QuestLog_UpdateQuestDetails(1);
		end
		if( BQH_CONFIG.QuestAutoRemove == 1 )then
			BlinkQuestHelper_QuestWatchAutoRemove();
		end
	end
end

function BlinkQuestHelper_Init()
	if not BQH_CONFIG.QuestLevel then
		BQH_CONFIG.QuestLevel = 1;
	end
	if not BQH_CONFIG.QuestWatch then
		BQH_CONFIG.QuestWatch = 1;
	end
	if not BQH_CONFIG.QuestAutoAdd then
		BQH_CONFIG.QuestAutoAdd = 1;
		setglobal("AUTO_QUEST_WATCH","1");
	end
	if not BQH_CONFIG.QuestAutoRemove then
		BQH_CONFIG.QuestAutoRemove = 1;
	end
	if not BQH_CONFIG.QuestAnnounceToParty then
		BQH_CONFIG.QuestAnnounceToParty = 1;
	end
--	if not BQH_CONFIG.QuestDetailAnnounceToParty then
--		BQH_CONFIG.QuestDetailAnnounceToParty = 0;
--	end
	if ( BQH_CONFIG.QuestAutoAdd == 1 ) then
		setglobal("AUTO_QUEST_WATCH","1");
	end

	-- hooks
	BlinkQuestHelper_OriginalQuestLog_Update = QuestLog_Update;
	QuestLog_Update = BlinkQuestHelper_QuestLog_Update;

	BlinkQuestHelper_OriginalQuestLogTitleButton_OnClick = QuestLogTitleButton_OnClick;
	QuestLogTitleButton_OnClick = BlinkQuestHelper_QuestLogTitleButton_OnClick;

	BlinkQuestHelper_OriginalGetQuestLogIndexByName = GetQuestLogIndexByName;
	GetQuestLogIndexByName = BlinkQuestHelper_GetQuestLogIndexByName;

	BlinkQuestHelper_OriginalQuestWatch_Update = QuestWatch_Update;
	QuestWatch_Update = BlinkQuestHelper_QuestWatch_Update;

	BlinkQuestHelper_OriginalGetQuestText = GetQuestText;
	GetQuestText = BlinkQuestHelper_GetQuestText;

	BlinkQuestHelper_OriginalGetQuestLogQuestText = GetQuestLogQuestText;
	GetQuestLogQuestText = BlinkQuestHelper_GetQuestLogQuestText;
end

function BlinkQuestHelper_FindQuestIndexByUIMessage(message)
	for i=1, GetNumQuestLogEntries(), 1 do
		numObjectives = GetNumQuestLeaderBoards(i);
		if( numObjectives > 0 )then
			for j=1, numObjectives do
				text, type_, finished = GetQuestLogLeaderBoard(j, i);
				if (gsub(message,"(.*): %d+/%d+","%1",1) == gsub(text,"(.*): %d+/%d+","%1",1)) then
					return i;
				end
			end
		end
	end
	return nil;
end

function BQH_QuestAnnounceToParty(msg)
	if ( GetNumPartyMembers()>0 ) then
		local updatedIndex = BlinkQuestHelper_FindQuestIndexByUIMessage(msg);
		if( updatedIndex )then
			local questLogTitleText, level, questTag = GetQuestLogTitle(updatedIndex);
			if( questLogTitleText )then
				if ( questTag == ELITE ) then
					questLogTitleText = "Lv."..level.."+ "..strtrim(questLogTitleText);
				elseif ( questTag == RAID ) then
					questLogTitleText = "Lv."..level.."(공) "..strtrim(questLogTitleText);
				elseif ( questTag == GROUP ) then
					questLogTitleText = "Lv."..level.."(파) "..strtrim(questLogTitleText);
				elseif ( questTag == LFG_TYPE_DUNGEON ) then
					questLogTitleText = "Lv."..level.."(던) "..strtrim(questLogTitleText);
				elseif ( questTag == "전쟁" ) then -- ? PVP?
					questLogTitleText = "Lv."..level.."(쟁) "..strtrim(questLogTitleText);
				else
					questLogTitleText = "Lv."..level.." "..strtrim(questLogTitleText);
				end
				questLogTitleText = questLogTitleText .. ": " .. msg;
--				if ( BQH_CONFIG.QuestDetailAnnounceToParty == 1 ) then
--					local _, _, a, b = msg:find(".+: (%d+)/(%d+)")
--					if ( a and b and a == b ) then
--						BlinkQuestHelper_Notice(questLogTitleText, updatedIndex, "PARTY");
--						return;
--					end
--				end
				SendChatMessage( questLogTitleText, "PARTY" );
			end
		end
	end
end

function BlinkQuestHelper_QuestWatchAutoRemove()
	local needUpdate = false;
	local numQuestWatches = GetNumQuestWatches();
	for i=1, numQuestWatches do
		questIndex = GetQuestIndexForWatch(i);
		if ( questIndex ) then
			local _, _, _, _, isHeader, _, isComplete = GetQuestLogTitle(questIndex);
			if ( not isHeader ) then
				if ( isComplete and isComplete > 0 ) then
					RemoveQuestWatch(questIndex);
					needUpdate = true;
				end
			end
		end
	end
	if( needUpdate )then QuestWatch_Update(); end
end

function BlinkQuestHelper_ShowDropdown(questTitle,questIndex)
	HideDropDownMenu(1);
	if ( questIndex ) then
		UIDropDownMenu_Initialize(BlinkQuestHelperDropDown, function ()
			local info = {};
			info.isTitle = 1;
			info.text = "진행상황 알림";
			UIDropDownMenu_AddButton(info);

			info = {};
			info.text = "일반 대화";
			info.func = function ()
				BlinkQuestHelper_Notice(questTitle,questIndex,"SAY");
			end
			UIDropDownMenu_AddButton(info);

			info = {};
			info.text = "외치기";
			info.func = function ()
				BlinkQuestHelper_Notice(questTitle,questIndex,"YELL");
			end
			UIDropDownMenu_AddButton(info);

			if ( GetNumPartyMembers() > 0 ) then
				info = {};
				info.text = "파티원";
				info.func = function ()
					BlinkQuestHelper_Notice(questTitle,questIndex,"PARTY");
				end
				UIDropDownMenu_AddButton(info);
			end
			if ( UnitInRaid("player") ) then
				info = {};
				info.text = "공대원";
				info.func = function ()
					BlinkQuestHelper_Notice(questTitle,questIndex,"RAID");
				end
				UIDropDownMenu_AddButton(info);
			end

			if ( UnitExists("target") and UnitIsFriend("player","target") and UnitIsPlayer("target") and not UnitIsUnit("player","target") ) then
				info = {};
				info.text = "귓속말 : "..UnitName("target");
				info.func = function ()
					BlinkQuestHelper_Notice(questTitle,questIndex,"WHISPER",UnitName("target"));
				end
				UIDropDownMenu_AddButton(info);
			end

			if ( IsInGuild() ) then
				info = {};
				info.text = "길드";
				info.func = function ()
					BlinkQuestHelper_Notice(questTitle,questIndex,"GUILD");
				end
				UIDropDownMenu_AddButton(info);
			end
		end ,"MENU");
		ToggleDropDownMenu(1, nil, BlinkQuestHelperDropDown, "cursor");
	end
end

function BlinkQuestHelper_Notice(questTitle,questIndex, chat, who)
	local _, _, questTag = GetQuestLogTitle(questIndex);
	local questString = {};
	local title; -- = gsub(questTitle:GetText(), " *(.*)", "%1");
	local numObjectives = GetNumQuestLeaderBoards(questIndex);
	if ( type(questTitle)=="string" ) then
		title = questTitle
	else
		title = gsub(questTitle:GetText(), " *(.*)", "%1");
	end
	if ( questTag ) then
		title = title.."("..questTag..")";
	end
	table.insert(questString,title);
	for i=1, numObjectives, 1 do
		local text, type, finished = GetQuestLogLeaderBoard(i,questIndex);
		if ( not text or strlen(text) == 0 ) then
			text = type;
		end
		if ( finished ) then
			text = text.." ("..COMPLETE..")";
		end
		text = "  - "..text;
		table.insert(questString,text);
	end
	if ( table.getn(questString) > 1 ) then
		for i=1, table.getn(questString) do
			SendChatMessage(questString[i], chat, GetDefaultLanguage(), who);
		end
	end
end

function BlinkQuestHelper_ToggleQuestLevel(toggle)
	if( toggle == 1 )then
		BQH_CONFIG.QuestLevel = 1;
	elseif( toggle == 0 )then
		BQH_CONFIG.QuestLevel = 0;
	else
		if( BQH_CONFIG.QuestLevel ~= 1 )then
			BQH_CONFIG.QuestLevel = 1;
		else
			BQH_CONFIG.QuestLevel = 0;
		end
	end
	QuestLog_Update();
	QuestWatch_Update();
end

function BlinkQuestHelper_ToggleQuestWatch(toggle)
	if( toggle == 1 )then
		BQH_CONFIG.QuestWatch = 1;
	elseif( toggle == 0 )then
		BQH_CONFIG.QuestWatch = 0;
	else
		if( BQH_CONFIG.QuestWatch ~= 1 )then
			BQH_CONFIG.QuestWatch = 1;
		else
			BQH_CONFIG.QuestWatch = 0;
		end
	end
	QuestLog_Update();
	QuestWatch_Update();
end

function BlinkQuestHelper_SlashCmd(msg)
	local cmd = gsub(msg, "%s*([^%s]+).*", "%1");

	if( strlen(cmd) <= 0 ) then
		BlinkQuestHelper_Usage();
		return;
	end

	if( cmd == "레벨" )then
		BlinkQuestHelper_ToggleQuestLevel();
		if( BQH_CONFIG.QuestLevel == 1 )then
			BlinkPrint("퀘스트목록에 레벨을 표시합니다.");
		else
			BlinkPrint("퀘스트목록에 레벨을 표시하지 않습니다.");
		end
		return;
	elseif( cmd == "색상" )then
		BlinkQuestHelper_ToggleQuestWatch();
		if( BQH_CONFIG.QuestWatch == 1 )then
			BlinkPrint("퀘스트도우미의 진행상황을 색장으로 표시해줍니다.");
		else
			BlinkPrint("퀘스트도우미를 원래 기능으로 되돌립니다.");
		end
		return;
	elseif( cmd == "자동제거" )then
		if( BQH_CONFIG.QuestAutoRemove == 0 )then
			BlinkPrint("퀘스트도우미에 등록된 퀘스트중 완료된 퀘스트는 자동으로 제거합니다.");
			BQH_CONFIG.QuestAutoRemove = 1;
		else
			BlinkPrint("퀘스트가 완료되도 퀘스트도우미 리스트에서 자동으로 제거하지 않습니다.");
			BQH_CONFIG.QuestAutoRemove = 0;
		end
		return;
	elseif( cmd == "자동추가" )then
		if( BQH_CONFIG.QuestAutoAdd == 0 )then
			BlinkPrint("퀘스트아이템을 얻으면 퀘스트도우미에 자동으로 추가합니다.");
			BQH_CONFIG.QuestAutoAdd = 1;
			setglobal("AUTO_QUEST_WATCH","1");
		else
			BlinkPrint("퀘스트도우미에 수동으로 추가해야합니다.-_-");
			BQH_CONFIG.QuestAutoAdd = 0;
			setglobal("AUTO_QUEST_WATCH","0");
		end
		return;
	elseif( cmd == "파티알림" )then
		if( BQH_CONFIG.QuestAnnounceToParty == 0 )then
			BlinkPrint("퀘스트아이템을 얻으면 파티원에게 알려줍니다.");
			BQH_CONFIG.QuestAnnounceToParty = 1;
		else
			BlinkPrint("파티원에게 알리지않습니다.");
			BQH_CONFIG.QuestAnnounceToParty = 0;
		end
		return;
--	elseif( cmd == "파티상세알림" )then
--		if( BQH_CONFIG.QuestDetailAnnounceToParty == 0 )then
--			BlinkPrint("퀘스트가 부분적으로 완료되었을때 파티원에게 상세하게 알려줍니다.");
--			BQH_CONFIG.QuestDetailAnnounceToParty = 1;
--		else
--			BlinkPrint("파티원에게 자세히~_~ 알리지않습니다.");
--			BQH_CONFIG.QuestDetailAnnounceToParty = 0;
--		end
--		return;
	elseif( cmd == "설정보기" or cmd == "?" )then
		BlinkQuestHelper_Status();
		return;
	end
	BlinkQuestHelper_Usage();
end

function BlinkQuestHelper_Usage()
	BlinkPrint("퀘스트도우미 사용방법:");
	BlinkPrint(" /퀘도우미          : 도움말");
	BlinkPrint(" /퀘도우미 레벨     : 퀘스트목록에서 레벨을 표시해줍니다.");
	BlinkPrint(" /퀘도우미 색상     : 퀘스트도우미의 진행상황을 색상으로 표시해줍니다.");
	BlinkPrint(" /퀘도우미 자동추가 : 퀘스트도우미에 자동으로 추가");
	BlinkPrint(" /퀘도우미 자동제거 : 완료된 퀘스트 자동으로 제거");
	BlinkPrint(" /퀘도우미 파티알림 : 퀘스트 진행상황을 파티원에게 알립니다.");
--	BlinkPrint(" /퀘도우미 파티상세알림 : 퀘스트가 부분적으로 완료되었을때 파티원에게 상세하게 알려줍니다.");
	BlinkPrint(" /퀘도우미 설정보기 : 퀘스트도우미 설정상태를 확인할수 있습니다.");
end

function BlinkQuestHelper_Status()
	BlinkPrint("퀘스트도우미 설정상태:");
	if( BQH_CONFIG.QuestLevel == 1 )then
		BlinkPrint("  퀘스트레벨표시 : |cff00ff00켜짐|r");
	else
		BlinkPrint("  퀘스트레벨표시 : |cffff0000꺼짐|r");
	end
	if( BQH_CONFIG.QuestWatch == 1 )then
		BlinkPrint("  퀘스트도우미 색상표시 : |cff00ff00켜짐|r");
	else
		BlinkPrint("  퀘스트도우미 색상표시 : |cffff0000꺼짐|r");
	end
	if( BQH_CONFIG.QuestAutoAdd == 1 )then
		BlinkPrint("  퀘스트도우미 자동추가 : |cff00ff00켜짐|r");
	else
		BlinkPrint("  퀘스트도우미 자동추가 : |cffff0000꺼짐|r");
	end
	if( BQH_CONFIG.QuestAutoRemove == 1 )then
		BlinkPrint("  퀘스트도우미 자동제거 : |cff00ff00켜짐|r");
	else
		BlinkPrint("  퀘스트도우미 자동제거 : |cffff0000꺼짐|r");
	end
	if( BQH_CONFIG.QuestAnnounceToParty == 1 )then
		BlinkPrint("  퀘스트도우미 파티알림 : |cff00ff00켜짐|r");
	else
		BlinkPrint("  퀘스트도우미 파티알림 : |cffff0000꺼짐|r");
	end
--	if( BQH_CONFIG.QuestDetailAnnounceToParty == 1 )then
--		BlinkPrint("  퀘스트도우미 파티상세알림 : |cff00ff00켜짐|r");
--	else
--		BlinkPrint("  퀘스트도우미 파티상세알림 : |cffff0000꺼짐|r");
--	end
end


-------------------------------------------------------------------------------
-- Hooking Functions
-------------------------------------------------------------------------------

local function colorizeQuestText(text)
	-- from nQuestLog
	text = gsub(text,"([^%a%d%|])(%d+)([^%a%d%|])", "%1|cff000000%2|r%3"); -- Match numbers
	text = gsub(text,"([^%a%d%|])(%d+)([^%a%d%|])", "%1|cff000000%2|r%3"); -- Match numbers again

	text = gsub(text,"("..UnitName("player")..")", "|cff000000%1|r");
	text = gsub(text,"([^%s%|r]+)에게 ", "|cff000000%1|r에게 ");
	text = gsub(text,"([^%s%|r]+)(%|1으로;로;) ", "|cff000000%1|r%2 ");
	text = gsub(text,"([^%s%|r]+)(%|1을;를;) ", "|cff000000%1|r%2 ");
	text = gsub(text,"([^%s%|r]+)(%|1이여;여;) ", "|cff000000%1|r%2 ");
	text = gsub(text,"([^%s%|r]+)(%|1이;가;) ", "|cff000000%1|r%2 ");
	text = gsub(text,"([^%s%|r]+)(%|1과;와;) ", "|cff000000%1|r%2 ");
	text = gsub(text,"([^%s%|r]+)(%|1이라는;라는;) ", "|cff000000%1|r%2 ");
	text = gsub(text,"([^%s%|r]+)(%|1은;는;) ", "|cff000000%1|r%2 ");

	text = gsub(text,"(북서쪽)([^%a%d])", "|cff000000%1|r%2");
	text = gsub(text,"(북동쪽)([^%a%d])", "|cff000000%1|r%2");
	text = gsub(text,"(남서쪽)([^%a%d])", "|cff000000%1|r%2");
	text = gsub(text,"(남동쪽)([^%a%d])", "|cff000000%1|r%2");
	text = gsub(text,"(북서쪽)([^%a%d])", "|cff000000%1|r%2");
	text = gsub(text,"(북쪽)([^%a%d])", "|cff000000%1|r%2");
	text = gsub(text,"(서쪽)([^%a%d])", "|cff000000%1|r%2");
	text = gsub(text,"(동쪽)([^%a%d])", "|cff000000%1|r%2");
	text = gsub(text,"(남쪽)([^%a%d])", "|cff000000%1|r%2");
	return text;
end

function BlinkQuestHelper_GetQuestText()
	local text = BlinkQuestHelper_OriginalGetQuestText();
	return colorizeQuestText(text);
end

function BlinkQuestHelper_GetQuestLogQuestText()
	questDescription, questObjectives = BlinkQuestHelper_OriginalGetQuestLogQuestText();
	questObjectives = colorizeQuestText(questObjectives);
	questDescription = colorizeQuestText(questDescription);
	return questDescription, questObjectives;
end

function BlinkQuestHelper_QuestLog_Update()
	local numEntries, numQuests = GetNumQuestLogEntries();
	if ( numEntries == 0 ) then
		EmptyQuestLogFrame:Show();
		QuestLogFrameAbandonButton:Disable();
		QuestLogFrame.hasTimer = nil;
		QuestLogDetailScrollFrame:Hide();
		QuestLogExpandButtonFrame:Hide();
	else
		EmptyQuestLogFrame:Hide();
		QuestLogFrameAbandonButton:Enable();
		QuestLogDetailScrollFrame:Show();
		QuestLogExpandButtonFrame:Show();
	end

	-- Update Quest Count
	QuestLogUpdateQuestCount(numQuests);

	-- ScrollFrame update
	FauxScrollFrame_Update(QuestLogListScrollFrame, numEntries, QUESTS_DISPLAYED, QUESTLOG_QUEST_HEIGHT, nil, nil, nil, QuestLogHighlightFrame, 293, 316 )
	
	-- Update the quest listing
	QuestLogHighlightFrame:Hide();

	-- If no selection then set it to the first available quest
	if ( GetQuestLogSelection() == 0 ) then
		QuestLog_SetFirstValidSelection();
	end

	local questIndex, questLogTitle, questTitleTag, questNumGroupMates, questNormalText, questHighlight, questCheck;
	local questLogTitleText, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, color;
	local numPartyMembers, partyMembersOnQuest, tempWidth, textWidth;
	for i=1, QUESTS_DISPLAYED, 1 do
		questIndex = i + FauxScrollFrame_GetOffset(QuestLogListScrollFrame);
		questLogTitle = getglobal("QuestLogTitle"..i);
		questTitleTag = getglobal("QuestLogTitle"..i.."Tag");
		questNumGroupMates = getglobal("QuestLogTitle"..i.."GroupMates");
		questCheck = getglobal("QuestLogTitle"..i.."Check");
		questNormalText = getglobal("QuestLogTitle"..i.."NormalText");
		questHighlight = getglobal("QuestLogTitle"..i.."Highlight");
		if ( questIndex <= numEntries ) then
			questLogTitleText, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily = GetQuestLogTitle(questIndex);
			if ( isHeader ) then
				if ( questLogTitleText ) then
					questLogTitle:SetText(questLogTitleText);
				else
					questLogTitle:SetText("");
				end
				
				if ( isCollapsed ) then
					questLogTitle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up");
				else
					questLogTitle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up"); 
				end
				questHighlight:SetTexture("Interface\\Buttons\\UI-PlusButton-Hilight");
				questNumGroupMates:SetText("");
				questCheck:Hide();
			else
				if ( BQH_CONFIG.QuestLevel == 1 ) then
					questLogTitle:SetText("  Lv."..level.." "..questLogTitleText);
					--Set Dummy text to get text width *SUPER HACK*
					QuestLogDummyText:SetText("  Lv."..level.." "..questLogTitleText);
				else
					questLogTitle:SetText("  "..questLogTitleText);
					--Set Dummy text to get text width *SUPER HACK*
					QuestLogDummyText:SetText("  "..questLogTitleText);
				end

				questLogTitle:SetNormalTexture("");
				questHighlight:SetTexture("");

				-- If not a header see if any nearby group mates are on this quest
				numPartyMembers = GetNumPartyMembers();
				if ( numPartyMembers == 0 ) then
					--return;
				end
				partyMembersOnQuest = 0;
				for j=1, numPartyMembers do
					if ( IsUnitOnQuest(questIndex, "party"..j) ) then
						partyMembersOnQuest = partyMembersOnQuest + 1;
					end
				end
				if ( partyMembersOnQuest > 0 ) then
					questNumGroupMates:SetText("["..partyMembersOnQuest.."]");
				else
					questNumGroupMates:SetText("");
				end
			end
			-- Save if its a header or not
			questLogTitle.isHeader = isHeader;

			if ( isComplete and isComplete < 0 ) then
				questTag = FAILED;
			elseif ( isComplete and isComplete > 0 ) then
				questTag = COMPLETE;
			elseif ( isDaily ) then
				if ( questTag ) then
					questTag = format(DAILY_QUEST_TAG_TEMPLATE, questTag);
				else
					questTag = DAILY;
				end
			end
			if ( questTag ) then
				questTitleTag:SetText("("..questTag..")");
				-- Shrink text to accomdate quest tags without wrapping
				tempWidth = 275 - 15 - questTitleTag:GetWidth();

				if ( QuestLogDummyText:GetWidth() > tempWidth ) then
					textWidth = tempWidth;
				else
					textWidth = QuestLogDummyText:GetWidth();
				end

				questNormalText:SetWidth(tempWidth);
				
				-- If there's quest tag position check accordingly
				questCheck:Hide();
				if ( IsQuestWatched(questIndex) ) then
					if ( questNormalText:GetWidth() + 24 < 275 ) then
						questCheck:SetPoint("LEFT", questLogTitle, "LEFT", textWidth+24, 0);
					else
						questCheck:SetPoint("LEFT", questLogTitle, "LEFT", textWidth+10, 0);
					end
					questCheck:Show();
				end
			else
				questTitleTag:SetText("");
				questNormalText:SetWidth(275);

				-- Show check if quest is being watched
				questCheck:Hide();
				if ( IsQuestWatched(questIndex) ) then
					if ( questNormalText:GetWidth() + 24 < 275 ) then
						questCheck:SetPoint("LEFT", questNormalText, "LEFT", questNormalText:GetWidth()+24, 0);
					else
						questCheck:SetPoint("LEFT", questNormalText, "LEFT", questNormalText:GetWidth()-10, 0);
					end
					questCheck:Show();
				end
			end

			-- Color the quest title and highlight according to the difficulty level
			local playerLevel = UnitLevel("player");
			if ( isHeader ) then
				color = QuestDifficultyColor["header"];
			else
				color = GetDifficultyColor(level);
			end
			questTitleTag:SetTextColor(color.r, color.g, color.b);
			questLogTitle:SetTextColor(color.r, color.g, color.b);
			questNumGroupMates:SetTextColor(color.r, color.g, color.b);
			questLogTitle.r = color.r;
			questLogTitle.g = color.g;
			questLogTitle.b = color.b;
			questLogTitle:Show();

			-- Place the highlight and lock the highlight state
			if ( QuestLogFrame.selectedButtonID and GetQuestLogSelection() == questIndex ) then
				QuestLogHighlightFrame:SetPoint("TOPLEFT", "QuestLogTitle"..i, "TOPLEFT", 0, 0);
				QuestLogSkillHighlight:SetVertexColor(questLogTitle.r, questLogTitle.g, questLogTitle.b);
				QuestLogHighlightFrame:Show();
				questTitleTag:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
				questLogTitle:LockHighlight();
			else
				questLogTitle:UnlockHighlight();
			end
		else
			questLogTitle:Hide();
		end
	end
		
	-- Set the expand/collapse all button texture
	local numHeaders = 0;
	local notExpanded = 0;
	-- Somewhat redundant loop, but cleaner than the alternatives
	for i=1, numEntries, 1 do
		local index = i;
		local questLogTitleText, level, questTag, suggestedGroup, isHeader, isCollapsed = GetQuestLogTitle(i);
		if ( questLogTitleText and isHeader ) then
			numHeaders = numHeaders + 1;
			if ( isCollapsed ) then
				notExpanded = notExpanded + 1;
			end
		end
	end
	-- If all headers are not expanded then show collapse button, otherwise show the expand button
	if ( notExpanded ~= numHeaders ) then
		QuestLogCollapseAllButton.collapsed = nil;
		QuestLogCollapseAllButton:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up");
	else
		QuestLogCollapseAllButton.collapsed = 1;
		QuestLogCollapseAllButton:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up");
	end

	-- Determine whether the selected quest is pushable or not
	if ( numEntries == 0 ) then
		QuestFramePushQuestButton:Disable();
	elseif ( GetQuestLogPushable() and GetNumPartyMembers() > 0 ) then
		QuestFramePushQuestButton:Enable();
	else
		QuestFramePushQuestButton:Disable();
	end
end

function BlinkQuestHelper_QuestLogTitleButton_OnClick(button)
	local questName = this:GetText();
	local questIndex = this:GetID() + FauxScrollFrame_GetOffset(QuestLogListScrollFrame);
	if ( button == "LeftButton" ) then
		if ( IsShiftKeyDown() ) then
			-- If header then return
			if ( this.isHeader ) then
				return;
			end
			-- Otherwise try to track it or put it into chat
			if ( ChatFrameEditBox:IsVisible() ) then
				local questLogTitleText, level, questTag = GetQuestLogTitle(questIndex);
				if ( questTag == ELITE ) then
					questLogTitleText = "[Lv."..level.."+ "..strtrim(questLogTitleText).."]";
				elseif ( questTag == RAID ) then
					questLogTitleText = "[Lv."..level.."(공) "..strtrim(questLogTitleText).."]";
				elseif ( questTag == GROUP ) then
					questLogTitleText = "[Lv."..level.."(파) "..strtrim(questLogTitleText).."]";
				elseif ( questTag == LFG_TYPE_DUNGEON ) then
					questLogTitleText = "[Lv."..level.."(던) "..strtrim(questLogTitleText).."]";
				elseif ( questTag == "전쟁" ) then -- ? PVP?
					questLogTitleText = "[Lv."..level.."(쟁) "..strtrim(questLogTitleText).."]";
				else
					questLogTitleText = "[Lv."..level.." "..strtrim(questLogTitleText).."]";
				end
				ChatFrameEditBox:Insert(questLogTitleText);
			else
				-- Shift-click toggles quest-watch on this quest.
				if ( IsQuestWatched(questIndex) ) then
					RemoveQuestWatch(questIndex);
					QuestWatch_Update();
				else
					-- Set error if no objectives
					if ( GetNumQuestLeaderBoards(questIndex) == 0 ) then
						UIErrorsFrame:AddMessage(QUEST_WATCH_NO_OBJECTIVES, 1.0, 0.1, 0.1, 1.0);
						return;
					end
					-- Set an error message if trying to show too many quests
					if ( GetNumQuestWatches() >= MAX_WATCHABLE_QUESTS ) then
						UIErrorsFrame:AddMessage(format(QUEST_WATCH_TOO_MANY, MAX_WATCHABLE_QUESTS), 1.0, 0.1, 0.1, 1.0);
						return;
					end
					AddQuestWatch(questIndex);
					QuestLog_Update();
					QuestWatch_Update();
				end
			end
		elseif ( IsControlKeyDown() ) then
			local _, _, questTag = GetQuestLogTitle(questIndex);
			local questString = {};
			local title = strtrim(this:GetText());
			local numObjectives = GetNumQuestLeaderBoards(questIndex);
			if ( questTag ) then
				title = title.."("..questTag..")";
			end
			table.insert(questString,title);
			for i=1, numObjectives, 1 do
				local text, type, finished = GetQuestLogLeaderBoard(i,questIndex);
				if ( not text or strlen(text) == 0 ) then
					text = type;
				end
				if ( finished ) then
					text = text.." ("..COMPLETE..")";
				end
				text = "  - "..text;
				table.insert(questString,text);
			end
			if ( table.getn(questString) > 1 ) then
				for i=1, table.getn(questString) do
					if ( GetNumPartyMembers()>0 and not UnitInRaid("player") ) then
						SendChatMessage(questString[i], "PARTY");
					elseif ( UnitInRaid("player") ) then
						SendChatMessage(questString[i], "RAID");
					else
						SendChatMessage(questString[i], "SAY");
					end
				end
			end
		end
	else
		BlinkQuestHelper_ShowDropdown(this,questIndex);
	end

	QuestLog_SetSelection(questIndex)
	QuestLog_Update();
end

-- QuestWatch functions
function BlinkQuestHelper_QuestWatch_Update()
	local numObjectives;
	local questWatchMaxWidth = 0;
	local tempWidth;
	local watchText;
	local text, type_, finished;
	local questTitle,qlevel;
	local watchTextIndex = 1;
	local questIndex;
	local objectivesCompleted;

	for i=1, GetNumQuestWatches() do
		questIndex = GetQuestIndexForWatch(i);
		if ( questIndex ) then
			numObjectives = GetNumQuestLeaderBoards(questIndex);
		
			--If there are objectives set the title
			if ( numObjectives > 0 ) then
				-- Set title
				watchText = getglobal("QuestWatchLine"..watchTextIndex);
				questTitle,qlevel = GetQuestLogTitle(questIndex);
				if ( BQH_CONFIG.QuestLevel == 1 ) then
					watchText:SetText("["..qlevel.."] "..questTitle);
				else
					watchText:SetText(questTitle);
				end
				
				tempWidth = watchText:GetWidth();
				-- Set the anchor of the title line a little lower
				if ( watchTextIndex > 1 ) then
					watchText:SetPoint("TOPLEFT", "QuestWatchLine"..(watchTextIndex - 1), "BOTTOMLEFT", 0, -4);
				end
				watchText:Show();
				if ( tempWidth > questWatchMaxWidth ) then
					questWatchMaxWidth = tempWidth;
				end
				watchTextIndex = watchTextIndex + 1;
				objectivesCompleted = 0;
				for j=1, numObjectives do
					text, type_, finished = GetQuestLogLeaderBoard(j, questIndex);
					watchText = getglobal("QuestWatchLine"..watchTextIndex);
					-- Set Objective text
					local qlc = BlinkQuestHelper_GetLeaderboardColor(text);
					-- Color the objectives
					if ( finished ) then
						watchText:SetText(" - "..text.." ("..COMPLETE..")");
						if( qlc and BQH_CONFIG.QuestWatch == 1 )then
							watchText:SetTextColor(qlc.r, qlc.g, qlc.b);
						else
							watchText:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
						end
						objectivesCompleted = objectivesCompleted + 1;
					else
						watchText:SetText(" - "..text);
						if( qlc and BQH_CONFIG.QuestWatch == 1 )then
							watchText:SetTextColor(qlc.r, qlc.g, qlc.b);
						else
							watchText:SetTextColor(0.8, 0.8, 0.8);
						end
					end
					tempWidth = watchText:GetWidth();
					if ( tempWidth > questWatchMaxWidth ) then
						questWatchMaxWidth = tempWidth;
					end
					watchText:SetPoint("TOPLEFT", "QuestWatchLine"..(watchTextIndex - 1), "BOTTOMLEFT", 0, 0);
					watchText:Show();
					watchTextIndex = watchTextIndex + 1;
				end
				-- Brighten the quest title if all the quest objectives were met
				watchText = getglobal("QuestWatchLine"..watchTextIndex-numObjectives-1);
				if ( objectivesCompleted == numObjectives ) then
					watchText:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
				else
					if ( BQH_CONFIG.QuestWatch == 1 ) then
						local qtc = GetDifficultyColor(qlevel);
						watchText:SetTextColor(qtc.r, qtc.g, qtc.b);
					else
						watchText:SetTextColor(0.75, 0.61, 0);
					end
				end
			end
		end
	end

	-- Set tracking indicator
	if ( GetNumQuestWatches() > 0 ) then
		QuestLogTrackTracking:SetVertexColor(0, 1.0, 0);
	else
		QuestLogTrackTracking:SetVertexColor(1.0, 0, 0);
	end
	
	-- If no watch lines used then hide the frame and return
	if ( watchTextIndex == 1 ) then
		QuestWatchFrame:Hide();
		return;
	else
		QuestWatchFrame:Show();
		QuestWatchFrame:SetHeight(watchTextIndex * 13);
		QuestWatchFrame:SetWidth(questWatchMaxWidth + 10);
	end

	-- Hide unused watch lines
	for i=watchTextIndex, MAX_QUESTWATCH_LINES do
		getglobal("QuestWatchLine"..i):Hide();
	end

	UIParent_ManageFramePositions();
end

function BlinkQuestHelper_GetQuestLogIndexByName(name)
	local numEntries = GetNumQuestLogEntries();
	local questLogTitleText,level;
	for i=1, numEntries, 1 do
		questLogTitleText,level = GetQuestLogTitle(i);
		if ( BQH_CONFIG.QuestWatch == 1 ) then
			questLogTitleText = "Lv."..level.." "..questLogTitleText;
		end
		if ( "  "..questLogTitleText == name ) then
			return i;
		end
	end
	return nil;
end

function BlinkQuestHelper_GetLeaderboardColor(text)
	local _,_,curcol,maxcol = string.find(text,".+: (%d+)/(%d+)");
	local color = {};
	if( curcol and maxcol )then
		local p = curcol / maxcol;
		if( p == 0 )then
			color.r = 1.0;
			color.g = 0.0;
		elseif( p == 1 )then
			color.r = 0.0;
			color.g = 1.0;
		else
			color.r = 1.0 - p;
			color.g = p;
		end
		color.b = 0.0;
		return color;
	end
	return nil;
end

-- BlinkMod GUI Config --------------------------------------------------------

function BQH_BlinkModRegister()
	if ( not BlinkMod_RegisterMenu ) then
		return;
	end

	local info;

	-- tier 1
	info = {};
	info.parentkey = "SELF";
	info.key = "BQHMAIN";
	info.text = "퀘스트도우미";
	info.hasArrow = 1;
	info.tooltipTitle = "퀘스트도우미";
	info.tooltipText = "기본 퀘스트도우미의 기능을 확장합니다.";
	info.notCheckable = 1;
	BlinkMod_RegisterMenu( info, 1 );

		-- tier 2 : parent = BQHMAIN
		info = {};
		info.parentkey = "BQHMAIN";
		info.key = "BQHTITLE";
		info.text = "퀘스트도우미";
		info.isTitle = 1;
		info.notCheckable = 1;
		BlinkMod_RegisterMenu( info, 2 );

		info = {};
		info.parentkey = "BQHMAIN";
		info.key = "BQHQUESTLEVEL";
		info.text = "레벨표시";
		info.tooltipTitle = "퀘스트레벨표시";
		info.tooltipText = "퀘스트목록에 레벨을 표시합니다.";
		info.ClickFunction = BQH_BM_QuestLevelClick;
		info.CheckFunction = BQH_BM_QuestLevelCheck;
		BlinkMod_RegisterMenu( info, 2 );

		info = {};
		info.parentkey = "BQHMAIN";
		info.key = "BQHQUESTWATCH";
		info.text = "색상표시";
		info.tooltipTitle = "퀘스트색상표시";
		info.tooltipText = "퀘스트도우미의 진행상황을 색상으로 표시해줍니다.";
		info.ClickFunction = BQH_BM_QuestWatchClick;
		info.CheckFunction = BQH_BM_QuestWatchCheck;
		BlinkMod_RegisterMenu( info, 2 );

		info = {};
		info.parentkey = "BQHMAIN";
		info.key = "BQHQUESTAUTOADD";
		info.text = "자동추가";
		info.tooltipTitle = "퀘스트자동추가";
		info.tooltipText = "퀘스트몹이나 퀘스트아이템을 얻을 경우 퀘스트도우미에 자동으로 추가합니다.";
		info.ClickFunction = BQH_BM_QuestAutoAddClick;
		info.CheckFunction = BQH_BM_QuestAutoAddCheck;
		BlinkMod_RegisterMenu( info, 2 );

		info = {};
		info.parentkey = "BQHMAIN";
		info.key = "BQHQUESTAUTOREMOVE";
		info.text = "자동제거";
		info.tooltipTitle = "퀘스트자동제거";
		info.tooltipText = "해당 퀘스트가 완료가 되면 자동으로 퀘스트도우미 목록에서 제거합니다.";
		info.ClickFunction = BQH_BM_QuestAutoRemoveClick;
		info.CheckFunction = BQH_BM_QuestAutoRemoveCheck;
		BlinkMod_RegisterMenu( info, 2 );

		info = {};
		info.parentkey = "BQHMAIN";
		info.key = "BQHQUESTANNOUNCE";
		info.text = "파티알림";
		info.tooltipTitle = "파티알림";
		info.tooltipText = "퀘스트 진행상황을 파티원들에게 알려줍니다.";
		info.ClickFunction = BQH_BM_QuestAnnouncePartyClick;
		info.CheckFunction = BQH_BM_QuestAnnouncePartyCheck;
		BlinkMod_RegisterMenu( info, 2 );
end
-------------------------------------------------------------------------------
function BQH_BM_QuestLevelClick()
	BlinkQuestHelper_ToggleQuestLevel();
end

function BQH_BM_QuestLevelCheck()
	if ( BQH_CONFIG.QuestLevel == 1 ) then
		return true;
	else
		return false;
	end
end
-------------------------------------------------------------------------------
function BQH_BM_QuestWatchClick()
	BlinkQuestHelper_ToggleQuestWatch();
end

function BQH_BM_QuestWatchCheck()
	if ( BQH_CONFIG.QuestWatch == 1 ) then
		return true;
	else
		return false;
	end
end
-------------------------------------------------------------------------------
function BQH_BM_QuestAutoAddClick()
	if ( BQH_CONFIG.QuestAutoAdd == 0 ) then
		BQH_CONFIG.QuestAutoAdd = 1;
		setglobal("AUTO_QUEST_WATCH","1");
	else
		BQH_CONFIG.QuestAutoAdd = 0;
		setglobal("AUTO_QUEST_WATCH","0");
	end
end
function BQH_BM_QuestAutoAddCheck()
	if ( BQH_CONFIG.QuestAutoAdd == 1 ) then
		return true;
	else
		return false;
	end
end
-------------------------------------------------------------------------------
function BQH_BM_QuestAutoRemoveClick()
	if ( BQH_CONFIG.QuestAutoRemove == 0 ) then
		BQH_CONFIG.QuestAutoRemove = 1;
		setglobal("AUTO_QUEST_WATCH","1");
	else
		BQH_CONFIG.QuestAutoRemove = 0;
	end
end
function BQH_BM_QuestAutoRemoveCheck()
	if ( BQH_CONFIG.QuestAutoRemove == 1 ) then
		return true;
	else
		return false;
	end
end
-------------------------------------------------------------------------------

function BQH_BM_QuestAnnouncePartyClick()
	if ( BQH_CONFIG.QuestAnnounceToParty == 0 ) then
		BQH_CONFIG.QuestAnnounceToParty = 1;
	else
		BQH_CONFIG.QuestAnnounceToParty = 0;
	end
end
function BQH_BM_QuestAnnouncePartyCheck()
	if ( BQH_CONFIG.QuestAnnounceToParty == 1 ) then
		return true;
	else
		return false;
	end
end

-------------------------------------------------------------------------------
-- configure BlinkGUI
-------------------------------------------------------------------------------
function BQH_BlinkGUIRegister()
	if ( not Blink_AddAddon ) then
		return;
	end
	Blink_AddAddon("퀘스트 도우미",BLINK_CATEGORY_QUESTS,{
		{
			["HEADER"] = {
				text = "블링크의 퀘스트 도우미",
			}
		},
		{
			["TEXT"] = {
				text = "퀘스트의 레벨표시, 자동추가/제거 기능, 난이도 표시",
				tooltip = "퀘스트 레벨표시, 자동으로 추가, 제거 기능 및 난이도별 색상 표시 기능, 파티원에게 퀘스트진행상황 알림 기능",
			}
		},
		{
			["CHECKBOX"] = {
				text = "퀘스트 레벨 표시하기",
				tooltip = "퀘스트를 수행할수 있는 적정 레벨을 표시해줍니다.",
				set = function (value)
					if ( value == 1 ) then
						BlinkQuestHelper_ToggleQuestLevel(1);
					else
						BlinkQuestHelper_ToggleQuestLevel(0);
					end
				end,
				get = function ()
					if ( BQH_CONFIG.QuestLevel == 1 ) then
						return 1;
					else
						return nil;
					end
				end,
			},
		},
		{
			["CHECKBOX"] = {
				text = "진행상화 색상 변화하기",
				tooltip = "퀘스트의 진행상황을 색상으로 표시해줍니다.",
				set = function (value)
					if ( value ) then
						BlinkQuestHelper_ToggleQuestWatch(1);
					else
						BlinkQuestHelper_ToggleQuestWatch(0);
					end
				end,
				get = function ()
					if ( BQH_CONFIG.QuestWatch == 1 ) then
						return 1;
					else
						return nil;
					end
				end,
			},
		},
		{
			["CHECKBOX"] = {
				text = "퀘스트 자동으로 추가하기",
				tooltip = "퀘스트 아이템을 얻거나 적을 처치했을때, 자동으로 퀘스트알리미 목록에 추가합니다. 자동으로 추가되는 갯수는 최대 5개입니다.",
				set = function (value)
					if ( value ) then
						BQH_CONFIG.QuestAutoAdd = 1;
					else
						BQH_CONFIG.QuestAutoAdd = 0;
					end
				end,
				get = function ()
					if ( BQH_CONFIG.QuestAutoAdd == 1 ) then
						return 1;
					else
						return nil;
					end
				end,
			},
		},
		{
			["CHECKBOX"] = {
				text = "완료된 퀘스트 자동으로 제거하기",
				tooltip = "퀘스트가 완료되었을때 자동으로 퀘스트알리미 목록에서 제거해줍니다.",
				set = function (value)
					if ( value ) then
						BQH_CONFIG.QuestAutoRemove = 1;
					else
						BQH_CONFIG.QuestAutoRemove = 0;
					end
				end,
				get = function ()
					if ( BQH_CONFIG.QuestAutoRemove == 1 ) then
						return 1;
					else
						return nil;
					end
				end,
			},
		},
		{
			["CHECKBOX"] = {
				text = "퀘스트 진행상황 파티원에게 알려주기",
				tooltip = "퀘스트의 진행상황을 파티원에게 알려줍니다.",
				set = function (value)
					if ( value ) then
						BQH_CONFIG.QuestAnnounceToParty = 1;
					else
						BQH_CONFIG.QuestAnnounceToParty = 0;
					end
				end,
				get = function ()
					if ( BQH_CONFIG.QuestAnnounceToParty == 1 ) then
						return 1;
					else
						return nil;
					end
				end,
			},
		},
--		{
--			["CHECKBOX"] = {
--				indentlevel = 1,
--				text = "퀘스트가 부분적으로 완료되었을때 파티원에게 상세알림",
--				tooltip = "퀘스트가 부분적으로 완료되었을때 파티원에게 상세하게 알려줍니다.",
--				set = function (value)
--					if ( value ) then
--						BQH_CONFIG.QuestDetailAnnounceToParty = 1;
--					else
--						BQH_CONFIG.QuestDetailAnnounceToParty = 0;
--					end
--				end,
--				get = function ()
--					if ( BQH_CONFIG.QuestDetailAnnounceToParty == 1 ) then
--						return 1;
--					else
--						return nil;
--					end
--				end,
--			},
--		},
	})
end
