--[[
	Hanul Quest

	By Arbi

	This mod improves Blizzard quest watch addon.

	Change Log:

	1.0 - Initial release.

	1.1 - Changed background color to transparent and reduce window scale.

	1.2 - Popup background textures when mouse cursor is being on hanulquest window.
	      Fixed to UI scale bug.

	1.3 - Changed Auto-add feature to Static Auto-add. if you checked, no longer delete
	      quest in 5 minutes.

	1.4 - Added detaled quest title tag in chat frame.

	]]

HQOptions = { };

HQ_PlayerEntered = false;
HQ_PlayerName = nil;

function HanulQuest_OnLoad()
	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("UI_INFO_MESSAGE");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");

	HanulQuest_PopUp(0);
	HanulQuest_Hookfunctions();
	HanulQuestBorder:SetBackdropColor(0,0,0,0.7);
	HanulQuestBorder:SetFrameStrata("LOW");

	if ( Cosmos_RegisterConfiguration ) then
		HanulQuest_Register_Cosmos();
	else
		SlashCmdList["HANULQUEST"] = HanulQuest_ChatCommandHandler;
		SLASH_HANULQUEST1 = "/퀘스트알림";
		SLASH_HANULQUEST2 = "/hq";
	end
end

function HanulQuest_OnEvent(event, arg1)
	if ( event == "VARIABLES_LOADED" ) then
		if ( UnitName("player") ~= nil and UnitName("player") ~= UNKNOWNOBJECT and UnitName("player") ~= UKNOWNBEING ) then  
			HQ_PlayerName = GetCVar("realmName").."|"..UnitName("player");
			if ( not HQOptions[HQ_PlayerName] ) then
				HQOptions[HQ_PlayerName] = {};
				HQOptions[HQ_PlayerName].Minimize = false;
				HQOptions[HQ_PlayerName].Enable = 1;
				HQOptions[HQ_PlayerName].AutoAdd = 0;
				HQOptions[HQ_PlayerName].AutoRemove = 1;
				HQOptions[HQ_PlayerName].Back = 0;
				HQOptions[HQ_PlayerName].QuestList = {};
			end
		end
	elseif ( event == "PLAYER_ENTERING_WORLD" ) then
		HQ_PlayerEntered = true;
	end
end

function HanulQuest_Hookfunctions()
	if ( Sea and Sea.util and Sea.util.hook ) then
		Sea.util.hook("QuestLog_Update", "HanulQuest_QuestLog_Update", "after");
		Sea.util.hook("QuestWatch_Update", "HanulQuest_QuestWatch_Update", "replace");
		Sea.util.hook("QuestLogTitleButton_OnClick", "HanulQuest_QuestLogTitleButton_OnClick", "replace");
		Sea.util.hook("QuestLog_OnEvent", "HanulQuest_QuestLog_OnEvent", "replace");
	end
end

function HanulQuest_Register_Cosmos()
	Cosmos_RegisterConfiguration(
		"COS_HANULQUEST",
		"SECTION",
		HANULQUEST_CONFIG_HEADER,
		HANULQUEST_CONFIG_HEADER_INFO
	);
	Cosmos_RegisterConfiguration(
		"COS_HANULQUEST_HEADER",
		"SEPARATOR",
		HANULQUEST_CONFIG_HEADER,
		HANULQUEST_CONFIG_HEADER_INFO
	);
	Cosmos_RegisterConfiguration(
		"COS_HANULQUEST_AUTOADD",
		"CHECKBOX",
		HANULQUEST_CONFIG_AUTOADD,
		HANULQUEST_CONFIG_AUTOADD_INFO,
		HanulQuest_Toggle_AutoAdd,
		1
	);
	Cosmos_RegisterConfiguration(
		"COS_HANULQUEST_AUTOREMOVE",
		"CHECKBOX",
		HANULQUEST_CONFIG_AUTOREMOVE,
		HANULQUEST_CONFIG_AUTOREMOVE_INFO,
		HanulQuest_Toggle_AutoRemove,
		1
	);
	Cosmos_RegisterConfiguration(
		"COS_HANULQUEST_BACK",
		"CHECKBOX",
		HANULQUEST_CONFIG_BACK,
		HANULQUEST_CONFIG_BACK_INFO,
		HanulQuest_Toggle_Back,
		0
	);
	Cosmos_RegisterConfiguration(
		"COS_HANULQUEST_RESETPOS",
		"BUTTON",
		HANULQUEST_CONFIG_RESETPOS,
		HANULQUEST_CONFIG_RESETPOS_INFO,
		HanulQuest_ResetPos,
		0,
		0,
		0,
		0,
		HANULQUEST_RESETPOS_BUTTONTEXT
	);
