-------------------------------------------------------------------------------
--
--  Mod Name : Blink's QuestHelper Extend v1.2.1
--  Author   : Blink
--  Modifier : DroArc
--  Date     : 2005/03/28
--  LastUpdate : 2010/05/19
--
-------------------------------------------------------------------------------
local frame
local dropdown
local questLineIndex = 1

-- 추가 정의
local skin = "Interface\\AddOns\\rActionButtonStyler\\media\\gloss.tga"		
local hover = "Interface\\AddOns\\rActionButtonStyler\\media\\hover.tga"	
local pushed = "Interface\\AddOns\\rActionButtonStyler\\media\\pushed.tga"	

local WFContainer = CreateFrame("Frame", "WFContainer", UIParent)
local db, SetSize, MoveWatchFrame, Appearance, FontChanges, line	--, WFO_BF, itembtn
local nextline = 1
local nextbutton = 1
local LSM = LibStub("LibSharedMedia-3.0")
--bqh_OriginalGetQuestText = nil
--bqh_OriginalGetQuestLogQuestText = nil
ori_WatchFrame_Update = nil
local BQH_WATCHFRAME_LINKBUTTONS = {}
local BQH_WATCHFRAME_SETLINES = {}
local BQH_WATCHFRAME_SETLINES_NUMLINES;
--local GetQuestLogTitle = _G.GetQuestLogTitle
local ori_GetQuestLogTitle
local GameTooltip = _G.GameTooltip

local DASH_NONE = 0;
local DASH_SHOW = 1;
local DASH_HIDE = 2;
local DASH_WIDTH;
local IS_HEADER = true;

local tomtomBox = {}
local completeCheckBox = {}

local positions = {
	{ text = "상단", value = "TOP", },
	{ text = "우측상단", value = "TOPRIGHT", },
	{ text = "좌측상단", value = "TOPLEFT", },
	{ text = "하단", value = "BOTTOM", },
	{ text = "우측하단", value = "BOTTOMRIGHT", },
	{ text = "좌측하단", value = "BOTTOMLEFT", },
	{ text = "우측", value = "RIGHT", },
	{ text = "좌측", value = "LEFT", },
	{ text = "정중앙", value = "CENTER", },
}
local fontlist = {
	{ text = "굵은 글꼴", value = "굵은 글꼴", },
	{ text = "기본 글꼴", value = "기본 글꼴", },
	{ text = "데미지 글꼴", value = "데미지 글꼴", },
	{ text = "퀘스트 글꼴", value = "퀘스트 글꼴", },
}
local fontFlags = {
	{ text = "없음", value = "None", },
	{ text = "외곽선", value = "Outline", },
	{ text = "굵은 외곽선", value = "Thick Outline", },
	{ text = "모노크롬", value = "Monochrome", },
}
local borderlist = {
	{ text = "없음", value = "None", },
	{ text = "Blizzard Dialog", value = "Blizzard Dialog", },
	{ text = "Blizzard Dialog Gold", value = "Blizzard Dialog Gold", },
	{ text = "Blizzard Tooltip", value = "Blizzard Tooltip", },
}
local backgroundlist = {
	{ text = "없음", value = "None", },
	{ text = "Blizzard Dialog Background", value = "Blizzard Dialog Background", },
	{ text = "Blizzard Low Health", value = "Blizzard Low Health", },
	{ text = "Blizzard Out of Control", value = "Blizzard Out of Control", },
	{ text = "Blizzard Parchment", value = "Blizzard Parchment", },
	{ text = "Blizzard Parchment 2", value = "Blizzard Parchment 2", },
	{ text = "Blizzard Tabard Background", value = "Blizzard Tabard Background", },
	{ text = "Blizzard Tooltip", value = "Blizzard Tooltip", },
	{ text = "Solid", value = "Solid", },
}
local function playSoundFor(soundPath)
	if ((string.sub(soundPath, -4) == ".wav") or (string.sub(soundPath, -4) == ".mp3")) then
		PlaySoundFile(soundPath)
	else
		PlaySound(soundPath)
	end
end

local Complete_Sound = {
	{ text = "PVPENTERQUEUE", value = "PVPENTERQUEUE", func = function () playSoundFor(this.value) end, },
	{ text = "PVPTHROUGHQUEUE", value = "PVPTHROUGHQUEUE", func = function () playSoundFor(this.value) end, },
	{ text = "GLUECREATECHARACTERBUTTON", value = "GLUECREATECHARACTERBUTTON", func = function () playSoundFor(this.value) end, },
	{ text = "GLUEENTERWORLDBUTTON", value = "GLUEENTERWORLDBUTTON", func = function () playSoundFor(this.value) end, },
	{ text = "QUESTCOMPLETED", value = "QUESTCOMPLETED", func = function () playSoundFor(this.value) end, },
	{ text = "INTERFACESOUND_MONEYFRAMEOPEN", value = "INTERFACESOUND_MONEYFRAMEOPEN", func = function () playSoundFor(this.value) end, },
	{ text = "igPlayerInvite", value = "igPlayerInvite", func = function () playSoundFor(this.value) end, },
	{ text = "LEVELUP", value = "LEVELUP", func = function () playSoundFor(this.value) end, },
	{ text = "QUESTADDED", value = "QUESTADDED", func = function () playSoundFor(this.value) end, },
	{ text = "gsCharacterCreationCreateChar", value = "gsCharacterCreationCreateChar", func = function () playSoundFor(this.value) end, },
	{ text = "TalentScreenOpen", value = "TalentScreenOpen", func = function () playSoundFor(this.value) end, },
	{ text = "ReadyCheck", value = "ReadyCheck", func = function () playSoundFor(this.value) end, },
	{ text = "RaidWarning", value = "RaidWarning", func = function () playSoundFor(this.value) end, },
	{ text = "AuctionWindowOpen", value = "AuctionWindowOpen", func = function () playSoundFor(this.value) end, },
	{ text = "AuctionWindowClose", value = "AuctionWindowClose", func = function () playSoundFor(this.value) end, },
	{ text = "PeonBuildingComplete1", value = "Sound\\Creature\\Peon\\PeonBuildingComplete1.wav", func = function () playSoundFor(this.value) end, },
	{ text = "PeonReady1", value = "Sound\\Creature\\Peon\\PeonReady1.wav", func = function () playSoundFor(this.value) end, },
	{ text = "PeasantReady1", value = "Sound\\Creature\\Peasant\\PeasantReady1.wav", func = function () playSoundFor(this.value) end, },
	{ text = "igPlayerBind", value = "Sound\\Interface\\igPlayerBind.wav", func = function () playSoundFor(this.value) end, },
	{ text = "TEMPEST_Millhouse_Ready01", value = "Sound\\Creature\\MillhouseManastorm\\TEMPEST_Millhouse_Ready01.wav", func = function () playSoundFor(this.value) end, },
	{ text = "TEMPEST_Millhouse_Slay01", value = "Sound\\Creature\\MillhouseManastorm\\TEMPEST_Millhouse_Slay01.wav", func = function () playSoundFor(this.value) end, },
	{ text = "CowDeath", value = "Sound\\Creature\\Cow\\CowDeath.wav", func = function () playSoundFor(this.value) end, },
	{ text = "HumanExploration", value = "Sound\\interface\\HumanExploration.wav", func = function () playSoundFor(this.value) end, },
}

local wideFrame = GetCVar("watchFrameWidth")
-- 추가정의 끝

-- 임무 추적기(Watchframe) 초기값
local defaults = {
	bg = "None",
	border = "None",
	borderWidth = 16,
	inset = 5,
	anchorPoint = "TOPRIGHT",
	xOffset = "-10",
	yOffset = "-215",
	height = 500,
	bgColor = {r = .1, g = .1, b = .1, a = 1},
	borderColor = {r = 1, g = 1, b = 1, a = 1},
	font = "일반 글꼴",
	fontSize = 12,
	fontFlag = "None",
	questSpacing = 10,
	lineSpacing = 4,
	disableShadow = false,
	scale = 0.9,
}
-- 초기값 끝

local function hexToDec(hex)
	if not hex or string.len(hex)~=8 then
		return 1, 1, 1, 1
	end
	local r = hex:sub(1, 2)
	local g = hex:sub(3, 4)
	local b = hex:sub(5, 6)
	local a = hex:sub(7, 8)
	r = tonumber(r, 16) / 255
	g = tonumber(g, 16) / 255
	b = tonumber(b, 16) / 255
	a = tonumber(a, 16) / 255
	return r, g, b, a
end
local function FloatToText(r, g, b, a)
	if ( type (r) == "table" and r.r and r.g and r.b ) then
		r, g, b, a = r.r, r.g, r.b, (r.a or 1.0)
	end
	if ( r > 1 ) then r = 1.0 end
	if ( g > 1 ) then g = 1.0 end
	if ( b > 1 ) then b = 1.0 end
	if ( a > 1 ) then a = 1.0 end
	local newR, newG, newB, newA = math.floor(r * 255), math.floor(g * 255), math.floor(b * 255), math.floor(a * 255)
	local fmt = "%.2x"

	return string.format(fmt, newR )..string.format(fmt, newG )..string.format(fmt, newB )..string.format(fmt, newA )
end

local function print(msg)
	if(ChatFrame1) then
		ChatFrame1:AddMessage(msg, 1.0, 1.0, 0.0)
	end
end

local function load(self)

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

	self:RegisterEvent("UI_INFO_MESSAGE")
	self:RegisterEvent("QUEST_WATCH_UPDATE")
	self:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
	self:RegisterEvent("QUEST_LOG_UPDATE")
	self:RegisterEvent("UPDATE_FACTION")
	self:RegisterEvent("UNIT_QUEST_LOG_CHANGED")
	self:SetScript("OnEvent", BlinkQuestHelper_OnEvent)

	dropdown = CreateFrame("FRAME", "BlinkQuestHelperDropDown", QuestLogFrame, "UIDropDownMenuTemplate")

	BlinkQuestHelper_Init()
	BlinkQuestHelper_ToggleQuestLevel(BQH_CONFIG.QuestLevel)
	BlinkQuestHelper_ToggleQuestWatch(BQH_CONFIG.QuestWatch)
	BlinkQuestHelper_Status()
	BQH_BlinkGUIRegister()

	_G.MAX_QUEST_WATCH_TIME = nil

	DASH_WIDTH = WatchFrame.lineCache:GetFrame().dash:GetWidth()

	-- 기본 퀘스트와치 ui에서 먼저 실행한 link버튼들 전부 해제;
	--[[
	for i = 1, #WATCHFRAME_LINKBUTTONS do
		watchButton = WATCHFRAME_LINKBUTTONS[i];
		watchButton.type = nil
		watchButton.index = nil;
		watchButton:Hide();
		watchButton.frameCache:ReleaseFrame(watchButton);
		WATCHFRAME_LINKBUTTONS[i] = nil;
	end
	]]
	WatchFrame_RemoveObjectiveHandler(WatchFrame_DisplayTrackedQuests)
end

-- from QuestHelper
local function clamp(v)
	if v < 0 then return 0 elseif v > 1.0 then return 1.0 else return v end
end
local function colorlerp(position, r1, g1, b1, r2, g2, b2)
	local antip = 1 - position
	local color = {}
	color.r = clamp(r1 * antip + r2 * position)
	color.g = clamp(g1 * antip + g2 * position)
	color.b = clamp(b1 * antip + b2 * position)
	return color