end

function HanulQuest_Toggle_AutoAdd(toggle)
	if ( not HQOptions[HQ_PlayerName] ) then
		return;
	end
	if ( toggle == 1 ) then
		HQOptions[HQ_PlayerName].AutoAdd = 1;
	else
		HQOptions[HQ_PlayerName].AutoAdd = 0;
	end
end

function HanulQuest_Toggle_AutoRemove(toggle)
	if ( not HQOptions[HQ_PlayerName] ) then
		return;
	end
	if ( toggle == 1 ) then
		HQOptions[HQ_PlayerName].AutoRemove = 1;
	else
		HQOptions[HQ_PlayerName].AutoRemove = 0;
	end
end

function HanulQuest_Toggle_Back(toggle)
	if ( not HQOptions[HQ_PlayerName] ) then
		return;
	end
	if ( toggle == 1 ) then
		HQOptions[HQ_PlayerName].Back = 1;
		HanulQuest_PopUp(1);
	else
		HQOptions[HQ_PlayerName].Back = 0;
		HanulQuest_PopUp(0);
	end
end

function HanulQuest_ChatCommandHandler(arg1)
	if ( not arg1 or arg1 == "" ) then
		HanulQuest_Toggle();
	elseif ( arg1 == "도움말" ) then
	elseif ( arg1 == "자동추가" ) then
		if ( HQOptions[HQ_PlayerName].AutoAdd == 0 ) then
			Sea.io.print(HANULQUEST_CHAT_AUTOADD_ENABLE);
			HQOptions[HQ_PlayerName].AutoAdd = 1;
		else
			Sea.io.print(HANULQUEST_CHAT_AUTOADD_DISABLE);
			HQOptions[HQ_PlayerName].AutoAdd = 0;
		end
	elseif ( arg1 == "자동삭제" ) then
		if ( HQOptions[HQ_PlayerName].AutoRemove == 0 ) then
			Sea.io.print(HANULQUEST_CHAT_AUTOREMOVE_ENABLE);
			HQOptions[HQ_PlayerName].AutoRemove = 1;
		else
			Sea.io.print(HANULQUEST_CHAT_AUTOREMOVE_DISABLE);
			HQOptions[HQ_PlayerName].AutoRemove = 0;
		end
	elseif ( arg1 == "배경" ) then
		if ( HQOptions[HQ_PlayerName].Back == 0 ) then
			Sea.io.print(HANULQUEST_CHAT_BACK_ENABLE);
			HQOptions[HQ_PlayerName].Back = 1;
			HanulQuest_PopUp(1);
		else
			Sea.io.print(HANULQUEST_CHAT_BACK_DISABLE);
			HQOptions[HQ_PlayerName].Back = 0;
			HanulQuest_PopUp(0);
		end
	elseif ( arg1 == "초기화" ) then
		HanulQuest_ResetPos();
	end
end

function HanulQuest_AddList(questIndex, questTitle)
	HQOptions[HQ_PlayerName]["QuestList"][questIndex] = questTitle;
end

function HanulQuest_RemoveList(questIndex)
	HQOptions[HQ_PlayerName]["QuestList"][questIndex] = nil;
end

function HanulQuest_ResetPos()
	HanulQuestFrame:ClearAllPoints();
	HanulQuestFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", 0, 10);
	HanulQuestMinimizeFrame:ClearAllPoints();
	HanulQuestMinimizeFrame:SetPoint("TOPRIGHT", "HanulQuestFrame", "CENTER", 0, 10);
end

function HanulQuest_UpdateQuestList(arg1)
	if ( HQOptions[HQ_PlayerName]["QuestList"] and GetNumQuestWatches() == 0 ) then
		RemoveQuestWatch(arg1);
	--[[	for i = 1, MAX_QUESTLOG_QUESTS, 1 do
			if ( HQOptions[HQ_PlayerName]["QuestList"][i] ) then
				AddQuestWatch(i);
			end
		end		
		HQOptions[HQ_PlayerName].QuestList = {};]]--
		--QuestWatch_Update();
	end
end

function HanulQuest_Toggle()
	if ( HQOptions[HQ_PlayerName].Minimize ) then
		if ( HanulQuestMinimizeFrame:IsVisible() ) then
			HanulQuestMinimizeFrame:Hide();
			HQOptions[HQ_PlayerName].Enable = 0;
		else
			HanulQuestMinimizeFrame:Show();
			HQOptions[HQ_PlayerName].Enable = 1;
			QuestWatch_Update();
		end
	else
		if ( HanulQuestFrame:IsVisible() ) then
			HanulQuestFrame:Hide();
			HQOptions[HQ_PlayerName].Enable = 0;
		else
			HanulQuestFrame:Show();
			HQOptions[HQ_PlayerName].Enable = 1;
			QuestWatch_Update();
		end
	end
end

function HanulQuest_Show()
	if ( HQOptions[HQ_PlayerName].Minimize ) then
		HanulQuestFrame:Hide();
		HanulQuestMinimizeFrame:Show();
		HQOptions[HQ_PlayerName].Enable = 1;
		QuestWatch_Update();
	else
		HanulQuestMinimizeFrame:Hide();
		HanulQuestFrame:Show();
		HQOptions[HQ_PlayerName].Enable = 1;
		QuestWatch_Update();
	end
end

function HanulQuest_PopUp(toggle)
	if ( toggle == 1 ) then
		HanulQuestBorder:Show();
		HanulQuestCloseButton:Show();
		HanulQuestMinimizeButton:Show();
	else
		HanulQuestBorder:Hide();
		HanulQuestCloseButton:Hide();
		HanulQuestMinimizeButton:Hide();
	end
end

function HanulQuest_QuestLog_Update()
	local numEntries = GetNumQuestLogEntries();
	
	for i=1, QUESTS_DISPLAYED, 1 do
		local questIndex = i + FauxScrollFrame_GetOffset(QuestLogListScrollFrame);
		local questLogTitle = getglobal("QuestLogTitle"..i);
		local questTitleTag = getglobal("QuestLogTitle"..i.."Tag");
		if ( questIndex <= numEntries ) then
			local questLogTitleText, level, isHeader;
			questLogTitleText, level, _, _, isHeader = GetQuestLogTitle(questIndex);
			if (level and not isHeader) then
				questLogTitle:SetText("  ["..level.."] "..questLogTitleText);
			end
		end
	end
end

function HanulQuest_QuestWatch_Init()
	if ( GetNumQuestWatches() == 0 ) then
		HanulQuestFrame:Hide();
		HanulQuestMinimizeFrame:Hide();
		QuestLogTrackTracking:SetVertexColor(1.0, 0, 0);
		return;
	end
end