end

-- We're just gonna do the same thing QH originally did - red->yellow->green.
local function difficulty_color(position)
  if position < 0 then position = 0 end
  if position > 1 then position = 1 end
  return (position < 0.5) and colorlerp(position * 2, 1, 0, 0, 1, 1, 0) or colorlerp(position * 2 - 1, 1, 1, 0, 0, 1, 0)
end

local function _QuestLog_HighlightQuest(questLogTitle)
	local prevParent = QuestLogHighlightFrame:GetParent();
	if ( prevParent and prevParent ~= questLogTitle ) then
		-- set prev quest's colors back to normal
		local prevName = prevParent:GetName();
		prevParent:UnlockHighlight();
		prevParent.tag:SetTextColor(prevParent.r, prevParent.g, prevParent.b);
		prevParent.groupMates:SetTextColor(prevParent.r, prevParent.g, prevParent.b);
	end
	if ( questLogTitle ) then
		local name = questLogTitle:GetName();
		-- highlight the quest's colors
		questLogTitle.tag:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
		questLogTitle.groupMates:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
		questLogTitle:LockHighlight();
		-- reposition highlight frames
		QuestLogHighlightFrame:SetParent(questLogTitle);
		QuestLogHighlightFrame:SetPoint("TOPLEFT", questLogTitle, "TOPLEFT", 0, 0);
		QuestLogHighlightFrame:SetPoint("BOTTOMRIGHT", questLogTitle, "BOTTOMRIGHT", 0, 0);
		QuestLogSkillHighlight:SetVertexColor(questLogTitle.r, questLogTitle.g, questLogTitle.b);
		QuestLogHighlightFrame:Show();
	else
		QuestLogHighlightFrame:Hide();
	end
end

local function _QuestLog_ToggleQuestWatch(questIndex)
	if ( IsQuestWatched(questIndex) ) then
		RemoveQuestWatch(questIndex);
		WatchFrame_Update();
	else
		if ( GetNumQuestWatches() >= MAX_WATCHABLE_QUESTS ) then -- Check this first though it's less likely, otherwise they could make the frame bigger and be disappointed
			UIErrorsFrame:AddMessage(format(QUEST_WATCH_TOO_MANY, MAX_WATCHABLE_QUESTS), 1.0, 0.1, 0.1, 1.0);
			return;
		end
		AddQuestWatch(questIndex);
		WatchFrame_Update();
	end
end

local function getQuestLogIndexByQuestId(questId)
	local numEntries = GetNumQuestLogEntries()
	local qid
	for i=1, numEntries, 1 do
		_, _, _, _, _, _, _, _, qid = GetQuestLogTitle(i)
		if qid == questId then
			return i
		end
	end
end

local function setTootipQuestProgress(tt)
	local t, color
	local fmt = "%.2x"
	if tt then
		for i=1, 30 do
			t = _G[tt:GetName() .. "TextLeft"..i]
			if not t or not t:GetText() then
				break
			end
			color = bqh_GetLeaderboardColor(t:GetText())
			if color then
				t:SetText("|c"
					..string.format(fmt, 255)
					..string.format(fmt, color.r*255 )
					..string.format(fmt, color.g*255 )
					..string.format(fmt, color.b*255 )
					..t:GetText() .. "|r")
			end
		end
	end
end


--[[
block 문제로 사용안함
local function colorizeQuestText(text)
	-- from nQuestLog
	text = gsub(text,"([^%a%d%|])(%d+)([^%a%d%|])", "%1|cffffffff%2|r%3") -- Match numbers
	text = gsub(text,"([^%a%d%|])(%d+)([^%a%d%|])", "%1|cffffffff%2|r%3") -- Match numbers again

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

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

local bqh_watchButtonIndex = 1;
local function bqh_GetLinkButton ()
	local button = BQH_WATCHFRAME_LINKBUTTONS[bqh_watchButtonIndex]
	if ( not button ) then
		BQH_WATCHFRAME_LINKBUTTONS[bqh_watchButtonIndex] = WatchFrame.buttonCache:GetFrame();
		button = BQH_WATCHFRAME_LINKBUTTONS[bqh_watchButtonIndex]
	end
	bqh_watchButtonIndex = bqh_watchButtonIndex + 1
	return button
end

local function bqh_ResetLinkButtons ()
	bqh_watchButtonIndex = 1
end

local function bqh_ReleaseUnusedLinkButtons ()
	local watchButton
	for i = bqh_watchButtonIndex, #BQH_WATCHFRAME_LINKBUTTONS do
		watchButton = BQH_WATCHFRAME_LINKBUTTONS[i]
		watchButton.type = nil
		watchButton.index = nil
		watchButton:Hide()
		watchButton.frameCache:ReleaseFrame(watchButton)
		BQH_WATCHFRAME_LINKBUTTONS[i] = nil
	end
end

local function bqh_GetQuestLine ()
	local line = WATCHFRAME_QUESTLINES[questLineIndex]
	if ( not line ) then
		WATCHFRAME_QUESTLINES[questLineIndex] = WatchFrame.lineCache:GetFrame()
		line = WATCHFRAME_QUESTLINES[questLineIndex]
	end

	line:Reset()
	questLineIndex = questLineIndex + 1
	return line
end

local function bqh_ResetQuestLines ()
	questLineIndex = 1
end

local function bqh_ReleaseUnusedQuestLines ()
	local line
	for i = questLineIndex, #WATCHFRAME_QUESTLINES do
		line = WATCHFRAME_QUESTLINES[i]
		line:Hide()
		line.frameCache:ReleaseFrame(line)
		WATCHFRAME_QUESTLINES[i] = nil
	end
end

local function bqh_buildQuestLevelTag(questLogTitleText, level, questTag, suggestedGroup, isDaily, hideDaily)
	local tag = ""

	if questLogTitleText then
		if questTag == ELITE then
			tag = "["..level.."+"
		elseif questTag == GROUP then
			tag = "["..level.."+"
			if suggestedGroup>0 then
				tag = tag .. suggestedGroup
			end
		elseif questTag == LFG_TYPE_DUNGEON then
			tag = "["..level.."D"
		elseif questTag == RAID then
			tag = "["..level.."R"
		elseif questTag == "전쟁" then -- ? PVP?
			tag = "["..level.."W"
		elseif questTag then
			tag = "["..level..questTag
		else
			tag = "["..level
		end
		if isDaily and not hideDaily then
			tag = tag .. ":" .. DAILY
		end
		tag = tag .. "]"
	end
	return tag
end

function bqh_GetQuestLogTitle(questLogID)
	local questTitle, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID = ori_GetQuestLogTitle(questLogID)
--	if not isHeader and BQH_CONFIG.QuestLevel == 1 and ENABLE_COLORBLIND_MODE ~= "1" then
	if not isHeader and BQH_CONFIG.QuestLevel == 1 then
		local levelTag = bqh_buildQuestLevelTag(questTitle, level, questTag, suggestedGroup, isDaily, true)
		if (questTitle ~= nil) then
			questTitle = levelTag .. " " .. questTitle
		end
	end
	return questTitle, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID
end

function bhq_ToggleWayPoint(questId)

	--[[ 이 함수를 이용해서 c,z를 찾아보자.... 안되네;;
	local mapID, floorNumber = GetQuestWorldMapAreaID(questId)
	]]

	local _, posX, posY, objective = QuestPOIGetIconInfo(questId)
	local numEntries, numQuests = GetNumQuestLogEntries();
	local qtitle, title, level, qid, questIndex, color
	local c, z = GetCurrentMapContinent(), GetCurrentMapZone()
	if ( posX and posY and TomTom) then
		questIndex = 1
		title, level, _, _, _, _, _, _, qid = GetQuestLogTitle(questIndex)
		while qid do
			if questId == qid then
				qtitle = title
				break
			end
			questIndex = questIndex + 1
			title, level, _, _, _, _, _, _, qid = GetQuestLogTitle(questIndex)
		end
		color = bqh_GetQuestDifficultyColor(level)
		if tomtomBox[questId] then
			TomTom:RemoveWaypoint(tomtomBox[questId])
			tomtomBox[questId] = nil
			print(string.format("|cff%02x%02x%02x%s|r: 웨이포인트 제거", color.r*255, color.g*255, color.b*255, (qtitle or "퀘스트")))
			return 1
		else
			tomtomBox[questId] = TomTom:AddZWaypoint(c, z, posX*100, posY*100, string.format("|cff%02x%02x%02x%s|r", color.r*255, color.g*255, color.b*255, (qtitle or "퀘스트")), false)
			print(string.format("|cff%02x%02x%02x%s|r: 웨이포인트 추가", color.r*255, color.g*255, color.b*255, (qtitle or "퀘스트")))
			return 0
		end
	end
	return 0
end

function bqh_GetLeaderboardColor(text)
	local _,_,curcol,maxcol = string.find(text,".+: (%d+)/(%d+)")
	local color = {}

	if not curcol or not maxcol then
		_,_,curcol,maxcol = string.find(text, "(%d+)/(%d+)%s.+")
	end

	if( curcol and maxcol )then
		if curcol == maxcol then
			return {r=0.8, g=0.8, b=0.8}
		end

		local p = curcol / maxcol
		if p > 1 then
			color.r = 0.1
			color.g = 0.8
		elseif p < 0 then
			color.r = 0.8
			color.g = 0.1
		elseif p > .5 then
			color.r = 2.1-p*2
			color.g = 0.8
		else
			color.r = 0.8
			color.g = p*2
		end
		color.b = 0.1
		return color
	end
	return nil
end

function bqh_GetLeaderboardColor_Highlight(color)
	local c = {}
	c.r = color.r * 1.25
	c.g = color.g * 1.25
	c.b = color.b * 1.25
	return c
end


function bqh_GetQuestDifficultyColorByGradation(level)
	local color
	local plevel = UnitLevel("player") -- meh, should probably cache this, buuuuut
	local grayd

	if plevel >= 60 then
		grayd = 9
	elseif plevel >= 40 then
		grayd = plevel / 5 + 1
	else
		grayd = plevel / 10 + 5
	end

	if (plevel - floor(grayd) >= level) then
		color = {r=0.69, g=0.69, b=0.69}
	else
		color = difficulty_color(1 - ((level - plevel) / grayd + 1) / 2)
	end
	return color
end

local bqh_QuestDifficultyColors = {
	["impossible"]		= { r = 1.00, g = 0.10, b = 0.10 };
	["verydifficult"]	= { r = 1.00, g = 0.50, b = 0.25 };
	["difficult"]		= { r = 0.75, g = 0.61, b = 0.00 };
	["standard"]		= { r = 0.25, g = 0.75, b = 0.25 };
	["trivial"]			= { r = 0.50, g = 0.50, b = 0.50 };
	["header"]			= { r = 0.70, g = 0.70, b = 0.70 };
};
function bqh_GetQuestDifficultyColorByStep(level)
	local levelDiff = level - UnitLevel("player");
	local color;
	if ( levelDiff >= 5 ) then
		return bqh_QuestDifficultyColors["impossible"];
	elseif ( levelDiff >= 3 ) then
		return bqh_QuestDifficultyColors["verydifficult"];
	elseif ( levelDiff >= -2 ) then
		return bqh_QuestDifficultyColors["difficult"];
	elseif ( -levelDiff <= GetQuestGreenRange() ) then
		return bqh_QuestDifficultyColors["standard"];
	else
		return bqh_QuestDifficultyColors["trivial"];
	end
end

function bqh_GetQuestDifficultyColor(level)
	if BQH_CONFIG.QuestWatchColorType == 1 then
		return bqh_GetQuestDifficultyColorByStep(level)
	else
		return bqh_GetQuestDifficultyColorByGradation(level)
	end
end
function bqh_WatchFrameLinkButtonTemplate_Highlight(self, onEnter)
	local line;
	for index = self.startLine, self.lastLine do
		line = self.lines[index];
		if self.type == "QUEST" and BQH_CONFIG.QuestWatch == 1 then
			if ( line ) then
				local color
				if ( index == self.startLine ) then
					-- header
					if line.isDaily then
						color = {r=0.3, g=0.5, b=0.9}
					else
						color = bqh_GetQuestDifficultyColor(line.level) -- or UnitLevel("player"))
					end
					if ( onEnter ) then
						color = bqh_GetLeaderboardColor_Highlight(color)
					end
					line.text:SetTextColor(color.r, color.g, color.b);
				else
					color = bqh_GetLeaderboardColor(line.text:GetText())
					if color then
						if ( onEnter ) then
							color = bqh_GetLeaderboardColor_Highlight(color)
						end
						line.text:SetTextColor(color.r, color.g, color.b);
						line.dash:SetTextColor(color.r, color.g, color.b);
					else
						if ( onEnter ) then
							line.text:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
							line.dash:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
						else
							line.text:SetTextColor(0.8, 0.8, 0.8);
							line.dash:SetTextColor(0.8, 0.8, 0.8);
						end
					end
				end
			end
		else
			if ( line ) then
				if ( index == self.startLine ) then
					-- header
					if ( onEnter ) then
						line.text:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
					else
						line.text:SetTextColor(0.75, 0.61, 0);
					end
				else
					if ( onEnter ) then
						line.text:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
						line.dash:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
					else
						line.text:SetTextColor(0.8, 0.8, 0.8);
						line.dash:SetTextColor(0.8, 0.8, 0.8);
					end
				end
			end
		end
	end
end

function bqh_WatchFrame_SetLine(line, anchor, verticalOffset, isHeader, text, dash, hasItem, isComplete, level, isDaily)
	-- anchor
	if ( anchor ) then
		line:SetPoint("TOPRIGHT", anchor, "BOTTOMRIGHT", 0, verticalOffset);
		line:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, verticalOffset);
	end
	line.level = level
	line.isDaily = isDaily

	-- text
	line.text:SetText(text);
	if ( isHeader ) then -- 퀘스트 제목
		BQH_WATCHFRAME_SETLINES_NUMLINES = 0;
		if ( BQH_CONFIG.QuestWatch == 1 ) then
			if isDaily then
				line.text:SetTextColor(0.3, 0.5, 0.9)
			else
				local qtc = bqh_GetQuestDifficultyColor(level)
				line.text:SetTextColor(qtc.r, qtc.g, qtc.b)
			end
		else
			line.text:SetTextColor(0.75, 0.61, 0)
		end
	else
		if not isComplete then -- 완료되지 않은 퀘스트 오브젝트들은 색상을 셋팅해준다.
			local qlc = bqh_GetLeaderboardColor(text)
			text = WatchFrame_ReverseQuestObjective(text)
			if( qlc and BQH_CONFIG.QuestWatch == 1 )then
				if ( dash == DASH_SHOW ) then
					line.dash:SetTextColor(qlc.r, qlc.g, qlc.b)
				end
				line.text:SetTextColor(qlc.r, qlc.g, qlc.b)
			else
				if ( dash == DASH_SHOW ) then
					line.dash:SetTextColor(0.8, 0.8, 0.8)
				end
				line.text:SetTextColor(0.8, 0.8, 0.8)
			end
		else
			if ( dash == DASH_SHOW ) then
				line.dash:SetTextColor(0.8, 0.8, 0.8)
			end
		end
	end
	-- dash
	local usedWidth = 0;
	if ( dash == DASH_SHOW ) then
		line.dash:SetText(QUEST_DASH);
		usedWidth = DASH_WIDTH or 10;
	elseif ( dash == DASH_HIDE ) then
		line.dash:SetText(QUEST_DASH);
		line.dash:Hide();
		usedWidth = DASH_WIDTH or 10;
	end
	-- multiple lines
	if ( hasItem and BQH_WATCHFRAME_SETLINES_NUMLINES < 2 ) then
		usedWidth = usedWidth + WATCHFRAME_ITEM_WIDTH;
	end
	line.text:SetWidth(WATCHFRAME_MAXLINEWIDTH - usedWidth);
	if ( line.text:GetHeight() > WATCHFRAME_LINEHEIGHT ) then
		if ( isComplete ) then
			line:SetHeight(line.text:GetHeight() + 4);
		else
			line:SetHeight(WATCHFRAME_MULTIPLE_LINEHEIGHT);
			line.text:SetHeight(WATCHFRAME_MULTIPLE_LINEHEIGHT);
		end
		BQH_WATCHFRAME_SETLINES_NUMLINES = BQH_WATCHFRAME_SETLINES_NUMLINES + 2;
	else
		BQH_WATCHFRAME_SETLINES_NUMLINES = BQH_WATCHFRAME_SETLINES_NUMLINES + 1;
	end
	tinsert(BQH_WATCHFRAME_SETLINES, line);
end

function bqh_WatchFrameQuestPOI_OnClick(self, button)
	if button == "LeftButton" then
		if ( self.questLogIndex ) then
			if ( not WorldMapFrame:IsShown() ) then
				ToggleFrame(WorldMapFrame);
				WorldMapFrame_SelectQuestFrame(_G["WorldMapQuestFrame"..self.questLogIndex]);
			elseif ( WorldMapQuestScrollChildFrame.selected.index == self.questLogIndex ) then
				ToggleFrame(WorldMapFrame);
			else
				PlaySound("igMainMenuOptionCheckBoxOn");
				WorldMapFrame_SelectQuestFrame(_G["WorldMapQuestFrame"..self.questLogIndex]);
			end
		else
			WorldMap_OpenToQuest(self.questId);
		end
	elseif button == "RightButton" then
		bhq_ToggleWayPoint(self.questId)
	end
end

function bqh_WorldMapQuestPOI_OnClick(self, button)
	if button == "LeftButton" then
		PlaySound("igMainMenuOptionCheckBoxOn");
		if ( self.quest ~= WorldMapQuestScrollChildFrame.selected ) then
			if ( WorldMapQuestScrollChildFrame.selected ) then
				WorldMapBlobFrame:DrawQuestBlob(WorldMapQuestScrollChildFrame.selected.questId, false);
			end
			WorldMapFrame_SelectQuestById(self.questId);
		end
	elseif button == "RightButton" then
		bhq_ToggleWayPoint(self.questId)
	end
end