function HanulQuest_QuestWatch_Update()
	local numObjectives;
	local questWatchMaxWidth = 0;
	local tempWidth;
	local watchText;
	local text, type, finished;
	local questTitle, level, questTag, color;
	local watchTextIndex = 1;
	local questIndex;
	local objectivesCompleted;

	for i=1, GetNumQuestWatches() do
		questIndex = GetQuestIndexForWatch(i);
		if ( questIndex ) then
			numObjectives = GetNumQuestLeaderBoards(questIndex);
			HanulQuestMiniNameTemplate:SetText(HANULQUESTTEXT.." - "..GetNumQuestWatches().."/5");
		
			--If there are objectives set the title
			if ( numObjectives > 0 ) then
				-- Set title
				questTitle, level, questTag = GetQuestLogTitle(questIndex);
				HanulQuest_AddList(questIndex, questTitle);
				if ( questTag and questTag == RAID ) then
					questTag = "공] ";
				elseif ( questTag and questTag == "던전" ) then
					questTag = "던] ";
				elseif ( questTag and questTag == ELITE ) then
					questTag = "+] ";
				elseif ( questTag and questTag == "전쟁" ) then
					questTag = "쟁] ";
				elseif ( questTag and questTag == "영웅" ) then
					questTag = "영] ";
				elseif ( questTag and questTag == GROUP ) then
					questTag = "+] ";
				else
					questTag = "] ";
				end
				questTitle = "["..level..questTag..questTitle;
				color = GetDifficultyColor(level);
				watchText = getglobal("HanulQuestLine"..watchTextIndex);
				watchText:SetTextColor(color.r, color.g, color.b);
				watchText:SetText(questTitle);
				tempWidth = watchText:GetWidth();
				-- Set the anchor of the title line a little lower
				if ( watchTextIndex > 1 ) then
					watchText:SetPoint("TOPLEFT", "HanulQuestLine"..(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("HanulQuestLine"..watchTextIndex);
					local i, j, itemname, numberitemsgot, numberitemsneeded = string.find(text, "(.*):%s*([-%d]+)%s*/%s*([-%d]+)%s*$");
					local green = 0;
					local red = 1.0;
					if ( not numberitemsgot ) then
						local i, j, stritemname, stritemsgot, strneeded = string.find(text, "(.*):%s*(.+)%s*/%s*(.+)%s*$");
						if ( stritemsgot ) then
							if ( stritemsgot == strneeded ) then
								red = 0;
								green = 1.0;
							else
								red = 1.0;
								green = 0;
							end
						end
					else
						green = numberitemsgot / numberitemsneeded;
						red = 1.0 - green;
					end
					-- Color the finished objectives
					if ( finished ) then
						green = 1.0;
						red = 0;
						objectivesCompleted = objectivesCompleted + 1;
					end
					-- Set Objective text and their color
					watchText:SetTextColor(red, green, 0);
					watchText:SetText(" - "..text);

					tempWidth = watchText:GetWidth();
					if ( tempWidth > questWatchMaxWidth ) then
						questWatchMaxWidth = tempWidth;
					end
					watchText:SetPoint("TOPLEFT", "HanulQuestLine"..(watchTextIndex - 1), "BOTTOMLEFT", 0, 0);
					watchText:Show();
					watchTextIndex = watchTextIndex + 1;
					if ( objectivesCompleted == numObjectives and HQOptions[HQ_PlayerName].AutoRemove == 1 ) then
						RemoveQuestWatch(questIndex);
						HanulQuest_RemoveList(questIndex);
						--QuestWatch_Update();
					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
		HanulQuestFrame:Hide();
		HanulQuestMinimizeFrame:Hide();
		return;
	else
		if ( HQOptions[HQ_PlayerName].Enable == 0 ) then
			return;
		end
		if ( not HQOptions[HQ_PlayerName].Minimize ) then
			HanulQuestFrame:Show();
			HanulQuestFrame:SetHeight((watchTextIndex * 14) + 25);
			HanulQuestFrame:SetWidth(questWatchMaxWidth + 25);
		else
			HanulQuestMinimizeFrame:Show();
		end
	end

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

function HanulQuest_QuestLogTitleButton_OnClick(button)
	local questName = this:GetText();
	local questIndex = this:GetID() + FauxScrollFrame_GetOffset(QuestLogListScrollFrame);
	local isCompleted, questTag;
	if ( IsShiftKeyDown() ) then
		if ( questIndex ) then
			_, _, questTag, _, _, _, isCompleted = GetQuestLogTitle(questIndex);
		end		
		-- If header then return
		if ( this.isHeader ) then
			return;
		end
		-- Otherwise try to track it or put it into chat
		if ( ChatFrameEditBox:IsVisible() ) then
			-- Trim leading whitespace
			local qTitle = gsub(this:GetText(), " *(.*)", "%1");
			if ( questTag and questTag == RAID ) then
				qTitle = gsub(qTitle, "(.*)] *(.*)", "%1공] %2");
			elseif ( questTag and questTag == "던전" ) then
				qTitle = gsub(qTitle, "(.*)] *(.*)", "%1던] %2");
			elseif ( questTag and questTag == ELITE ) then
				qTitle = gsub(qTitle, "(.*)] *(.*)", "%1+] %2");
			elseif ( questTag and questTag == "전쟁" ) then
				qTitle = gsub(qTitle, "(.*)] *(.*)", "%1쟁] %2");
			elseif ( questTag and questTag == "영웅" ) then
				qTitle = gsub(qTitle, "(.*)] *(.*)", "%1영] %2");
			elseif ( questTag and questTag == GROUP ) then
				qTitle = gsub(qTitle, "(.*)] *(.*)", "%1+] %2");
			end
			ChatFrameEditBox:Insert(qTitle);
		else
			-- Shift-click toggles quest-watch on this quest.
			if ( IsQuestWatched(questIndex) ) then
				HanulQuest_RemoveList(questIndex);
				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, UIERRORS_HOLD_TIME);
					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, UIERRORS_HOLD_TIME);
					return;
				end
				if ( isCompleted == 1 and HQOptions[HQ_PlayerName].AutoRemove == 1 ) then
					UIErrorsFrame:AddMessage(HANULQUEST_WATCH_COMPLETED_OBJECTIVES, 1.0, 0.1, 0.1, 1.0, UIERRORS_HOLD_TIME);
					return;
				end
				HQOptions[HQ_PlayerName].Enable = 1;
				AddQuestWatch(questIndex);
				QuestLog_Update();
				QuestWatch_Update();
			end
		end
	end
	QuestLog_SetSelection(questIndex)
	QuestLog_Update();