function bhq_DisplayTrackedQuests(lineFrame, initialOffset, maxHeight, frameWidth)
	local _;
	local questTitle;
	local questIndex;
	local line;
	local lastLine;
	local linkButton;
	local watchItemIndex = 0;
	local numVisible = 0;

	local numPOINumeric = 0;
	local numPOICompleteIn = 0;
	local numPOICompleteOut = 0;

	local text, finished;
	local numQuestWatches = GetNumQuestWatches();
	local numObjectives;
	local title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID;

	local maxWidth = 0;
	local lineWidth = 0;
	local heightUsed = 0;
	local topEdge = 0;

	local playerMoney = GetMoney();
	local selectedQuestId;
	if ( WorldMapFrame and WorldMapFrame:IsShown() ) then
		selectedQuestId = WORLDMAP_SETTINGS.selectedQuestId;
	else
		-- For the filter REMOTE ZONES: when it's unchecked we need to display local POIs only. Unfortunately all the POI
		-- code uses the current map so the tracker would not display the right quests if the world map was windowed and
		-- open to a different zone.
		table.wipe(LOCAL_MAP_QUESTS);
		LOCAL_MAP_QUESTS["zone"] = GetCurrentMapZone();
		for id in pairs(CURRENT_MAP_QUESTS) do
			LOCAL_MAP_QUESTS[id] = true;
		end	
	end
	
	table.wipe(VISIBLE_WATCHES);
	bqh_ResetQuestLines()

	for i = 1, numQuestWatches do
		BQH_WATCHFRAME_SETLINES = table.wipe(BQH_WATCHFRAME_SETLINES or { });
		questIndex = GetQuestIndexForWatch(i);
		if ( questIndex ) then
			title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID = GetQuestLogTitle(questIndex);
			local requiredMoney = GetQuestLogRequiredMoney(questIndex);
			numObjectives = GetNumQuestLeaderBoards(questIndex);
			if ( isComplete and isComplete < 0 ) then
				isComplete = false;
			elseif ( numObjectives == 0 and playerMoney >= requiredMoney ) then
				isComplete = true;		
			end			
			-- check filters
			local filterOK = true;
			if ( isComplete and bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_COMPLETED_QUESTS) ~= WATCHFRAME_FILTER_COMPLETED_QUESTS ) then
				filterOK = false;
			elseif ( bit.band(WATCHFRAME_FILTER_TYPE, WATCHFRAME_FILTER_REMOTE_ZONES) ~= WATCHFRAME_FILTER_REMOTE_ZONES and not LOCAL_MAP_QUESTS[questID] ) then
				filterOK = false;
			end			

			if ( filterOK ) then
				local link, item, charges = GetQuestLogSpecialItemInfo(questIndex);
				if ( requiredMoney > 0 ) then
					WatchFrame.watchMoney = true;	-- for update event			
				end
				questTitle = bqh_GetQuestLine();
				bqh_WatchFrame_SetLine(questTitle, lastLine, -WATCHFRAME_QUEST_OFFSET, IS_HEADER, title, DASH_NONE, item, nil, level, isDaily);
				if ( not lastLine ) then -- First line
					questTitle:SetPoint("TOPRIGHT", lineFrame, "TOPRIGHT", 0, initialOffset);
					questTitle:SetPoint("TOPLEFT", lineFrame, "TOPLEFT", 0, initialOffset);
					topEdge = questTitle:GetTop();
				end
				lastLine = questTitle;

				if ( isComplete ) then
					line = bqh_GetQuestLine();
					line.level = level
					line.isDaily = isDaily
					bqh_WatchFrame_SetLine(line, lastLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, GetQuestLogCompletionText(questIndex), DASH_SHOW, nil, true, level, isDaily);
					lastLine = line;
				else
					for j = 1, numObjectives do
						text, _, finished = GetQuestLogLeaderBoard(j, questIndex);
						if ( not finished ) then
							-- 아래 라인 주석풀면 "- 0/10 내용"으로 바뀜
							text = WatchFrame_ReverseQuestObjective(text);
							line = bqh_GetQuestLine();
							line.level = level
							line.isDaily = isDaily
							bqh_WatchFrame_SetLine(line, lastLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, text, DASH_SHOW, item, nil, level, isDaily);
							lastLine = line;
						end
					end
					if ( requiredMoney > playerMoney ) then
						text = GetMoneyString(playerMoney).." / "..GetMoneyString(requiredMoney);
						line = bqh_GetQuestLine();
						line.level = level
						line.isDaily = isDaily
						bqh_WatchFrame_SetLine(line, lastLine, WATCHFRAMELINES_FONTSPACING, not IS_HEADER, text, DASH_SHOW, item, nil, level, isDaily);
						lastLine = line;
					end
				end

				-- stop processing if there's no room to fit the quest
				local numLines = #BQH_WATCHFRAME_SETLINES;
				local lastBottom = lastLine:GetBottom();
				if ( lastBottom and lastBottom < WatchFrame:GetBottom() ) then
					questLineIndex = questLineIndex - numLines;
					table.wipe(BQH_WATCHFRAME_SETLINES);
					break;
				end

				numVisible = numVisible + 1;
				table.insert(VISIBLE_WATCHES, numVisible, questIndex);		-- save the quest log index because watch order can change after dropdown is opened
				-- turn on quest item
				local itemButton;
				if ( item and not isComplete ) then
					watchItemIndex = watchItemIndex + 1;
					itemButton = _G["WatchFrameItem"..watchItemIndex];
					if ( not itemButton ) then
						WATCHFRAME_NUM_ITEMS = watchItemIndex;
						itemButton = CreateFrame("BUTTON", "WatchFrameItem" .. watchItemIndex, lineFrame, "WatchFrameItemButtonTemplate");
					end
					itemButton:Show();
					itemButton:ClearAllPoints();
					itemButton:SetID(questIndex);
					SetItemButtonTexture(itemButton, item);
					SetItemButtonCount(itemButton, charges);
					itemButton.charges = charges;
					WatchFrameItem_UpdateCooldown(itemButton);
					itemButton.rangeTimer = -1;
					itemButton:SetPoint("TOPRIGHT", questTitle, "TOPRIGHT", 10, -2);
				end
				-- turn on all lines
				for _, line in pairs(BQH_WATCHFRAME_SETLINES) do
					line:Show();
					lineWidth = line.text:GetWidth() + line.dash:GetWidth();
					maxWidth = max(maxWidth, lineWidth);
				end
				-- turn on link button
				linkButton = bqh_GetLinkButton();
				linkButton:SetPoint("TOPLEFT", questTitle);
				linkButton:SetPoint("BOTTOMLEFT", questTitle);
				linkButton:SetPoint("RIGHT", questTitle.text);
				linkButton.type = "QUEST"
				linkButton.index = i; -- We want the Watch index, we'll get the quest index later with GetQuestIndexForWatch(i);
				linkButton.lines = WATCHFRAME_QUESTLINES;
				linkButton.startLine = questLineIndex - numLines;
				linkButton.lastLine = questLineIndex - 1;
				linkButton:Show();
				-- quest POI icon
				if ( WatchFrame.showObjectives ) then
					local poiButton;
					if ( CURRENT_MAP_QUESTS[questID] ) then
						if ( isComplete ) then
							numPOICompleteIn = numPOICompleteIn + 1;
							poiButton = QuestPOI_DisplayButton("WatchFrameLines", QUEST_POI_COMPLETE_IN, numPOICompleteIn, questID);
						else
							numPOINumeric = numPOINumeric + 1;
							poiButton = QuestPOI_DisplayButton("WatchFrameLines", QUEST_POI_NUMERIC, numPOINumeric, questID);
						end
					elseif ( isComplete ) then
						numPOICompleteOut = numPOICompleteOut + 1;
						poiButton = QuestPOI_DisplayButton("WatchFrameLines", QUEST_POI_COMPLETE_OUT, numPOICompleteOut, questID);
					end
					if ( poiButton ) then
						poiButton:SetPoint("TOPRIGHT", questTitle, "TOPLEFT", 0, 5);
						poiButton.questLogIndex = CURRENT_MAP_QUESTS[questID];
					end
				end

				if ( lastBottom ) then
					heightUsed = topEdge - lastLine:GetBottom();
				else
					heightUsed = 1;
				end
			end
		end
	end

	for i = watchItemIndex + 1, WATCHFRAME_NUM_ITEMS do
		_G["WatchFrameItem" .. i]:Hide();
	end
	QuestPOI_HideButtons("WatchFrameLines", QUEST_POI_NUMERIC, numPOINumeric + 1);
	QuestPOI_HideButtons("WatchFrameLines", QUEST_POI_COMPLETE_IN, numPOICompleteIn + 1);
	QuestPOI_HideButtons("WatchFrameLines", QUEST_POI_COMPLETE_OUT, numPOICompleteOut + 1);

	bqh_ReleaseUnusedQuestLines()

	if ( selectedQuestId ) then
		QuestPOI_SelectButtonByQuestId("WatchFrameLines", selectedQuestId, true);	
	end

	return heightUsed, maxWidth, numQuestWatches
end

function bqh_WatchFrame_Update (self)
	--ori_WatchFrame_Update(self)

	self = self or WatchFrame; -- Speeds things up if we pass in this reference when we can conveniently.

	-- Display things in this order: quest timers, achievements, quests, addon subscriptions.
	if ( self.updating ) then
		return;
	end

	self.updating = true;

	local pixelsUsed = 0;
	local totalOffset = self.nextOffset or WATCHFRAME_INITIAL_OFFSET;
	local lineFrame = WatchFrameLines;
	local maxHeight = (WatchFrame:GetTop() - WatchFrame:GetBottom()); -- Can't use lineFrame:GetHeight() because it could be an invalid rectangle (width of 0)

	local maxFrameWidth = WATCHFRAME_MAXLINEWIDTH;
	local maxWidth = 0;
	local maxLineWidth;
	local numObjectives;
	local totalObjectives = 0;

	bqh_ResetLinkButtons();

	pixelsUsed, maxLineWidth, numObjectives = bhq_DisplayTrackedQuests(lineFrame, totalOffset, maxHeight, maxFrameWidth)
	maxWidth = max(maxLineWidth, maxWidth);
	totalObjectives = totalObjectives + numObjectives

	if ( pixelsUsed > 0 ) then
		totalOffset = totalOffset - WATCHFRAME_TYPE_OFFSET - pixelsUsed;
	end
	--disabled for now, might make it an option
	--lineFrame:SetWidth(min(maxWidth, maxFrameWidth));

	if ( totalObjectives > 0 ) then
		WatchFrameHeader:Show();
		WatchFrameCollapseExpandButton:Show();
		WatchFrameTitle:SetText(OBJECTIVES_TRACKER_LABEL.." ("..totalObjectives..")");
		WatchFrameHeader:SetWidth(WatchFrameTitle:GetWidth() + 4);
		-- visible objectives?
		if ( totalOffset < WATCHFRAME_INITIAL_OFFSET ) then
			if ( self.collapsed and not self.userCollapsed ) then
				WatchFrame_Expand(self);
			end
			WatchFrameCollapseExpandButton:Enable();
		else
			if ( not self.collapsed ) then
				WatchFrame_Collapse(self);
			end
			WatchFrameCollapseExpandButton:Disable();		
		end		
	else
		WatchFrameHeader:Hide();
		WatchFrameCollapseExpandButton:Hide();
	end

--	if ( totalOffset < WATCHFRAME_INITIAL_OFFSET ) then
--		WatchFrameTitle:Show();
--		WatchFrameCollapseExpandButton:Show();
--	else
--		WatchFrameTitle:Hide();
--		WatchFrameCollapseExpandButton:Hide();
--	end

	bqh_ReleaseUnusedLinkButtons();

	self.updating = nil;
	self.nextOffset = totalOffset;

	-- 제외된 퀘스트중 tomtom에 있던거는 뺀다;
	local title, color, level, questIndex, questLogIndex
	local numQuestWatches = GetNumQuestWatches()
	local ta = {}
	for qid, ttuid in pairs(tomtomBox) do
		questLogIndex = getQuestLogIndexByQuestId(qid)
		if questLogIndex then
			ta[questLogIndex] = qid
		end
	end
	for i=1, numQuestWatches, 1 do
		questIndex = GetQuestIndexForWatch(i)
		if questIndex then
			ta[questIndex] = nil
		end
	end
	for k, v in pairs(ta) do
		title, level = GetQuestLogTitle(k)
		color = bqh_GetQuestDifficultyColor(level)
		TomTom:RemoveWaypoint(tomtomBox[v])
		if tomtomBox[v] then
			tomtomBox[v] = nil
			print(string.format("|cff%02x%02x%02x%s|r: 웨이포인트 제거", color.r*255, color.g*255, color.b*255, (title or "퀘스트")))
		end
	end
end


function BlinkQuestHelper_Init()
	if not BQH_CONFIG then
		BQH_CONFIG = {}
	end
	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.QuestCompleteSound then
		BQH_CONFIG.QuestCompleteSound = 0
	end
	if not BQH_CONFIG.QuestCompleteSoundFile then
		BQH_CONFIG.QuestCompleteSoundFile = "igPlayerInvite"
	end
--	if not BQH_CONFIG.QuestDetailAnnounceToParty then
--		BQH_CONFIG.QuestDetailAnnounceToParty = 0
--	end
	if ( BQH_CONFIG.QuestAutoAdd == 1 ) then
		setglobal("AUTO_QUEST_WATCH","1")
	end
	if not BQH_CONFIG.QuestWatchColorType then
		BQH_CONFIG.QuestWatchColorType = 1
	end

	-- hack
	_G.WATCHFRAME_MAXLINEWIDTH = 202
	_G.WATCHFRAME_QUEST_OFFSET = 0

	-- hooks
	hooksecurefunc("WatchFrame_Update", bqh_WatchFrame_Update)

	--ori_WatchFrame_Update = WatchFrame_Update
	--WatchFrame_Update = bqh_WatchFrame_Update
	--QuestLog_Update = bqh_QuestLog_Update
	--QuestLogScrollFrame.update = QuestLog_Update
	QuestLogTitleButton_OnClick = bqh_QuestLogTitleButton_OnClick
	WatchFrameLinkButtonTemplate_Highlight = bqh_WatchFrameLinkButtonTemplate_Highlight
	ori_GetQuestLogTitle = GetQuestLogTitle
	GetQuestLogTitle = bqh_GetQuestLogTitle
	--[[
	bqh_OriginalGetQuestText = GetQuestText
	GetQuestText = bqh_GetQuestText
	bqh_OriginalGetQuestLogQuestText = GetQuestLogQuestText
	GetQuestLogQuestText = bqh_GetQuestLogQuestText
	]]

	if QuestPOI_DisplayButton and TomTom then
		hooksecurefunc("QuestPOI_DisplayButton", function (parentName, buttonType, buttonIndex, questId) 
			local buttonName = "poi"..parentName..buttonType.."_"..buttonIndex
			local poiButton = _G[buttonName]
			
			if poiButton then
				poiButton:RegisterForClicks("LeftButtonUp", "RightButtonUp")
				if buttonType == QUEST_POI_COMPLETE_SWAP and QUEST_POI_SWAP_BUTTONS[parentName] then
					QUEST_POI_SWAP_BUTTONS[parentName].questId = questId
					QUEST_POI_SWAP_BUTTONS[parentName]:RegisterForClicks("LeftButtonUp", "RightButtonUp")
				end
			end
			return poiButton
		end)
		WatchFrameQuestPOI_OnClick = bqh_WatchFrameQuestPOI_OnClick
		WorldMapQuestPOI_OnClick = bqh_WorldMapQuestPOI_OnClick
	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()
	WatchFrame_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()
	WatchFrame_Update()
end

function BlinkQuestHelper_ToggleQuestWatchColorType(toggle)
	if( toggle == 1 )then
		BQH_CONFIG.QuestWatchColorType = 1
	elseif( toggle == 0 )then
		BQH_CONFIG.QuestWatchColorType = 0
	else
		if( BQH_CONFIG.QuestWatchColorType ~= 1 )then
			BQH_CONFIG.QuestWatchColorType = 1
		else
			BQH_CONFIG.QuestWatchColorType = 0
		end
	end
	QuestLog_Update()
	WatchFrame_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
			print("퀘스트목록에 레벨을 표시합니다.")
		else
			print("퀘스트목록에 레벨을 표시하지 않습니다.")
		end
		return
	elseif( cmd == "색상" )then
		BlinkQuestHelper_ToggleQuestWatch()
		if( BQH_CONFIG.QuestWatch == 1 )then
			print("퀘스트도우미의 진행상황을 색상으로 표시해줍니다.")
		else
			print("퀘스트도우미를 원래 기능으로 되돌립니다.")
		end
		return
	elseif( cmd == "색상타입" )then
		if BQH_CONFIG.QuestWatch == 1 then
			BlinkQuestHelper_ToggleQuestWatchColorType()
			if( BQH_CONFIG.QuestWatchColorType == 1 )then
				print("퀘스트도우미의 진행상황을 색상을 난이도별로 표시합니다.")
				print(" - |cff7f7f7f회색|r: 저레벨")
				print(" - |cff3fbf3f녹색|r: 보통")
				print(" - |cffbf9b00노란색|r: 어려움")
				print(" - |cffff7f3f주황색|r: 매우 어려움")
				print(" - |cffff1919빨간색|r: 불가능")
			else
				print("퀘스트도우미의 진행상황을 색상을 자연스럽게 표시합니다.")
			end
		else
			print("퀘스트도우미의 진행상황을 색상으로 표시기능을 먼저 활성화하십시오.")
		end
		return
	elseif( cmd == "자동제거" )then
		if( BQH_CONFIG.QuestAutoRemove == 0 )then
			print("퀘스트도우미에 등록된 퀘스트중 완료된 퀘스트는 자동으로 제거합니다.")
			BQH_CONFIG.QuestAutoRemove = 1
		else
			print("퀘스트가 완료되도 퀘스트도우미 리스트에서 자동으로 제거하지 않습니다.")
			BQH_CONFIG.QuestAutoRemove = 0
		end
		return
	elseif( cmd == "자동추가" )then
		if( BQH_CONFIG.QuestAutoAdd == 0 )then
			print("퀘스트아이템을 얻으면 퀘스트도우미에 자동으로 추가합니다.")
			BQH_CONFIG.QuestAutoAdd = 1
			setglobal("AUTO_QUEST_WATCH","1")
		else
			print("퀘스트도우미에 수동으로 추가해야합니다.-_-")
			BQH_CONFIG.QuestAutoAdd = 0
			setglobal("AUTO_QUEST_WATCH","0")
		end
		return
	elseif( cmd == "파티알림" )then
		if( BQH_CONFIG.QuestAnnounceToParty == 0 )then
			print("퀘스트아이템을 얻으면 파티원에게 알려줍니다.")
			BQH_CONFIG.QuestAnnounceToParty = 1
		else
			print("파티원에게 알리지않습니다.")
			BQH_CONFIG.QuestAnnounceToParty = 0
		end
		return
	--[[
	elseif( cmd == "파티상세알림" )then
		if( BQH_CONFIG.QuestDetailAnnounceToParty == 0 )then
			print("퀘스트가 부분적으로 완료되었을때 파티원에게 상세하게 알려줍니다.")
			BQH_CONFIG.QuestDetailAnnounceToParty = 1
		else
			print("파티원에게 자세히~_~ 알리지않습니다.")
			BQH_CONFIG.QuestDetailAnnounceToParty = 0
		end
		return
	]]
	elseif( cmd == "설정보기" or cmd == "?" )then
		BlinkQuestHelper_Status()
		return
	end
	BlinkQuestHelper_Usage()
end

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

function BlinkQuestHelper_Status()
	print("퀘스트도우미 설정상태:")
	if( BQH_CONFIG.QuestLevel == 1 )then
		print("  퀘스트레벨표시 : |cff00ff00켜짐|r")
	else
		print("  퀘스트레벨표시 : |cffff0000꺼짐|r")
	end
	if( BQH_CONFIG.QuestWatch == 1 )then
		print("  퀘스트도우미 색상표시 : |cff00ff00켜짐|r")
		if BQH_CONFIG.QuestWatchColorType == 1 then
			print("  퀘스트도우미 색상타입 : |cff00ff00단계적으로 변화|r")
		else
			print("  퀘스트도우미 색상타입 : |cff00ff00부드럽게 변화|r")
		end
	else
		print("  퀘스트도우미 색상표시 : |cffff0000꺼짐|r")
	end
	if( BQH_CONFIG.QuestAutoAdd == 1 )then
		print("  퀘스트도우미 자동추가 : |cff00ff00켜짐|r")
	else
		print("  퀘스트도우미 자동추가 : |cffff0000꺼짐|r")
	end
	if( BQH_CONFIG.QuestAutoRemove == 1 )then
		print("  퀘스트도우미 자동제거 : |cff00ff00켜짐|r")
	else
		print("  퀘스트도우미 자동제거 : |cffff0000꺼짐|r")
	end
	if( BQH_CONFIG.QuestAnnounceToParty == 1 )then
		print("  퀘스트도우미 파티알림 : |cff00ff00켜짐|r")
	else
		print("  퀘스트도우미 파티알림 : |cffff0000꺼짐|r")
	end
--	if( BQH_CONFIG.QuestDetailAnnounceToParty == 1 )then
--		print("  퀘스트도우미 파티상세알림 : |cff00ff00켜짐|r")
--	else
--		print("  퀘스트도우미 파티상세알림 : |cffff0000꺼짐|r")
--	end
end

function BlinkQuestHelper_QuestCompleteCheck()
	for questIndex, _ in pairs(completeCheckBox) do
		local questLogTitleText, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID = GetQuestLogTitle(questIndex)
		if isComplete and isComplete > 0 then
			local qlink = GetQuestLink(questIndex);
			print(qlink .. " 퀘스트 완료")
			if BQH_CONFIG.QuestCompleteSound == 1 then
				playSoundFor(BQH_CONFIG.QuestCompleteSoundFile)
			end
			completeCheckBox[questIndex] = nil
		end
	end
end

function BlinkQuestHelper_QuestCompleteAnnounce(msg)
	local questIndex = BlinkQuestHelper_FindQuestIndexByUIMessage(msg)
	if questIndex then
		local questLogTitleText, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID = GetQuestLogTitle(questIndex)
		local _, _, a, b = msg:find(".+: (%d+)/(%d+)")
		if a and b and a == b then
			completeCheckBox[questIndex] = 1
		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 WatchFrame_Update() end
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, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID = GetQuestLogTitle(updatedIndex)
			if( questLogTitleText )then

				questLogTitleText = strtrim(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_Notice(questTitle, questIndex, chat, who)
	local questTitle, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID = GetQuestLogTitle(questIndex)
	local questString = {}
	local title = GetQuestLink(questIndex)
	local numObjectives = GetNumQuestLeaderBoards(questIndex)
	local complete = ""

	if ( isComplete and isComplete < 0 ) then
		complete = " - ("..FAILED..")"
	elseif ( isComplete and isComplete > 0 ) then
		complete = " - ("..COMPLETE..")"
	end
	if ( isDaily ) then
		if ( questTag ) then
			questTag = format(DAILY_QUEST_TAG_TEMPLATE, questTag)
		else
			questTag = DAILY
		end
	end

	title = title .. complete

	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_ShowDropdown(questTitle,questIndex)
	HideDropDownMenu(1)
	if ( questIndex ) then
		UIDropDownMenu_Initialize(dropdown, 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, dropdown, "cursor")
	end
end

--[[
block 문제로 사용안함
function bqh_GetQuestText()
	local text = bqh_OriginalGetQuestText()
	return colorizeQuestText(text)
end

function bqh_GetQuestLogQuestText()
	questDescription, questObjectives = bqh_OriginalGetQuestLogQuestText()
	questObjectives = colorizeQuestText(questObjectives)
	questDescription = colorizeQuestText(questDescription)
	return questDescription, questObjectives
end
]]

function bqh_QuestLogTitleButton_OnClick(self, button)
	local questName = self:GetText()
	local questIndex = self:GetID()
	if ( button == "LeftButton" ) then
		if ( IsModifiedClick() ) then
			-- If header then return
			if ( self.isHeader ) then
				return
			end
			-- Otherwise try to track it or put it into chat
			if ( IsModifiedClick("CHATLINK") and ChatFrameEditBox:IsVisible() ) then
				local questLink = GetQuestLink(questIndex);
				if ( questLink ) then
					ChatEdit_InsertLink(questLink);
				end
				QuestLog_SetSelection(questIndex);
				return
			elseif ( IsModifiedClick("QUESTWATCHTOGGLE") ) then
				_QuestLog_ToggleQuestWatch(questIndex);
				QuestLog_SetSelection(questIndex);
				QuestLog_Update();
			elseif IsModifiedClick("BQHANNOUNCEQUEST") then
				local questTitle, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID = GetQuestLogTitle(questIndex)
				local questString = {}
				local title = GetQuestLink(questIndex)
				local numObjectives = GetNumQuestLeaderBoards(questIndex)
				local complete = ""

				if ( isComplete and isComplete < 0 ) then
					complete = " - ("..FAILED..")"
				elseif ( isComplete and isComplete > 0 ) then
					complete = " - ("..COMPLETE..")"
				end
				if ( isDaily ) then
					if ( questTag ) then
						questTag = format(DAILY_QUEST_TAG_TEMPLATE, questTag)
					else
						questTag = DAILY
					end
				end

				title = title .. complete

				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
		end
	else
		BlinkQuestHelper_ShowDropdown(self,questIndex)
	end

	QuestLog_SetSelection(questIndex)
	--QuestLog_Update()
end

--[[ 사용안함
function bqh_QuestLog_Update()
	if ( not QuestLogFrame:IsShown() ) then
		return;
	end

	local numEntries, numQuests = GetNumQuestLogEntries();
	if ( numEntries == 0 ) then
		HideUIPanel(QuestLogDetailFrame);
		QuestLogDetailFrame.timeLeft = nil;
		EmptyQuestLogFrame:Show();
		QuestLog_SetSelection(0);
	else
		EmptyQuestLogFrame:Hide();
	end

	QuestLog_UpdateMapButton();

	-- Update Quest Count
	QuestLog_UpdateQuestCount(numQuests);

	-- If no selection then set it to the first available quest
	local questLogSelection = GetQuestLogSelection();
	local haveSelection = questLogSelection ~= 0;
	if ( numQuests > 0 and not haveSelection ) then
		if ( QuestLogFrame.selectedIndex ) then
			QuestLog_SetNearestValidSelection();
		else
			QuestLog_SetFirstValidSelection();
		end
		questLogSelection = GetQuestLogSelection();
	end
	QuestLogFrame.selectedIndex = questLogSelection;

    --The counts may have changed with SetNearestValidSelection expanding quest headers.
    --Bug ID 170644
    numEntries, numQuests = GetNumQuestLogEntries();

	-- hide the details if we don't have a selected quest
	if ( not haveSelection ) then
		HideUIPanel(QuestLogDetailFrame);
	end

	-- update the group timer
	local haveGroup = GetNumPartyMembers() > 0 or GetNumRaidMembers() > 1;
	if ( haveGroup ) then
		QuestLogFrame.groupUpdateTimer = 0;
	else
		QuestLogFrame.groupUpdateTimer = nil;
	end

	-- hide the highlight frame initially, it may be shown when we loop through the quest listing if a quest is selected
	QuestLogHighlightFrame:Hide();

	-- Update the quest listing
	local buttons = QuestLogScrollFrame.buttons;
	local numButtons = #buttons;
	local scrollOffset = HybridScrollFrame_GetOffset(QuestLogScrollFrame);
	local buttonHeight = buttons[1]:GetHeight();
	local displayedHeight = 0;

	local numPartyMembers = GetNumPartyMembers();
	local questIndex, questLogTitle, questTitleTag, questNumGroupMates, questNormalText, questCheck;
	local title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily;
	local color;
	local partyMembersOnQuest, tempWidth, textWidth;
	for i=1, numButtons do
		questLogTitle = buttons[i];
		questIndex = i + scrollOffset;
		questLogTitle:SetID(questIndex);
		questTitleTag = questLogTitle.tag;
		questNumGroupMates = questLogTitle.groupMates;
		questCheck = questLogTitle.check;
		questNormalText = questLogTitle.normalText;
		if ( questIndex <= numEntries ) then
			title, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID = GetQuestLogTitle(questIndex);

			if ( isHeader ) then
				-- set the title
				if ( title ) then
					questLogTitle:SetText(title);
				else
					questLogTitle:SetText("");
				end

				-- set the normal texture based on the header's collapsed state
				if ( isCollapsed ) then
					questLogTitle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up");
				else
					questLogTitle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up");
				end
				questLogTitle:SetHighlightTexture("Interface\\Buttons\\UI-PlusButton-Hilight");

				questNumGroupMates:Hide();
				questTitleTag:Hide();
				questCheck:Hide();
			else
				-- set the title
				if (questID and displayQuestID) then
					questLogTitle:SetText("  "..questID.." - "..title);
				else
					questLogTitle:SetText("  "..title);
				end

				-- this isn't a header, hide the header textures
				questLogTitle:SetNormalTexture("");
				questLogTitle:SetHighlightTexture("");

				-- If not a header see if any nearby group mates are on this quest
				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.."]");
					questNumGroupMates:Show();
				else
					questNumGroupMates:Hide();
				end

				-- figure out which tag to show, if any
				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..")");
					questTitleTag:Show();
				else
					questTitleTag:Hide();
				end

				-- show the quest check if the quest is being watched
				if ( IsQuestWatched(questIndex) ) then
					questCheck:Show();
				else
					questCheck:Hide();
				end
			end

			-- Save if its a header or not
			questLogTitle.isHeader = isHeader;

			-- resize the title button so everything fits where it's supposed to
			QuestLogTitleButton_Resize(questLogTitle);

			-- Color the quest title and highlight according to the difficulty level
			if ( isHeader ) then
				color = QuestDifficultyColors["header"];
			else
				color = GetQuestDifficultyColor(level);
			end
			questTitleTag:SetTextColor(color.r, color.g, color.b);
			questLogTitle:SetNormalFontObject(color.font);
			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 ( questLogSelection == questIndex ) then
				_QuestLog_HighlightQuest(questLogTitle);
			else
				questLogTitle:UnlockHighlight();
			end
		else
			questLogTitle:Hide();
		end
		displayedHeight = displayedHeight + buttonHeight;
	end
	HybridScrollFrame_Update(QuestLogScrollFrame, numEntries * buttonHeight, displayedHeight);

	-- update the control panel
	QuestLogControlPanel_UpdateState();
end
]]