end

function HanulQuest_QuestLog_OnEvent(event)
	if ( event == "QUEST_LOG_UPDATE" or event == "UPDATE_FACTION" ) then
		QuestLog_Update();
		HanulQuest_QuestWatch_Init();
		QuestWatch_Update();
		if ( QuestLogFrame:IsVisible() ) then
			QuestLog_UpdateQuestDetails(1);
		end
	elseif ( event == "UNIT_QUEST_LOG_CHANGED" and arg1 == "player" ) then
		QuestLog_Update();
		QuestWatch_Update();
		if ( QuestLogFrame:IsVisible() ) then
			QuestLog_UpdateQuestDetails(1);
		end
	elseif ( event == "QUEST_WATCH_UPDATE" ) then
		if ( AUTO_QUEST_WATCH == "1" and GetNumQuestLeaderBoards(arg1) > 0 ) then
			if ( HQOptions[HQ_PlayerName].AutoAdd == 1 ) then
				AddQuestWatch(arg1);
			else
				AddQuestWatch(arg1,MAX_QUEST_WATCH_TIME);
			end
			QuestLog_Update();
			--HanulQuest_UpdateQuestList(arg1);
			HanulQuest_QuestWatch_Init();
			QuestWatch_Update();
		end
	else
		QuestLog_Update();
		if ( event == "PARTY_MEMBERS_CHANGED" ) then
			-- Determine whether the selected quest is pushable or not
			if ( GetQuestLogPushable() and GetNumPartyMembers() > 0 ) then
				QuestFramePushQuestButton:Enable();
			else
				QuestFramePushQuestButton:Disable();
			end
		end
	end
end