-------------------------------------------------------------------------------
-- configure BlinkGUI
-------------------------------------------------------------------------------
function BQH_BlinkGUIRegister()
	if _G.BlinkConfig then
		_G.BlinkConfig:RegisterOptions{
			name = "블링크 퀘스트 도우미",
			type = "root",
			command = {"퀘도우미설정","qhelperconfig"},
			options = {
				{
					type = "description",
					text = "블링크의 퀘스트 도우미 익스텐드",
					fontobject = "QuestTitleFont",
					r = 1,
					g = 0.82,
					b = 0,
					justifyH = "LEFT",
				},
				{
					type = "description",
					text = "퀘스트 레벨표시, 자동으로 추가, 제거 기능 및 난이도별 색상 표시 기능, 파티원에게 퀘스트진행상황 알림 기능\n",
					fontobject = "ChatFontNormal",
					justifyH = "LEFT",
					justifyV = "TOP",
				},
				{
					type = "description",
					text = "원 제작자 : 블링크\n수정자 : 드로아크",
					fontobject = "ChatFontNormal",
					justifyH = "CENTER",
					justifyV = "TOP",
				},
			},
			-- 하위메뉴 시작
			children = 
			{
				{ 
					type = "root",
					name = "기본 기능 설정",
					command = {"기본기능 설정","qhelperconfig"},
					-- 옵션 시작
					options = {
						-- 제목
						{
							type = "description",
							text = "기본 기능 설정",
							fontobject = "QuestTitleFont",
							r = 1,
							g = 0.82,
							b = 0,
							justifyH = "LEFT",
						},
						-- 주석
						{
							type = "description",
							text = "퀘스트 레벨표시, 자동으로 추가, 제거 기능 및 난이도별 색상 표시 기능, 파티원에게 퀘스트진행상황 알림 기능",
							fontobject = "ChatFontNormal",
							justifyH = "LEFT",
							justifyV = "TOP",
						},
						-- 퀘스트 레벨 표시하기
						{
							type = "toggle",
							text = "퀘스트 레벨 표시하기",
							tooltip = "퀘스트를 수행할수 있는 적정 레벨을 표시해줍니다.",
							get = function ()
								return BQH_CONFIG.QuestLevel == 1
							end,
							set = function (value)
							if value then
									BlinkQuestHelper_ToggleQuestLevel(1)
								else
									BlinkQuestHelper_ToggleQuestLevel(0)
								end
							end,
						},
						-- 퀘스트 자동으로 추가하기
					{
							type = "toggle",
							text = "퀘스트 자동으로 추가하기",
							tooltip = "퀘스트 아이템을 얻거나 적을 처치했을때, 자동으로 퀘스트알리미 목록에 추가합니다. 자동으로 추가되는 갯수는 최대 5개입니다.",
							get = function ()
								return BQH_CONFIG.QuestAutoAdd == 1
							end,
							set = function (value)
								if value then
									BQH_CONFIG.QuestAutoAdd = 1
								else
									BQH_CONFIG.QuestAutoAdd = 0
								end
							end,
						},
						-- 완료된 퀘스트 자동으로 제거하기
						{
							type = "toggle",
						text = "완료된 퀘스트 자동으로 제거하기",
						tooltip = "퀘스트가 완료되었을때 자동으로 퀘스트알리미 목록에서 제거해줍니다.",
							get = function ()
								return BQH_CONFIG.QuestAutoRemove == 1
							end,
							set = function (value)
								if value then
									BQH_CONFIG.QuestAutoRemove = 1
								else
									BQH_CONFIG.QuestAutoRemove = 0
								end
							end,
						},
						-- 퀘스트 진행상황 파티원에게 알려주기
						{
							type = "toggle",
							text = "퀘스트 진행상황 파티원에게 알려주기",
							tooltip = "퀘스트의 진행상황을 파티원에게 알려줍니다.",
							get = function ()
								return BQH_CONFIG.QuestAnnounceToParty == 1
							end,
							set = function (value)
								if value then
									BQH_CONFIG.QuestAnnounceToParty = 1
								else
									BQH_CONFIG.QuestAnnounceToParty = 0
								end
							end,
						},
						-- 퀘스트 완료시 소리 알림
						{
							type = "toggle",
							text = "퀘스트 완료시 소리 알림",
							tooltip = "퀘스트 완료시에 소리로 알려줍니다.",
							get = function ()
								return BQH_CONFIG.QuestCompleteSound == 1
							end,
							set = function (value)
								if value then
									BQH_CONFIG.QuestCompleteSound = 1
								else
									BQH_CONFIG.QuestCompleteSound = 0
								end
							end,
							needRefresh = true,
						},
						{
							type = "select",
							text = "퀘스트 완료 소리 선택",
							tooltip = "퀘스트 완료시 들려줄 소리를 선택합니다.",
							values = Complete_Sound,
							get = function()
								return BQH_CONFIG.QuestCompleteSoundFile
							end,
							set = function(value)
								BQH_CONFIG.QuestCompleteSoundFile = value
							end,
							disable = function ()
								return BQH_CONFIG.QuestCompleteSound ~= 1
							end,
						},
						-- 진행상황 색상 변화하기
						{
							type = "toggle",
							text = "진행상황 색상 변화하기",
							tooltip = "퀘스트의 진행상황을 색상으로 표시해줍니다.",
							get = function ()
								return BQH_CONFIG.QuestWatch == 1
							end,
							set = function (value)
								if value then
									BlinkQuestHelper_ToggleQuestWatch(1)
								else
									BlinkQuestHelper_ToggleQuestWatch(0)
								end
							end,
							needRefresh = true,
						},
						-- 진행상황 색상 변화 타입
						{
							type = "radio",
							text = "진행상황 색상 변화 타입",
							values = {
								{text = "단계적으로 변화", value = 1},
								{text = "부드럽게 변화", value = 0},
							},

							get = function ()
								return BQH_CONFIG.QuestWatchColorType and BQH_CONFIG.QuestWatchColorType or 1
							end,
							set = function (value)
								BQH_CONFIG.QuestWatchColorType = value
								BlinkQuestHelper_ToggleQuestWatchColorType(value)
							end,
							col = 2,
							disable = function ()
								return BQH_CONFIG.QuestWatch ~= 1
							end,
						},
					},
					-- 옵션 끝
				},
				{
					type = "root",
					name = "추적기 - 크기와 위치",
					fontobject = "QuestTitleFont",
					-- 옵션 시작
					options = 
					{
						{
							type = "description",
							text = "추적기 - 크기와 위치",
							fontobject = "QuestTitleFont",
							r = 1,
							g = 0.82,
							b = 0,
							justifyH = "LEFT",
						},
						{
							type = "description",
							text = "임무 추적기의 크기와 길이 그리고 위치를 설정합니다.\n",
							fontobject = "ChatFontNormal",
							justifyH = "LEFT",
							justifyV = "TOP",
						},
						{
							type = "group",
							text = "크기 비율과 길이",
							fontobject = "ChatFontNormal",
							r = 0,
							g = 0.82,
							b = 0.5,
							options = 
							{
								{
									type = "range",
									text = "크기 비율",
									tooltip = "추적기 프레임의 크기를 비율 단위로 설정합니다.",
									min = .5,
									max = 2,
									step = .05,
									get = function() return db.scale end,
									set = function(value) 
											db.scale = value
											SetSize()
									end,
								},
								{
									text = "프레임 길이",
									tooltip = "추적기 프레임의 최대 길이 값을 설정합니다. 해당 길이 이상 넘어가는 퀘스트는 화면에 보이지 않습니다.",
									type = "range",
									min = 200,
									max = 1000,
									step = 5,
									get = function() return db.height end,
									set = function(value)
											db.height = value
											SetSize()
										end,
								},
							},
						},
						{
							type = "description",
							text = "",
						},
						{
							type = "group",
							text = "위치 기준과 좌표",
							fontobject = "ChatFontNormal",
							options = 
							{
								{
									type = "select",
									text = "확장 기준",
									tooltip = "추적기 프레임의 확장 및 축소에 대한 기준 방향을 설정합니다.",
									needRefresh = true,
									values = positions,
									get = function()
											for k, v in pairs(positions) do
												if db.anchorPoint == positions[k].value then
													return k
												end
												
											end
										end,
									set = function(value)
											db.anchorPoint = value
												db.xOffset = "0"
												db.yOffset = "0"
											MoveWatchFrame()
										end,
								},
								{
									text = "X 단차",
									tooltip = "추적기 프레임의 좌/우 위치 값을 설정합니다.",
									type = "string",
									get = function() return db.xOffset end,
									set = function(value)
											if value == nil or value == "" then
												value = "0"
											end
											db.xOffset = value
											MoveWatchFrame()
										end,
								},
								{
									text = "Y 단차",
									tooltip = "추적기 프레임의 위/아래 위치 값을 설정합니다.",
									type = "string",
									get = function() return db.yOffset end,
									set = function(value)
											if value == nil or value == "" then
												value = "0"
											end
											db.yOffset = value
											MoveWatchFrame()
										end,
								},
							},
						},
					},
				},
				{
					type = "root",
					name = "추적기 - 글꼴 설정",
					fontobject = "QuestTitleFont",
					options = 
					{
						{
							type = "description",
							text = "추적기 - 글꼴 설정",
							fontobject = "QuestTitleFont",
							r = 1,
							g = 0.82,
							b = 0,
							justifyH = "LEFT",
						},
						{
							type = "description",
							text = "임무 추적기의 글꼴 크기와 모양을 설정합니다.\n",
							fontobject = "ChatFontNormal",
							justifyH = "LEFT",
							justifyV = "TOP",
						},
						{
							type = "group",
							text = "글꼴 종류와 크기",
							fontobject = "ChatFontNormal",
							r = 0,
							g = 0.82,
							b = 0.5,
							options = 
							{
								{
									text = "글꼴",
									tooltip = "추적기 프레임에 사용될 글꼴을 선택합니다.",
									type = "select",
									values = fontlist,
									get = function()
											return db.font
										end,
									set = function(value)
											db.font = value
											nextline = 1
											WatchFrame_Update()
										end,
								},
								{
									text = "글꼴 크기",
									tooltip = "추적기 프레임에 사용될 글꼴의 크기를 변경합니다.",
									type = "range",
									min = 6,
									max = 24,
									step = 1,
									get = function() return db.fontSize end,
									set = function(value) 
												db.fontSize = value
												nextline = 1
												WatchFrame_Update()
									end,
								},						
							},
						},
						{
							type = "description",
							text = "",
						},
						{
							type = "group",
							text = "글꼴 효과 및 간격",
							fontobject = "ChatFontNormal",
							r = 0,
							g = 0.82,
							b = 0.5,
							options = 
							{
								{
									text = "글꼴 효과",
									tooltip = "추적기 프레임의 글꼴에 사용될 효과를 설정합니다.",
									type = "select",
									values = fontFlags,
									get = function()
												for k, v in pairs(fontFlags) do
													if db.fontFlag == v then
														return k
													end
												end
											end,
									set = function(value)
												db.fontFlag = value
												nextline = 1	--start over from the beginning
												WatchFrame_Update()
											end,
									col = 2
								},
								{
									text = "글꼴 그림자 끄기",
									tooltip = "이 설정을 체크하면 글꼴의 그림자 효과가 없어집니다.",
									type = "toggle",
									get = function() return db.disableShadow end,
									set = function()
												db.disableShadow = not db.disableShadow
												nextline = 1
												FontChanges()
											end,
									col = 2
								},
								{
									text = "퀘스트 간격",
									tooltip = "퀘스트 간의 거리 간격을 변경합니다.",
									type = "range",
									min = 0,
									max = 12,
									step = 1,
									get = function() return db.questSpacing end,
									set = function(value)
												db.questSpacing = value
												WATCHFRAME_QUEST_OFFSET = value
												WatchFrame_Update()
											end,
									col = 2
								},
								{
									text = "라인 간격",
									tooltip = "각 라인 간의 간격을 변경합니다.",
									type = "range",
									min = 0,
									max = 10,
									step = 1,
									get = function() return db.lineSpacing end,
									set = function(value)
												db.lineSpacing = value
												WATCHFRAME_LINEHEIGHT = db.fontSize + value
												WatchFrame_Update()
											end,
									col = 2
								},
							},
						},
					},
				},

				{
					type = "root",
					name = "추적기 - 배경 설정",
					fontobject = "QuestTitleFont",
					options = 
					{
						{
							type = "description",
							text = "추적기 - 배경 설정",
							fontobject = "QuestTitleFont",
							r = 1,
							g = 0.82,
							b = 0,
							justifyH = "LEFT",
						},
						{
							type = "description",
							text = "임무 추적기의 배경 및 테두리를 설정합니다.\n",
							fontobject = "ChatFontNormal",
							justifyH = "LEFT",
							justifyV = "TOP",
						},
						{
							type = "group",
							text = "배경 설정",
							fontobject = "ChatFontNormal",
							r = 0,
							g = 0.82,
							b = 0.5,
							options = 
							{
								{
									text = "배경",
									tooltip = "추적기의 배경에 사용되는 무늬를 선택합니다.",
									type = "select",
									values = backgroundlist,
									get = function()
											return db.bg
										end,
									set = function(value)
											db.bg = value
											Appearance()
										end,
								},
								{
									text = "배경 색상/투명도",
									tooltip = "배경의 색상과 투명도 값을 설정합니다.\n\n만일 사용자 배경 무늬를 사용하고 색상을 사용하고 싶지 않다면 이 설정을 이용하세요.",
									type = "color",
									get = function() 
										return FloatToText(db.bgColor) end,
									set = function(value)
											r, b, g, a = hexToDec(value)
											db.bgColor.r = r
											db.bgColor.g = g
											db.bgColor.b = b
											db.bgColor.a = a
											Appearance()
									end,
								},
							},
						},
						{
							type = "description",
							text = "",
						},
						{
							type = "group",
							text = "테두리 설정",
							fontobject = "ChatFontNormal",
							r = 0,
							g = 0.82,
							b = 0.5,
							options = 
							{
																{
									text = "테두리",
									tooltip = "프레임의 테두리에 사용될 무늬를 선택합니다.",
									type = "select",
									values = borderlist,
									get = function()
											return db.border
										end,
									set = function(value)
											db.border = value
											Appearance()
										end,
								},
								{
									text = "테두리 색상/투명도",
									tooltip = "프레임의 테두리에 사용될 색상과 투명도를 설정합니다.",
									type = "color",
									get = function() return FloatToText(db.borderColor) end,
									set = function(value)
											r, b, g, a = hexToDec(value)
											db.borderColor.r = r
											db.borderColor.g = g
											db.borderColor.b = b
											db.borderColor.a = a
											Appearance()
									end,
								},
								{
									text = "테두리 두께",
									tooltip = "테두리의 두께 값을 설정합니다.",
									type = "range",
									min = 1,
									max = 24,
									step = .5,
									get = function() return db.borderWidth end,
									set = function(value) 
												db.borderWidth = value
												Appearance()
											end,
								},
								{
									text = "인셋",
									tooltip = "테두리와 배경 사이의 간격을 설정합니다.",
									type = "range",
									min = 0,
									max = 10,
									step = .5,
									get = function() return db.inset end,
									set = function(value) 
												db.inset = value
												Appearance()
										end,
								},
							},
						},
					},
				},

				{
					type = "root",
					name = "프로필 관리",
					fontobject = "QuestTitleFont",
					options = 
					{
						{
							type = "description",
							text = "프로필 관리",
							fontobject = "QuestTitleFont",
							r = 1,
							g = 0.82,
							b = 0,
							justifyH = "LEFT",
						},
						{
							type = "description",
							text = "전체 또는 캐릭터 별 프로필 작성 및 수정\n",
							fontobject = "ChatFontNormal",
							justifyH = "LEFT",
							justifyV = "TOP",
						},
						{
							type = "group",
							text = "배경 설정",
							fontobject = "ChatFontNormal",
							r = 0,
							g = 0.82,
							b = 0.5,
							options = 
							{	
								{
									text = "캐릭터 별 프로필",
									tooltip = "캐릭터 별로 각각 별도의 프로필을 생성합니다.  만약 이것을 체크하면 각 변경사항은 다른 캐릭터에 영향을 주지 않습니다.\n\n|c00E30016주의:|r 이 설정이 완료되면 UI가 자동으로 재시작됩니다!",
									type = "toggle",
--									width = "full",
									confirm = true,
									get = function() return BQHPCDB.charSpec end,
									set = function()
												BQHPCDB.charSpec = not BQHPCDB.charSpec
												ReloadUI()
											end,
									col = 3,
								},
								{
									text = "기본값에서 복사",
									tooltip = "이 캐릭터의 프로필 값에 기본값의 모든 설정 값을 복사해옵니다. 이 설정은 캐릭터 별 프로필에는 아무런 영향을 주지 않습니다.\n\n|c00E30016주의:|r 이 설정이 완료되면 UI가 자동으로 재시작됩니다!",
									type = "execute",
									confirm = true,
									disabled = function() return not BQHPCDB.charSpec end,
									func = function()
												BQHPCDB = BQHDB
												BQHPCDB.charSpec = true
												ReloadUI()
											end,
									col = 3,
								},
								{
									text = "프로필 초기화",
									tooltip = "모든 설정 값을 초기값으로 초기화 합니다. 이 설정은 어떠한 프로필에도 영향을 끼지치는 않습니다. \n\n|c00E30016주의:|r 이 설정이 완료되면 UI가 자동으로 재시작됩니다!",
									type = "execute",
									confirm = true,
									func = function()
												if BQHPCDB.charSpec then
													BQHPCDB = {charSpec = true}
												else
													BQHDB = {}
												end
												ReloadUI()
											end,
									col = 3,
								},
							},
						},
					},
				},

			},
			-- 하위 메뉴 끝
	}
	end
end

function BlinkQuestHelper_OnEvent(self, event, ...)
	local arg1 = ...
	if event == "UPDATE_MOUSEOVER_UNIT" then
		setTootipQuestProgress(GameTooltip)
	elseif event == "QUEST_WATCH_UPDATE" then
		completeCheckBox[arg1] = 1
	elseif event == "UI_INFO_MESSAGE" and BQH_CONFIG.QuestAnnounceToParty == 1 then
		local questUpdateText = gsub(arg1, "(.*): %d+/%d+", "%1", 1)
		if ( questUpdateText ~= arg1 ) then
			BQH_QuestAnnounceToParty(arg1)
		end
	elseif ( event == "QUEST_LOG_UPDATE" or event == "UPDATE_FACTION" or (event == "UNIT_QUEST_LOG_CHANGED" and arg1 == "player") ) then
		--[[if( BQH_CONFIG.QuestAutoRemove == 1 )then
			BlinkQuestHelper_QuestWatchAutoRemove()
		end]]
		BlinkQuestHelper_QuestCompleteCheck()
	end
end

BlinkQuestHelperFrame = CreateFrame("Frame", "BlinkQuestHelperFrame")
BlinkQuestHelperFrame:RegisterEvent("ADDON_LOADED")
BlinkQuestHelperFrame:SetScript("OnEvent", function(this, event, ...)
	if event == "ADDON_LOADED" then
		load(this)
	end
end)

-- 맵에서 퀘스트 툴팁에 레벨 표시 (Add by 드로아크)
hooksecurefunc("WorldMapFrame_UpdateQuests", function()
	if  (questTitle ~= nil) then
		i = 1
		local frame = _G["WorldMapQuestFrame"..i]
		while(_G["WorldMapQuestFrame"..i]) do
			frame.title:SetText(bqh_GetQuestLogTitle(frame.questLogIndex))
			i = i+1
			frame = _G["WorldMapQuestFrame"..i]
		end
	end
end)

hooksecurefunc("WorldMapQuestPOI_SetTooltip", function(self, questLogIndex)
	WorldMapTooltipTextLeft1:SetText(bqh_GetQuestLogTitle(questLogIndex))
	WorldMapTooltip:AppendText("")
	local questTitle, level, questTag, suggestedGroup, isHeader, isCollapsed, isComplete, isDaily = GetQuestLogTitle(questLogIndex) 
	if isDaily then
		WorldMapTooltipTextLeft1:SetTextColor(0.4, 0.6, 1.0)
	else
		local qtc = bqh_GetQuestDifficultyColor(level)
		WorldMapTooltipTextLeft1:SetTextColor(qtc.r, qtc.g, qtc.b)
	end
end)

-- 추가 함수 2

function MoveWatchFrame()
	WFContainer:ClearAllPoints()
	WFContainer:SetPoint(db.anchorPoint, UIParent, db.anchorPoint, db.xOffset, db.yOffset)
end

function SetSize()
	WFContainer:SetHeight(db.height)
	if wideFrame == "1" then
		WFContainer:SetWidth(350)
	else
		WFContainer:SetWidth(250)
	end
	WFContainer:SetScale(db.scale)
end

function Appearance()
	WFContainer:SetBackdrop({
			bgFile = LSM:Fetch("background", db.bg),
			edgeFile = LSM:Fetch("border", db.border),
			edgeSize = db.borderWidth,
			insets = {left=db.inset,right=db.inset,top=db.inset,bottom=db.inset}
		})
	WFContainer:SetBackdropColor(db.bgColor.r,db.bgColor.g,db.bgColor.b,db.bgColor.a)
	WFContainer:SetBackdropBorderColor(db.borderColor.r,db.borderColor.g,db.borderColor.b,db.borderColor.a)
end

function FontChanges()
	local font = LSM:Fetch("font", db.font)
	WatchFrameTitle:SetFont(font, db.fontSize, db.fontFlag)
	for i = nextline, 50 do
		line = _G["WatchFrameLine"..i]
		if line then
			line.text:SetFont(font, db.fontSize, db.fontFlag)
			line.dash:SetFont(font, db.fontSize, db.fontFlag)
			if db.disableShadow then
				line.text:SetShadowColor(0,0,0,0)
				line.dash:SetShadowColor(0,0,0,0)
			else
				line.text:SetShadowColor(0,0,0,1)
				line.dash:SetShadowColor(0,0,0,1)
			end
		else
			nextline = i	--so we only have to change new lines during the hook
			break
		end
	end
end

local function SkinButtons()
	if IsAddOnLoaded("rActionButtonStyler") then
		local colorR,colorG,colorB = ActionButton1NormalTexture:GetVertexColor()
		for i = nextbutton, 15 do
			itembtn = _G["WatchFrameItem"..i]
			if itembtn then
				itembtn:SetHighlightTexture(hover)
				itembtn:SetPushedTexture(pushed)
				border = _G[itembtn:GetName().."NormalTexture"]
				border:SetAllPoints()
				border:SetTexture(skin)
				border:SetVertexColor(colorR, colorG, colorB)
			else
				nextbutton = i
				break
			end
		end
	end
end

local function SetUpContainer()
	--keep nUI from hogging the WatchFrame - thanks Xrystal!
	if IsAddOnLoaded("nUI") then
		nUI_ResetWatchFrame = function() end
		nUI_Movers:lockFrame(WatchFrame, false, nil)
		nUI_Options.movedWatchFrame = true
	end
	
	MoveWatchFrame()
	SetSize()
	Appearance()
	SkinButtons()
--	if db.keybind ~= "" then
--		SetOverrideBinding(WFContainer, false, db.keybind, "CLICK WatchFrameCollapseExpandButton:LeftButton")
--	end	
	WATCHFRAME_QUEST_OFFSET = db.questSpacing
	WATCHFRAME_LINEHEIGHT = db.fontSize + db.lineSpacing
	
	hooksecurefunc("WatchFrame_Update", function()
		FontChanges()
		SkinButtons()
	end)
	hooksecurefunc("WatchFrame_Update", function()
		FontChanges()
		SkinButtons()

		if GetNumTrackedAchievements() == 0 and GetNumQuestWatches() == 0 then
			WFContainer:SetAlpha(0)
			WatchFrameCollapseExpandButton:EnableMouse(false)
		else
			WFContainer:SetAlpha(1)
			WatchFrameCollapseExpandButton:EnableMouse(true)
		end
	end)
	WatchFrame_Update()
	
	hooksecurefunc("WatchFrameLinkButtonTemplate_Highlight", function(self, enter)
		if enter then
			local id = self.index
			local watchType = self.type
			if watchType == "QUEST" then
				GameTooltip:SetOwner(self)
				GameTooltip:SetHyperlink(GetQuestLink(GetQuestIndexForWatch(id)))
				GameTooltip:Show()
			elseif watchType == "ACHIEVEMENT" then
				GameTooltip:SetOwner(self)
				GameTooltip:SetHyperlink(GetAchievementLink(id))
				GameTooltip:Show()			
			end
		else
			GameTooltip:Hide()
		end
	end)
	
	WatchFrame:SetParent(WFContainer)
	WatchFrame:SetClampedToScreen(false)
	WatchFrame:ClearAllPoints()
	WatchFrame.ClearAllPoints = function() end
	WatchFrame:SetPoint("TOPLEFT", 32,-2.5)
	WatchFrame:SetPoint("BOTTOMRIGHT", 4,0)
	WatchFrame.SetPoint = function() end

	WatchFrameTitle:SetParent(WFContainer)
	WatchFrameCollapseExpandButton:SetParent(WFContainer)
	WatchFrameTitle:Show()
	WatchFrameCollapseExpandButton:Show()
	WatchFrameTitle.Hide = function() end
	WatchFrameCollapseExpandButton.Hide = function() end
	WatchFrameCollapseExpandButton.Disable = function() end
	
	if BQHPCDB.collapsed then	--remember if watchframe was collapsed on last logout
		WatchFrame_CollapseExpandButton_OnClick()	--default function called by OnClick
		WFContainer:SetHeight(30)
		WFContainer:SetWidth(150)
	end
	
	WatchFrameCollapseExpandButton:RegisterForClicks("AnyDown")
	WatchFrameCollapseExpandButton:SetScript("OnClick", function(self,btn)	--redo this to allow for modified clicks
		if IsShiftKeyDown() then
			ToggleAchievementFrame()
		elseif IsAltKeyDown() then
			InterfaceOptionsFrame_OpenToCategory("블링크 퀘스트 도우미")
		elseif btn == "RightButton" then
			ToggleFrame(QuestLogFrame)
		else
			WatchFrame_CollapseExpandButton_OnClick()	--default function called by OnClick
			if WatchFrame.userCollapsed then	--my original hook
				WFContainer:SetHeight(30)
				WFContainer:SetWidth(150)
				BQHPCDB.collapsed = true
			else
				WFContainer:SetHeight(db.height)
				if wideFrame == "1" then
					WFContainer:SetWidth(350)
				else
					WFContainer:SetWidth(250)
				end
				BQHPCDB.collapsed = false
			end
		end
	end)
	WatchFrameCollapseExpandButton:SetScript("OnEnter", function(self)
			GameTooltip:SetOwner(self, "ANCHOR_TOP")
			GameTooltip:AddLine("[BQHE] 임무 추적기",1,1,1)
			if WatchFrame.collapsed then
				GameTooltip:AddLine("|cff00c0ff좌-클릭|r으로 추적기를 펼칩니다.")
			else
				GameTooltip:AddLine("|cff00c0ff좌-클릭|r으로 추적기를 최소화 합니다.")
			end
			GameTooltip:AddLine("|cff00c0ff우-클릭|r으로 퀘스트창을 열거나 닫습니다.")
			GameTooltip:AddLine("|cff00c0ff쉬프트+클릭|r으로 업적창을 열거나 닫습니다.")
			GameTooltip:AddLine("|cff00c0ff알트+클릭|r으로 설정 창을 엽니다.")
			GameTooltip:Show()
		end)
	WatchFrameCollapseExpandButton:SetScript("OnLeave", function() GameTooltip:Hide() end)
end

local function SetUpDB()
	if BQHPCDB.charSpec then
		--set defaults if new charSpec DB
		for k,v in pairs(defaults) do
			if type(BQHPCDB[k]) == "nil" then
				BQHPCDB[k] = v
			end
		end
		db = BQHPCDB
	else
		db = BQHDB
	end
end

local function Initialize()
	BQHDB = BQHDB or {}
	BQHPCDB = BQHPCDB or {}
		if BQHPCDB.charSpec == nil then
			BQHPCDB.charSpec = false
		end
		if BQHPCDB.collapsed == nil then
			BQHPCDB.collapsed = false
		end
	for k,v in pairs(defaults) do
	    if type(BQHDB[k]) == "nil" then
	        BQHDB[k] = v
	    end
	end
	SetUpDB()
	
	WFContainer:UnregisterEvent("PLAYER_ENTERING_WORLD")
	WFContainer:RegisterEvent("CVAR_UPDATE")
	WFContainer:SetScript("OnEvent", function(_,_,cvar,value)
			if cvar == "WATCH_FRAME_WIDTH_TEXT" then
				if not WatchFrame.userCollapsed then
					if value == "1" then
						WFContainer:SetWidth(350)
					else
						WFContainer:SetWidth(250)
					end
				end
				wideFrame = value
			end
		end)
end

WFContainer:RegisterEvent("PLAYER_ENTERING_WORLD")
local f = CreateFrame("Frame")	--need to create a slight delay to get rid of errors and glitches
f:Hide()
f.elapsed = 0
f:SetScript("OnUpdate", function(self, elapsed)
		f.elapsed = f.elapsed + elapsed
		if f.elapsed > .5 then
			SetUpContainer()
			f:Hide()
		end
	end)
WFContainer:SetScript("OnEvent", function() Initialize() f:Show() end)