BINDING_HEADER_FINDPARTY = "파티찾기 도우미(FindParty)";

FP_CURRENT_VERSION = 3.169;
FP_C_TITLE = "파티 찾기 도우미 v"..tostring(FP_CURRENT_VERSION);

--local debugSwitch = nil;
--local debugSwitch = 1;

FP_Scroll_Info = nil;
FP_Options = nil;
FP_Version = 1;
FP_DUNGEON_LIST = nil;
FP_Filter_Dungeon_Info = nil;
FP_UserDefinedAdMsg = nil;  --from 1.12
FP_Filter_Class = nil;
FP_Activated_Status = nil;
FP_IsDungeonInit = nil;

local FP_Datas = {};
local MAX_VIEW_LINE = 20;
local MIN_VIEW_LINE = 1;
local FP_Exceptions = {};

local CUTTED_MSG_LENGTH = 100;

local FP_OPTION_LIST = {
	[1] = {["광고 주기"] ={"10","15","20","25","30","45","60","90","120","300","600"}},
	[2] = {["유효 시간"] ={"30","60", "90","120", "300", "600"}},
	[3] = {["파티찾기 채널"] ={}},
	[4] = {[""] = {}},
	[5] = {["전체 크기"] = {"2","1.9","1.8","1.7","1.6","1.5","1.4",
		"1.3","1.2","1.1","1", "0.9","0.8", "0.7", "0.6",
		"0.5"}
	},
	[6] = {["글자 크기"] = {"12","13", "14","15","16","17","18"}},
	[7] = {["창 색상 편집"] = {}},
	[8] = {[""] = {}},
	[9] = {["던전 편집"] = {}},
	[10] = {[""] = {}},
	[11] = {["초기화"] = {"창 위치", "창 크기", "전체 옵션 초기화(Reload UI)"}},
	[12] = {[""] = {}},
--	[13] = {["캐릭명에 서버명 표기"] = {}},
	[13] = {["귀속던전 제외"] = {}},
	[14] = {["ESC로 창 닫기"] = {}},
	[15] = {["미니맵 버튼 활성/비활성"] = {}},
	[16] = {[""] = {}},
	[17] = {["5인던전 진행 중에 자동 끄기"] = {}},
	[18] = {["레이드 진행 중에 자동 끄기"] = {}},
	[19] = {["전장/투기장에 있을시 자동 끄기"] = {}},
	[20] = {[""] = {}},
	[21] = {["닫기"] = {}},
};

local FP_OPTION_NAME = {
	["광고 주기"] = "interval" ,
	["유효 시간"] = "valid"  ,
	["파티찾기 채널"] = "channel",
	["전체 크기"] = "scale",
	["글자 크기"] = "fontsize",
	["초기화"] = "reset",
	["창 색상 편집"] = "color",
--	["캐릭명에 서버명 표기"] = "charservername",
	["귀속던전 제외"] = "belong",
	["ESC로 창 닫기"] = "esc",
	["미니맵 버튼 활성/비활성"] = "minimaptoggle",
	["레이드 진행 중에 자동 끄기"] = "noraid",
	["5인던전 진행 중에 자동 끄기"] = "noparty",
	["전장/투기장에 있을시 자동 끄기"] = "nopvp",
};

local Party_Find_Info = {
	["class"]={},
	["mode"] = nil,
	["dungeon"] = nil,
	["zone"] = nil,
	["selected"] = false,
	["announcing"] = false,
};

local ShouterSelected = nil;

local ASCD = true;
local DESC = false;

local INC = 1;
local DEC = 2;
local MAX = 3;
local MIN = 4;

local FP_Sort_Info = {
	["time"] = ASCD,
	["dungeon"] = ASCD,
	["name"] = ASCD,
	["msg"] = ASCD,
	["current_sort"] ="dungeon"
};

local Col_Name = {"time", "dungeon", "name", "msg"}



local valdating_timer = 0;
local announce_timer = 0;

local User_Realm;
local User_Faction;

local FP_Default_Options= {
	["interval"] = 30,
	["valid"] = 60,
	["channel"] = { ["파티"] = true, ["파티찾기"] = true },
	["activated"] = true;
	["scale"] = 1,
	["fontsize"] = 13,
	["iconLocked"] = false,
	["color"] = { ["r"] = 0, ["g"] = 0, ["b"] = 0, ["opacity"] = 0.5, },
	["titlebarVisible"] = true,
	["menubarVisible"] = true,
	["activateBellnWindow"] = false,
--	["charservername"] = false,
	["belong"] = false,
	["esc"] = false,
	["minimaptoggle"] = true,
	["noraid"] = false,
	["noparty"] = false,
	["nopvp"] = false,
};

local InfoDepository = {};


function FP_Init()
	FP_Debug("FP_Init Start!!!!!!!!!!!");
	--FP_Debug("Version "..tostring(FP_Version).." / "..tostring(FP_CURRENT_VERSION));

	FP_GetChannels();
	
	if (not (FP_Version == FP_CURRENT_VERSION)) then
		--FP_Debug("--  New version Init");
		local oldOption = FP_Options;
		if (oldOption) then
			for k,v in pairs(FP_Default_Options) do
				if not FP_Options[k] then
					FP_Options[k] = v;
				end
			end
		end

		local oldScroll = FP_Scroll_Info;
		if (oldScroll) then
			for k, v in pairs(oldScroll) do
				FP_Scroll_Info[k] = v;
			end
		else
			FP_Scroll_Info = {
				["max"] = MAX_VIEW_LINE,
				["height"] = 25,
				["viewLines"] = MAX_VIEW_LINE,
			};
		end

		-- 구버전 강제 옵션 초기화
		if (not FP_DUNGEON_LIST or FP_Version < 2.72) then
			DEFAULT_CHAT_FRAME:AddMessage("|cffff0000FindParty - 던전 목록이 구버전이 발견되어 던전 리스트 목록을 초기화 합니다.");
			FP_LoadDefaultOption();
--			FP_LoadDefaultDungeonList();
      FP_DUNGEON_LIST = FP_DEFAULT_DUNGEON_LIST;
			-- from 1.12
			FP_Filter_Dungeon_Info = {
				["filtered"] = false,
				["zones"] = {},
				["dungeons"] = {},
				["num"] = 0;
			}

			-- from 1.12
			FP_Filter_Class = "모두";
		end

		FP_Version = FP_CURRENT_VERSION;
	end

	-- FP_RAID_ORDER 과 FP_DUNGEON_LIST의 항목이 일치하는지 체크 - 실패하면 던전 리스트를 초기화 한다 (오류 방지를 위해) by 영원이란
	local order_check1 = 0;
	local order_check2 = 0;
	
	for k, v in pairs(FP_RAID_ORDER) do
		order_check1 = order_check1 + 1;
		for c, n in pairs(FP_DUNGEON_LIST["공격대"]) do
			if (v == c) then
				order_check2 = order_check2 + 1;
			end
		end
	end
	
	if (order_check1 ~= order_check2) then
		DEFAULT_CHAT_FRAME:AddMessage("|cffff0000FindParty - 던전 목록 체크 실패! 던전 리스트를 초기화 합니다.");
		FP_LoadDefaultDungeonList();
	end

	--FP_OPTION_LIST["던전 편집"] = FP_DUNGEON_LIST;

	User_Realm = GetRealmName();
	User_Faction = UnitFactionGroup("player");

	FP_ListResize();
	FP_UIResize(FP_Options.scale);
	FP_FontResize();
	FP_SetListColor();

	if FP_Activated_Status then 
		FP_Activate(FP_Activated_Status); 
	else 
		FP_Activate(FP_Options.activated); 
	end

	if (FP_IsActiveBellnWindow()) then
		FP_TitleFrameActivateBellnWindow:SetNormalTexture("Interface\\AddOns\\FindParty\\bellActivated");
	else
		FP_TitleFrameActivateBellnWindow:SetNormalTexture("Interface\\AddOns\\FindParty\\bellDeactivated");
	end

	-- 타이틀바, 메뉴바 설정
	if (FP_Options.titlebarVisible) then
		FP_TitleFrame:Hide();
	else
		FP_TitleFrame:Show();
	end
	FP_ListFrameBridgeToTitle:GetScript("OnClick")();

	if (FP_Options.menubarVisible) then
		FP_MenuFrame:Hide();
	else
		FP_MenuFrame:Show();
	end
	FP_ListFrameBridgeToMenu:GetScript("OnClick")();

	--미니맵 아이콘 설정
	if FP_Minimap_Button and FP_Options.iconLocked then FP_Minimap_Button:RegisterForDrag(nil); end;

	--광고글 설정
	if (FP_UserDefinedAdMsg) then
		FP_FindFrameAdText:SetText(FP_UserDefinedAdMsg);
		if(FP_Options.userdefine) then FP_FindFrameEtc:SetChecked(true); end
	end
	if (FP_UserDefinedWhMsg) then
		FP_FindFrameWhText:SetText(FP_UserDefinedWhMsg);
		if(FP_Options.userdefineWh) then FP_FindFrameWhCheck:SetChecked(true); end
	end
	
	-- 던전선택 설정
	FP_ListFrameFilterDungeonText:SetText("던전: "..FP_GetDungeonFilterDesc());

	-- 클래스선택 설정
	FP_ListFrameFilterClassText:SetText("직업 골라내기 : "..FP_Filter_Class);

	if FP_Options.esc then
		tinsert(UISpecialFrames, "FP_Frame");
	end;

  if(FP_Options.MinimapToggle or FP_Options.MinimapToggle== nil) then FP_Minimap_Button:Show();
  else FP_Minimap_Button:Hide();
  end
  
--  if(FP_Options.charservername or FP_Options.charservername== nil) then FP_Minimap_Button:Show();
--  else FP_Minimap_Button:Hide();
--  end

end

function FP_Activate(active)
--FP_Debug("FP_Activate");
	FP_Options.activated = active;

	if (active) then
		DEFAULT_CHAT_FRAME:AddMessage("|cffffff00FindParty v"..FP_CURRENT_VERSION.." - 파티 찾기 도우미를 활성화 합니다.");
		FP_TitleFrameText:SetText(FP_C_TITLE);
		FP_TitleFrameActivation:SetNormalTexture("Interface\\AddOns\\FindParty\\activated");

		-- 재시작시 데이타 초기화
		FP_RemoveAllList();
		FP_Scroll();
	else
		DEFAULT_CHAT_FRAME:AddMessage("|cffffff00FindParty v"..FP_CURRENT_VERSION.." - 파티 찾기 도우미를 비활성화 합니다.");
		FP_TitleFrameText:SetText(FP_C_TITLE.." (중단)");
		FP_TitleFrameActivation:SetNormalTexture("Interface\\AddOns\\FindParty\\deactivated");
		collectgarbage("collect");
	end
end

function FP_ActiveBellnWindow(active)
--FP_Debug("FP_ActiveBellnWindow");
	if(active) then
		DEFAULT_CHAT_FRAME:AddMessage("|cffffff00팝업 모드를 비활성화 합니다.");
		FP_Options["activateBellnWindow"] = false;
		FP_TitleFrameActivateBellnWindow:SetNormalTexture("Interface\\AddOns\\FindParty\\bellDeactivated");
	else
		DEFAULT_CHAT_FRAME:AddMessage("|cffffff00팝업 모드를 활성화 합니다.");
		FP_Options["activateBellnWindow"] = true;
		FP_TitleFrameActivateBellnWindow:SetNormalTexture("Interface\\AddOns\\FindParty\\bellActivated");
	end
	
end

function FP_CreateNewShoutingInfo()
--FP_Debug("FP_CreateNewShoutingInfo");
	local info;
	local num = #InfoDepository;

	if (num > 0) then
		info = InfoDepository[num];
		table.remove(InfoDepository, num);
	else
		info ={["name"]= nil,
			["class"] = nil,
			["level"] = nil,
			["msg"] = nil,
			["time"] = 0,
			["dungeon"]= nil,
			["mode"]= nil,
			["user"]= nil,
		};
	end

	return info;
end

function FP_RestoreShoutingInfo(info)
--FP_Debug("FP_RestoreShoutingInfo");
	table.insert(InfoDepository, info);
end

function FP_GetChannels()
--FP_Debug("FP_GetChannels");
	FP_OPTION_LIST[3]["파티찾기 채널"] = {};

	for i=1, 20 do
		local id, name = GetChannelName(i);
		if (id and name) then
			table.insert(FP_OPTION_LIST[3]["파티찾기 채널"], tostring(name));
		end
	end
end

-- 유아원때일진님 파티찾기에서 참조 // 던전 필터링 함수
function filterIgnoreMsg(msg, ignoreText)
--FP_Debug("filterIgnoreMsg");
	local tempMsg = msg;
	local x = nil;
	local y = nil;
	local j = 1;
	local ignored = false;

	if ((tempMsg == nil) or (ignoreText == nil)) then
		return nil;
	end

	for i = 1, table.getn(ignoreText) do
		j = 1;

		while (true) do
			x, y = string.find(tempMsg, ignoreText[i], j);
			if (x) then
				tempMsg = string.sub(tempMsg, 1, x-1)..string.sub(tempMsg, y+1);
				ignored = true;
			else
				break;
			end
			j = x;
			x = nil;
		end
	end
	return tempMsg, ignored;
end

function FP_DungeonParse(msg)
--FP_Debug("FP_DungeonParse");
	local dungeon = nil;
	local mode = nil;
	local FP_dungeon_check = 1;
	local FP_MODE_check = true;
	local dungeon_status = nil;
	-- 유아원때일진님의 파티찾기에서 가져온 부분 // 광고 문자의 공백 제거
	local filteredMsg = string.gsub(msg, " ", "");
	filteredMsg = string.upper(filteredMsg);
	if (filteredMsg == nil) then
		return dungeon, mode;
	end
	-- 유아원때일진님의 파티찾기에서 가져온 부분 // 던전 및 난이도는 앞부분에 대부분 있으므로 앞부분 문자만 잘라냄
	filteredMsg = string.sub(filteredMsg, 1, CUTTED_MSG_LENGTH);
	if (filteredMsg == nil) then
--	FP_Debug("389>>>>>>>>"..tostring(dungeon)..tostring(mode));
		return dungeon, mode;
	end
	-- 유아원때일진님의 파티찾기에서 가져온 부분 // 방해되는 문자열 제거
	filteredMsg = filterIgnoreMsg(filteredMsg, FP_DUNGEON_IGNORE_TEXT);
	if (filteredMsg == nil) then
--	FP_Debug("395>>>>>>>>"..tostring(dungeon)..tostring(mode));
		return dungeon, mode;
	end

	--FP_Debug("msg : "..msg)
	for zone,dlist in pairs(FP_DUNGEON_LIST) do
		--FP_Debug("zone"..zone);
		-- 주간 퀘스트 판단을 위한 추가 by 영원이란 (주간 퀘스트 관련 문자열이 들어가면 무조건 주간 퀘스트로 분류)
		if(string.find(filteredMsg, "주간")) then dungeon = "주간 퀘스트"; dungeon_status = "1"; FP_dungeon_check = nil; break; end;
		if(string.find(filteredMsg, "주퀘")) then dungeon = "주간 퀘스트"; dungeon_status = "1"; FP_dungeon_check = nil; break; end;
		if(string.find(filteredMsg, "주관")) then dungeon = "주간 퀘스트"; dungeon_status = "1"; FP_dungeon_check = nil; break; end;

		if zone ~= "공격대" then
--			FP_Debug("==========="..zone.."============");
			for v,k in pairs(dlist) do
				for i=1, table.getn(k) do
					--FP_Debug("+++"..k[i])
					if (string.find(filteredMsg, k[i])) and FP_dungeon_check then
						dungeon = v;
						dungeon_status = "0";
						FP_dungeon_check = nil;
						break;
					end
				end
			end
		else
--			FP_Debug("----------"..zone.."------------");
			for k=1, table.getn(FP_RAID_ORDER) do
				--FP_Debug("FP_RAID_ORDER["..k.."]")
				for n = 1, table.getn(dlist[FP_RAID_ORDER[k]]) do
					--FP_Debug(">>>"..dlist[FP_RAID_ORDER[k]][n]..tostring(FP_dungeon_check))
					-- 아이템 관련 문자열은 던전 난이도가 아니므로 제거한다 by 영원이란
					if not string.find(filteredMsg, dlist[FP_RAID_ORDER[k]][n].."급") and not string.find(filteredMsg, dlist[FP_RAID_ORDER[k]][n].."이상") and not string.find(filteredMsg, dlist[FP_RAID_ORDER[k]][n].."스팩") and
					not string.find(filteredMsg, dlist[FP_RAID_ORDER[k]][n].."스펙") and not string.find(filteredMsg, dlist[FP_RAID_ORDER[k]][n].."파밍") and not string.find(filteredMsg, dlist[FP_RAID_ORDER[k]][n].."졸") and
					not string.find(filteredMsg, dlist[FP_RAID_ORDER[k]][n].."다니") and string.find(filteredMsg, dlist[FP_RAID_ORDER[k]][n]) and FP_dungeon_check then
						dungeon = FP_RAID_ORDER[k];
						dungeon_status = "1";
						FP_dungeon_check = nil;
						break;
					end
				end
			end
		end
	end
	--FP_Debug(">>>>dungeon : "..tostring(dungeon));

	--던전 난이도를 얻어오는 부분 재작성 by 영원이란 // 유아원때일진님 파티 찾기에서 참조. 문자와 숫자를 따로 처리함.
--	local modeDigit = -1;
--	local startAddr = nil;
--	local endAddr = 0;
--	for w in string.gmatch(filteredMsg, "%d+") do
--		startAddr, endAddr = string.find(filteredMsg, "%d+", endAddr+1);
--		modeDigit = tonumber(w);FP_Debug("447>>>>>>>> startAddr : "..tostring(startAddr).."endAddr : "..tostring(endAddr));
--		break;
--	end
--	FP_Debug("450>>>>>>>> modeDigit : "..tostring(modeDigit).."dungeon_status : "..tostring(dungeon_status));
--	if modeDigit and (modeDigit == 25 or modeDigit == 20) then
--	FP_Debug("452>>>>>>>>");
--		if dungeon_status == "1" then
--		FP_Debug("454>>>>>>>>");
--			mode = "25인";
--			FP_MODE_check = nil;
--		end
--	elseif modeDigit and modeDigit == 10 then
--	FP_Debug("459>>>>>>>>");
--		if dungeon_status == "1" then
--		FP_Debug("461>>>>>>>>");
--			mode = "10인";
--			FP_MODE_check = nil;
--		end
--	elseif modeDigit and modeDigit == 0 then
--	FP_Debug("466>>>>>>>>");
--		if dungeon_status == "0" then
--		FP_Debug("468>>>>>>>>");
--			mode = "영웅";
--			FP_MODE_check = nil;
--		end
--	elseif modeDigit and modeDigit == 1 then
--	FP_Debug("473>>>>>>>>");
--		if dungeon_status == "0" then
--		FP_Debug("475>>>>>>>>");
--			mode = "일반";
--			FP_MODE_check = nil;
--		end
--	else
		-- 난이도 판단에 영향을 미치는 문자열 제거(별도 함수처리 필요)
		filteredMsg = string.gsub(filteredMsg, "영원", "");
		filteredMsg = string.gsub(filteredMsg, "영눈", "");
		
		for k=1, table.getn(FP_DUNGEON_MODE_ORDER) do
			for n = 1, table.getn(FP_DUNGEON_MODE[FP_DUNGEON_MODE_ORDER[k]]) do
--			FP_Debug("FP_DUNGEON_MODE[FP_DUNGEON_MODE_ORDER[k]][n] : "..FP_DUNGEON_MODE[FP_DUNGEON_MODE_ORDER[k]][n]);
				if string.find(filteredMsg, FP_DUNGEON_MODE[FP_DUNGEON_MODE_ORDER[k]][n]) and FP_MODE_check then
					mode = FP_DUNGEON_MODE_ORDER[k];
					FP_MODE_check = nil;
				end
			end
		end
--	end
	
	if not mode then
--	FP_Debug("495>>>>>>>>");
		mode = "일반";
	end
	if dungeon_status == "1" then
--		if mode == "일반" then mode = "10인"; end
--		if mode == "영웅" then mode = "25인"; end
--		if string.find(filteredMsg, "하드") or string.find(filteredMsg, "HARD") or string.find(filteredMsg, "영웅") then mode = mode.." 영웅"; end	-- 하드 모드의 메시지 조합이 너무 많아서 하드라는 글자만 있으면 하드로 강제 셋팅 2009.09.08 edited by 일분일초 - 스톰레이지 : 추가: hard 라는 글자도 하드로 처리하게 수정 by 영원이란
--		if string.find(filteredMsg, "25H") and mode == "25인" then mode = mode.." 영웅"; end
--		if string.find(filteredMsg, "10H") and mode == "10인" then mode = mode.." 영웅"; end
	elseif dungeon_status == "0" then
--	FP_Debug("505>>>>>>>>");
		mode = "일반";
	end
	--FP_Debug("mode :: "..mode)

	-- 묶이지 않았을 경우만 작동하도록 수정 변경 2009.05.23 edited by 일분일초 - 스톰레이지
	if FP_Options.belong and (dungeon and mode) then
		for j=1, GetNumSavedInstances() do
			local name, id, remaining, difficulty, locked, extended, instanceIDMostSig, isRaid = GetSavedInstanceInfo(j);
			--FP_Debug(name.." "..difficulty.." "..tostring(locked).." "..tostring(extended).." "..tostring(instanceIDMostSig).." "..tostring(isRaid));
			--FP_Debug(tostring(dungeon).." "..tostring(FP_DUNGEON_NUM[mode]));
			
			-- 얼음왕관 성채의 경우 하드와 일반이 귀속을 공유하므로 추가 처리가 필요
			if name == "얼음왕관 성채" then
				if mode == "25인 영웅" and difficulty == 2 then
					difficulty = 4;
				elseif mode == "10인 영웅" and difficulty == 1 then
					difficulty = 3;
				end
			end
			
			-- 던전 및 모드값이 없어도 묶인 id값이 msg에 있으면 귀속던전 제외에서 예외적으로 작동하도록 추가 2009.05.25 by 일분일초 - 스톰레이지 속도 향상을 위한 추가 수정 by 영원이란
			if (string.find(filteredMsg, id)) then
			elseif (name == dungeon and difficulty == FP_DUNGEON_NUM[mode]) then
				--FP_Debug("귀속!!!??? : "..remaining);
--				if remaining == 0 then return dungeon, mode; end -- 인던 중 만료된 인던인 경우 작동 2009.08.17 edited by 호드머리 - 달라란
				if locked == false then return dungeon, mode; end -- 귀속정보 함수에서 뽑아냈어도 귀속되지 않은 함수가 있음.(버그인듯) 이 경우 해당 인스턴스 정보로부터 귀속 여부를 판단하여 비 귀속시 작동시킴 2009.10.05 edited by 일분일초 - 스톰레이지
--				if (string.find(msg, id)) then return dungeon, "귀속"; end	-- 묶였을 경우 묶인 던전 id가 메시지에 있을 경우 작동  2009.05.27 edited by 일분일초 - 스톰레이지
				dungeon = nil;
				mode = nil;
			end
		end
	end
	--FP_Debug(">>>>>>dungeon : "..tostring(dungeon));
	--FP_Debug(">>>>>>>dungeon : "..tostring(dungeon));
	--if(dungeon and string.find(dungeon, "일퀘")) then mode="일퀘"; end
	--FP_Debug("|cffff0000■■■■■■|r"..tostring(dungeon).."|cffff0000■■■■■■|r"..tostring(mode))
--FP_Debug("542>>>>>>>>"..tostring(dungeon)..tostring(mode));
	return  dungeon, mode;

end

function FP_FP_Filter_Class(msg, class, mode)
	--FP_Debug("|cffff0000■■■■■■FP_FP_Filter_Class Start|r");
	if (class=="모두") then return true; end
	--FP_Debug("Filtering : "..msg)
	-- 모두에 있는 문자열이 발견되면 그냥 묻지도 따지지도 말고 문자 반환
	for i=1, table.getn(FP_CLASS_LIST["모두"]) do
		--FP_Debug("Filtered by "..FP_CLASS_LIST[class][i]);
		if string.find(msg, FP_CLASS_LIST["모두"][i]) then
			return true;
		end
	end
	for i=1, table.getn(FP_CLASS_LIST[class]) do
		--FP_Debug("Filtered by "..FP_CLASS_LIST[class][i]);
		if string.find(msg, FP_CLASS_LIST[class][i]) then
			return true;
		end
	end
	--FP_Debug("|cffff0000■■■■■■FP_FP_Filter_Class End|r");
	return false;
end

function FP_DungeonFilter(dungeon, mode)
	--FP_Debug("|cffff0000■■■■■■FP_DungeonFilter Start|r");
	--FP_Debug(dungeon);
	--FP_Debug(mode);
	--FP_Debug(FP_Filter_Dungeon_Info.dungeon);
	--FP_Debug(FP_Filter_Dungeon_Info.mode);
	--FP_Debug(FP_Filter_Dungeon_Info.filtered);
	--if (mode=="귀속") then return true; end	-- 귀속 던전인 경우 어떤 던전이든 상관없이 true. 2009.05.27 edited by 일분일초 - 스톰레이지
	if (FP_Filter_Dungeon_Info.filtered) then
		-- 필터링 함수 수정 by 영원이란
		for d, m in pairs(FP_Filter_Dungeon_Info.dungeons) do
			if (dungeon == d) then
				for k, v in pairs(FP_Filter_Dungeon_Info.dungeons[d]) do
					if ((k == mode) and (v == true)) then
						return true;
					end
				end
			end
		end
		return false;
	end
	--FP_Debug("|cffff0000■■■■■■FP_DungeonFilter End|r");
	return true;
end

function FP_ExceptionFilter(exception)
	--FP_Debug("FP_ExceptionFilter");
	--FP_Debug(dungeon);
	--FP_Debug(mode);
	--FP_Debug(FP_Filter_Dungeon_Info.dungeon);
	--FP_Debug(FP_Filter_Dungeon_Info.mode);
	--ShouterSelected.name
	if (FP_Exceptions) then
		for i=1,#FP_Exceptions,1 do
			if (FP_Exceptions[i]==exception) then
				return false;
			end
		end
	end
	return true;
end

-- 파티찾기 창에 새로운 모집항목을 입력한다.
function FP_AddList(name, displayName, msg, classid)
	--FP_Debug("FP_AddList");
	--FP_Debug("msg : "..msg);
	-- 던전명과 난이도를 알아낸다
	local dungeon, mode = FP_DungeonParse(msg);
  local koClass, class = GetPlayerInfoByGUID(classid);

--	FP_Debug(">>>>>>>>"..tostring(dungeon)..tostring(mode));
	if (dungeon) then
		--FP_Debug("dungeon : name - "..dungeon.." : "..name);
		--FP_Debug("FP_Datas[name] : "..tostring(FP_Datas[name]));
		if (FP_Datas[name]) then
			FP_Datas[name].dungeon = dungeon;
			FP_Datas[name].msg = msg;
			FP_Datas[name].time = 0;
			FP_Datas[name].mode = mode;
		else
			local info = FP_CreateNewShoutingInfo();
			info.name = name;
			info.displayName = displayName;
			info.class = class;
			info.level = nil;
			info.msg = msg;
			info.time = 0;
			info.dungeon = dungeon;
			info.mode = mode;
			table.insert(FP_Datas,info);
			FP_Datas[name] = info;
		end
		FP_Scroll();
	end
end

function FP_RemoveList(name)
	if (FP_Datas[name]) then
		if (ShouterSelected and ShouterSelected.name == name) then
			ShouterSelected = nil;
		end

		for i=1, table.getn(FP_Datas) do
			--FP_Debug("i = "..i.." / "..table.getn(FP_Datas).."  name = "..FP_Datas[i].name.." / "..name);
			if (FP_Datas[i].name == name) then
				--FP_Debug("Matched");
				FP_RestoreShoutingInfo(FP_Datas[i]);
				table.remove(FP_Datas, i);
				break;
			end
		end
		FP_Datas[name] = nil;
		--collectgarbage("collect");
		FP_Scroll();
	end
end

function FP_RemoveAllList()
	FP_Datas = {};
	ShouterSelected = nil;
	InfoDepository = {};

	collectgarbage("collect");
end

function FP_Refresh(quick)
	--FP_Debug("|cffff0000■■■■■■FP_Refresh Start|r");
	local listOffset = FauxScrollFrame_GetOffset(FP_ListFrameScrollFrame);
	if (not listOffset) then listOffset = 0; end

	if (not quick)  then
		local sort_col = FP_Sort_Info.current_sort;
		local ascd = FP_Sort_Info[sort_col];

		FP_ListSort(FP_Datas, sort_col, ascd);
	end

	local dataIdx = listOffset + 1;
	local rowIdx = 1;
	while (rowIdx <= MAX_VIEW_LINE) do
		--FP_Debug("while");
		--FP_Debug("row ="..rowIdx.." data ="..dataIdx);

		local rowName ="FP_ListFrameRow"..tostring(rowIdx);
		local info = nil;
		if (rowIdx <= FP_Scroll_Info.viewLines) then
			info = FP_Datas[dataIdx];
		end

		--FP_Debug("info "..tostring(info));

		if (info) then
			--FP_Debug("FP_DungeonFilter-FP_FP_Filter_Class-FP_ExceptionFilter :: "..tostring(FP_DungeonFilter(info.dungeon, info.mode)).."-"..tostring(FP_FP_Filter_Class(info.msg, FP_Filter_Class)).."-"..tostring(FP_ExceptionFilter(info.name)));
			if (not FP_DungeonFilter(info.dungeon, info.mode) or not FP_FP_Filter_Class(info.msg, FP_Filter_Class, info.mode) or not FP_ExceptionFilter(info.name)) then
				getglobal(rowName):Hide();
				rowIdx = rowIdx - 1;
				FP_Scroll_Info.max = FP_Scroll_Info.max - 1;
				FauxScrollFrame_Update(FP_ListFrameScrollFrame,
				FP_Scroll_Info.max,
				FP_Scroll_Info.viewLines,
				FP_Scroll_Info.height);
				if (info == ShouterSelected) then ShouterSelected = nil; end
			else
				if(info.time<=0) then
					if(FP_Options["activateBellnWindow"]) then
						PlaySoundFile("Interface\\AddOns\\FindParty\\FindParty.ogg");
						FP_Frame:Show();
						info.time=1;
					end
				end
				getglobal(rowName):Show();
				getglobal(rowName):SetID(dataIdx);
				-- Time
				getglobal(rowName.."TimeText"):SetText(info.time);

				--Message
				local msg = info.msg;
				for class, alias in pairs(FP_CLASS_LIST) do
					for i=1, getn(alias) do
						msg = string.gsub(msg, alias[i], "|cffffff00"..alias[i].."|r");
					end
				end

				getglobal(rowName.."MsgText"):SetText(msg);
				getglobal(rowName.."MsgText"):SetWordWrap(enable);

				getglobal(rowName.."DungeonText"):SetText(info.dungeon);

				-- 색처리 세분화 / 수정
				if (info.mode == "25인 영웅") then
					getglobal(rowName.."DungeonText"):SetTextColor(1.0, 0.7, 0.7);
					getglobal(rowName.."DungeonText"):SetText(info.dungeon.."|cffff0000 (H)");
				elseif (info.mode == "25인") then
					getglobal(rowName.."DungeonText"):SetTextColor(1.0, 0.7, 0);
				elseif (info.mode == "10인 영웅") then
					getglobal(rowName.."DungeonText"):SetTextColor(0, 1, 0.7);
					getglobal(rowName.."DungeonText"):SetText(info.dungeon.."|cffff0000 (H)");
				elseif (info.mode == "10인") then
					getglobal(rowName.."DungeonText"):SetTextColor(0, 1, 0);
				--명예 / 귀속 분류 삭제에 따른 주석처리 by 영원이란
				--elseif (info.mode == "명예") then
				--	getglobal(rowName.."DungeonText"):SetTextColor(1, 0, 0);
				elseif (info.mode == "영웅") then
					getglobal(rowName.."DungeonText"):SetTextColor(0.5, 0.5, 0.8);
				--명예 / 귀속 분류 삭제에 따른 주석처리 by 영원이란
				--elseif (info.mode == "귀속") then
				--	getglobal(rowName.."DungeonText"):SetTextColor(1, 0.75, 0.2);
				elseif (info.mode == "신화") then
					getglobal(rowName.."DungeonText"):SetTextColor(1, 0.5, 0);
				else
					getglobal(rowName.."DungeonText"):SetTextColor(1,1,1);
				end

				-- Name
				local name = info.name;
--FP_Debug("모집자 레벨 "..tostring(info.level));
				if (info.level) then name = name.." ("..tostring(info.level)..")"; end
--FP_Debug("모집자 이름 색깔 "..tostring(info.class));
--FP_Debug("모집자 이름 "..tostring(info.name));
--local playerClass, englishClass = UnitClass(name);
--FP_Debug('Your player is a : ' .. playerClass .. '; ' .. englishClass .. '.');
				if (info.class) then
					local color = FP_CLASS_COLORS[info.class];
					if (color) then
						getglobal(rowName.."NameText"):SetTextColor(color.r, color.g, color.b);
					end
				else
					getglobal(rowName.."NameText"):SetTextColor(1,1,1);
				end
				getglobal(rowName.."NameText"):SetText(info.displayName);

				-- Highlight
				if (info == ShouterSelected) then
					getglobal(rowName):LockHighlight();
				else
					getglobal(rowName):UnlockHighlight();
				end
			end
		else
			getglobal(rowName):Hide();
		end -- end of if

		-- for next
		dataIdx = dataIdx + 1;
		rowIdx = rowIdx + 1;
	end -- end of while
	--FP_Debug("|cffff0000■■■■■■FP_Refresh End|r");
end

function FP_Scroll()
	if (not FP_Scroll_Info) then return; end
	FP_Scroll_Info.max = table.getn(FP_Datas);
	FauxScrollFrame_Update(FP_ListFrameScrollFrame, FP_Scroll_Info.max, FP_Scroll_Info.viewLines, FP_Scroll_Info.height);
	--FP_Debug("offset = "..tostring(FauxScrollFrame_GetOffset(FP_ListFrameScrollFrame)));
	FP_Refresh();
end

function FP_ListAdjust(adjust)
	local newNumRow;
	local curNumRow = FP_Scroll_Info.viewLines;
	if (not adjust) then
		local curHeight = FP_ListFrame:GetHeight();
		newNumRow = math.floor((curHeight - 40) / FP_Scroll_Info.height);
	elseif (adjust == INC) then
		newNumRow = math.min(MAX_VIEW_LINE, FP_Scroll_Info.viewLines + 1);
	elseif (adjust == DEC) then
		newNumRow = math.max(MIN_VIEW_LINE, FP_Scroll_Info.viewLines - 1);
	elseif (adjust == MAX) then
		newNumRow =MAX_VIEW_LINE;
	elseif (adjust == MIN) then
		newNumRow =MIN_VIEW_LINE;
	end

--	for i=newNumRow + 1, curNumRow, 1 do
--		getglobal("FP_ListFrameRow"..i):Hide();
--	end

	FP_Scroll_Info.viewLines = newNumRow;

	FP_ListResize();
end

local COLUMFRAME = {"DungeonText", "NameText", "MsgText"};

function FP_FontResize()
	for i=1, MAX_VIEW_LINE do
		rowName = "FP_ListFrameRow"..i;
		for j=1, 3 do
			local tempFrame = getglobal(rowName..COLUMFRAME[j]);
			local fontFile, unused, fontFlags = tempFrame:GetFont();
			tempFrame:SetFont(fontFile, FP_Options.fontsize, fontFlags);
		end
	end
end

function FP_SetListColor()
	FP_ListFrame:SetBackdropColor(FP_Options.color.r, FP_Options.color.g, FP_Options.color.b, FP_Options.color.opacity);
end

function FP_UIResize(scale)
	FP_Frame:SetScale(scale);
end

function FP_ListResize()
	local newListHeight = 40 + FP_Scroll_Info.viewLines * FP_Scroll_Info.height;
	--local newScrollHeight = 15 + FP_Scroll_Info.viewLines * FP_Scroll_Info.height;

	FP_ListFrame:SetHeight(newListHeight);
	-- FP_ListFrameScrollFrame:SetHeight(newScrollHeight)
	--FP_ListFrameScrollFrameMiddle:SetHeight(newScrollHeight - 50);

	FP_Scroll();
end

function FP_SortButtonClicked(self)
	local id = self:GetID();

	FP_Debug("sort "..tostring(id));
	column = Col_Name[id];

	FP_Sort_Info[column] = not FP_Sort_Info[column];
	FP_Sort_Info.current_sort = column;

	FP_Refresh();
	return FP_Sort_Info[column];
end

function FP_ListSort(list, col, ascd)
	if (list ~= nil and col ~= nil) then
		local endIdx = getn(list)
		for i=1, endIdx,1 do
			for j=i+1, endIdx, 1 do
				local pivot = list[i][col];
				local comp = list[j][col];

				if col == "dungeon" then
					pivot = pivot..list[i]["mode"];
					comp = comp..list[j]["mode"];
				end
				if ((ascd and (pivot > comp)) or (not ascd and (pivot < comp))) then
					local temp = list[i];
					list[i] = list[j];
					list[j] = temp;
				end
			end
		end
	end
end

function FP_IsActivated()
	return FP_Options.activated;
end

function FP_IsActiveBellnWindow()
	return FP_Options["activateBellnWindow"];
end

function FP_IconClicked(self, button)
	if (button == "LeftButton") then
		if (IsAltKeyDown()) then
			if (FP_Minimap_Button:IsShown()) then
				FP_Options.iconLocked = not FP_Options.iconLocked;
				if FP_Options.iconLocked then
					FP_Minimap_Button:RegisterForDrag(nil);
					DEFAULT_CHAT_FRAME:AddMessage("|cffffff00미니맵 아이콘을 고정합니다.");
				else
					FP_Minimap_Button:RegisterForDrag("LeftButton");
					DEFAULT_CHAT_FRAME:AddMessage("|cffffff00미니맵 아이콘 고정을 해제합니다.");
				end
			end
		elseif (IsShiftKeyDown()) then
			FP_Activate(not FP_IsActivated());
			FP_Activated_Status = FP_IsActivated();
		elseif (IsControlKeyDown()) then
			if (FP_IsAnnoucing()) then
				FP_StopAnnounce();
			else
				FP_StartAnnounce();
			end
		else
			if (FP_Frame:IsShown()) then
				FP_Frame:Hide()
			else
				FP_Frame:Show();
			end
		end
	elseif (button == "RightButton") then
		FP_GetChannels();
		UIDropDownMenu_Initialize(FP_DropDownMenu, FP_DropDownMenuOption_Initialize, "MENU");
		ToggleDropDownMenu(1, nil, FP_DropDownMenu, self, 0, 0);
	end
end

function FP_MenuClicked(self, button, menu, option)	-- 던전: 클릭 시
	FP_Debug("Menu "..tostring(menu).." "..tostring(option));
	--FP_Debug("click "..tostring(arg1).." / "..tostring(arg2).." //"..tostring(arg3));

	if (menu == "MENU_DUNGEON") then
		UIDropDownMenu_Initialize(FP_DropDownMenu, FP_DropDownMenuFindDungeon_Initialize, "MENU");
		ToggleDropDownMenu(1, nil, FP_DropDownMenu, FP_FindFrameDungeon, 0, 0);
	elseif (menu == "MENU_FILTERDUNGEON") then
		if (button == "LeftButton") then
			local filtered = FP_Filter_Dungeon_Info.filtered;

			if (filtered or (not filtered and FP_Filter_Dungeon_Info.num < 1)) then
				FP_SortButtonClicked(self);
				FP_Filter_Dungeon_Info.filtered = false;
				FP_ListFrameFilterDungeonText:SetText("던전: 모두(정렬)");
			else
				FP_Filter_Dungeon_Info.filtered = true;
				FP_ListFrameFilterDungeonText:SetText("던전: "..FP_GetDungeonFilterDesc());
			end

			FP_Scroll();
		else
			if (button == "RightButton") then
				UIDropDownMenu_Initialize(FP_DropDownMenu, FP_DropDownMenuFilterDungeon_Initialize, "MENU");
				ToggleDropDownMenu(1, nil, FP_DropDownMenu, FP_ListFrameFilterDungeon, 0, 0);
			else
				CloseDropDownMenus();
			end
		end
	elseif (menu=="MENU_CLASS") then
		if (button == "LeftButton") then
			--FP_Debug("class filter "..FP_Filter_Class);
			class = UnitClass("player");
			if (FP_Filter_Class == class) then
				FP_Filter_Class = "모두";
				FP_ListFrameFilterClassText:SetText("직업 골라내기 : "..FP_Filter_Class);
				FP_Scroll();
			else
				FP_Filter_Class = class;
				FP_ListFrameFilterClassText:SetText("직업 골라내기 : "..FP_Filter_Class);
				FP_Scroll();
			end
		else
			if (button == "RightButton") then
				UIDropDownMenu_Initialize(FP_DropDownMenu, FP_DropDownMenuClass_Initialize, "MENU");
			end;
			ToggleDropDownMenu(1, nil, FP_DropDownMenu, FP_ListFrameFilterClass, FP_ListFrameFilterClass:GetWidth()/2, 0);
		end
	elseif (menu=="MENU_OPTION") then
		FP_GetChannels();
		UIDropDownMenu_Initialize(FP_DropDownMenu, FP_DropDownMenuOption_Initialize, "MENU");
		ToggleDropDownMenu(1, nil, FP_DropDownMenu, FP_TitleFrameOption, 0, 0);
	elseif (menu == "MENU_APPLY") then
		if (ShouterSelected) then
			local playerClass = UnitClass("player");
			local msg="";
			local overall, equipped = GetAverageItemLevel();
			if (FP_Options.userdefineWh) then
				msg = FP_FindFrameWhText:GetText().."("..string.format("%s %.f, %s %.f", "평균템렙:",overall,"착용템렙:",equipped)..")";
				FP_UserDefinedWhMsg = msg; -- For save
			else
				local playerClass = UnitClass("player");
				local myTalent = FP_GetMyTalent();
				msg = myTalent.." "..playerClass.." 손 !! ("..string.format("%s %.f, %s %.f", "평균템렙:",overall,"착용템렙:",equipped)..")";
				--msg = playerClass.."["..myTalent.."]".." 손 !!";
			end
			--FP_Debug(msg);
			SendChatMessage(msg, "WHISPER", nil, ShouterSelected.name);
		end
	elseif (menu == "MENU_WHO") then
		if (ShouterSelected) then
--			local ppp=0
--			if string.find(ShouterSelected.name, "[a-z]+") then ppp=1 end
--			if ppp==1 then SendWho(ShouterSelected.name) else SendWho(ShouterSelected.name.."....") end
			SendWho(ShouterSelected.name);
		end
	elseif (menu == "MENU_EXCEPTION") then
		if (ShouterSelected) then
			if ( FP_Exceptions ) then savePlace = #FP_Exceptions+1; end
			FP_Exceptions[savePlace] = ShouterSelected.name

			for i=1,#FP_Exceptions,1 do
				--FP_Debug(FP_Exceptions[i])	
			end
			DEFAULT_CHAT_FRAME:AddMessage("|cffffff00"..ShouterSelected.name.."님의 파티광고를 파티모집 목록에서 제외합니다.");
		end
	elseif (menu == "MENU_EXCEPTION_DELETE") then
		FP_Exceptions = {};	
		DEFAULT_CHAT_FRAME:AddMessage("|cffffff00제외 목록을 초기화 합니다.");
	elseif (menu == "MENU_ANNOUNCE") then
		if (Party_Find_Info.announcing) then
			FP_StopAnnounce();
		else
			FP_StartAnnounce();
		end
	elseif (menu == "MENU_ACTIVATE_BELLNWINDOW") then
		FP_ActiveBellnWindow(FP_Options.activateBellnWindow);
	elseif (menu == "MENU_ACTIVATION") then
		-- --FP_Debug("Activation changed");
		FP_Activate(not FP_Options.activated);
		FP_Activated_Status = FP_Options.activated;
	elseif (menu == "MENU_INC") then
		FP_ListAdjust(INC);
	elseif (menu == "MENU_DEC") then
		FP_ListAdjust(DEC);
	elseif (menu == "MENU_MAX") then
		FP_ListAdjust(MAX);
	elseif (menu == "MENU_MIN") then
		FP_ListAdjust(MIN);
	elseif (menu == "MENU_INFO") then
		for i=1, table.getn(FP_HELPS) do
			-- 정보 버튼 활성화 by 영원이란
			DEFAULT_CHAT_FRAME:AddMessage(FP_HELPS[i]);
			--FP_Debug(FP_HELPS[i]);
		end
	elseif (menu == "SEL_SHOUT") then
		local index = self:GetID();
		local data = FP_Datas[index];

		if (button == "LeftButton") then
			if (IsAltKeyDown()) then
				ShouterSelected = data;
				local playerClass = UnitClass("player");
				local msg="";
				local overall, equipped = GetAverageItemLevel();
				if (FP_Options.userdefineWh) then
					msg = FP_FindFrameWhText:GetText().."("..string.format("%s %.f, %s %.f", "평균템렙:",overall,"착용템렙:",equipped)..")";
					FP_UserDefinedWhMsg = msg; -- For save
				else
					local playerClass = UnitClass("player");
					local myTalent = FP_GetMyTalent();
					msg = myTalent.." "..playerClass.." 손 !! ("..string.format("%s %.f, %s %.f", "평균템렙:",overall,"착용템렙:",equipped)..")";
					--msg = playerClass.."["..myTalent.."]".." 손 !!";
				end
				--FP_Debug(msg);
			SendChatMessage(msg, "WHISPER", nil, ShouterSelected.name);
			elseif (IsShiftKeyDown()) then
				ShouterSelected = data;
				SendWho(ShouterSelected.name);
			elseif (IsControlKeyDown()) then
				ShouterSelected = data;
				if ( FP_Exceptions ) then savePlace = #FP_Exceptions+1; end
				FP_Exceptions[savePlace] = ShouterSelected.name

				for i=1,#FP_Exceptions,1 do
					--FP_Debug(FP_Exceptions[i])	
				end
				DEFAULT_CHAT_FRAME:AddMessage("|cffffff00"..ShouterSelected.name.."님의 파티광고를 파티모집 목록에서 제외합니다.");
			else
				if (ShouterSelected == data) then
					ShouterSelected = nil;
				else
					ShouterSelected = data;
				end
			end
			FP_Refresh();
--		elseif ((button == "RightButton") and (FP_Options.rightButton == true)) then  -- 우클릭 파티신청 기능 제거(귓말 텍스트 입력 창 오픈 기능으로 변경)
    elseif ((button == "RightButton")) then
			ShouterSelected = data;
-- 우클릭 파티신청 기능 제거(귓말 텍스트 입력 창 오픈 기능으로 변경)
--			local msg="";
--			local overall, equipped = GetAverageItemLevel();
--			if (FP_Options.userdefineWh) then
--				msg = FP_FindFrameWhText:GetText().."("..string.format("%s %.f, %s %.f", "평균템렙:",overall,"착용템렙:",equipped)..")";
--				FP_UserDefinedWhMsg = msg; -- For save
--			else
--				local playerClass = UnitClass("player");
--				local myTalent = FP_GetMyTalent();
--				msg = myTalent.." "..playerClass.." 손 !! ("..string.format("%s %.f, %s %.f", "평균템렙:",overall,"착용템렙:",equipped)..")";
--				--msg = playerClass.."["..myTalent.."]".." 손 !!";
--			end
--			--FP_Debug(msg);
--			SendChatMessage(msg, "WHISPER", nil, ShouterSelected.name);

--    우클릭 귓말 텍스트 입력 창 오픈 기능
      local chatFrame = SELECTED_DOCK_FRAME
      if not chatFrame then
        chatFrame = DEFAULT_CHAT_FRAME;
      end
    
      local editBox = ChatFrame_OpenChat("", chatFrame);
      editBox:SetText(SLASH_WHISPER1.." "..ShouterSelected.name.." ");

		end
	elseif (menu=="SEL_ETC") then
		FP_Options.userdefine = option;
	elseif (menu=="SEL_ETC2") then
		FP_Options.userdefineWh = option;
		--Party_Find_Info.userdefineWh = option;
		elseif (menu=="SEL_WARRIOR") then FP_Party_Find_Class( "전사", option);
		elseif (menu=="SEL_PRIEST") then FP_Party_Find_Class("사제", option);
		elseif (menu=="SEL_PALADIN") then FP_Party_Find_Class("성기사", option);
		elseif (menu=="SEL_MAGE") then FP_Party_Find_Class("마법사", option);
		elseif (menu=="SEL_WARROCK") then FP_Party_Find_Class("흑마법사", option);
		elseif (menu=="SEL_HUNTER") then FP_Party_Find_Class("사냥꾼", option);
		elseif (menu=="SEL_DRUID") then FP_Party_Find_Class("드루이드", option);
		elseif (menu=="SEL_ROGUE") then FP_Party_Find_Class("도적", option);
		elseif (menu=="SEL_SHAMAN") then FP_Party_Find_Class("주술사", option);
		elseif (menu=="SEL_DEATHKNIGHT") then FP_Party_Find_Class("죽음의 기사", option);
	end
end

function FP_GetMyTalent()

	local currentSpec = GetSpecialization();
	local currentSpecName = currentSpec and select(2, GetSpecializationInfo(currentSpec)) or "None";

	FP_Debug(tostring(currentSpecName));

	return currentSpecName;
end

-- 클래스 드롭다운 메뉴 --
function FP_DropDownMenuClass_Initialize(frame, level)
	local info = UIDropDownMenu_CreateInfo();

	info.func = FP_ClassSelected;

	for key, subarray in pairs(FP_CLASS_LIST) do
		info.text = key;
		info.value = key;
		info.checked = (key == FP_Filter_Class);
		UIDropDownMenu_AddButton(info);
	end -- for key, subarray
	info.text = "";
	info.disabled = true;
	info.checked = false;
	info.hasArrow = false;
	UIDropDownMenu_AddButton(info, level);

	info.text = "닫기";
	info.keepShownOnClick = false;
	info.func=nil;
	info.disabled = false;
	UIDropDownMenu_AddButton(info, level);
end

function FP_ClassSelected(self)
	--FP_Debug("class sected "..??);
	if self.value then
		local class = self.value;
		FP_Filter_Class = class;
		--FP_Debug("class filter = "..FP_Filter_Class);
		FP_Scroll();
	end

	FP_ListFrameFilterClassText:SetText("직업 골라내기 : "..FP_Filter_Class);
end

function FP_GetClassFilterInfo()
	return FP_Filter_Class;
end

-- 파티 자동 광고 기능 수정 by 영원이란--
function FP_Party_Find_Class(class, selected)
	local temp = Party_Find_Info.class;
	if (selected) then
		table.insert(temp, class);
	else
		for i=1, table.getn(temp) do
			if (temp[i]==class) then
				table.remove(temp, i);
				break;
			end
		end
	end
end

function FP_Announce()
	--FP_Debug("파티모으기 "..tostring(Party_Find_Info.dungeon).."  "..tostring(table.getn(Party_Find_Info.class)));
	local msg = "";

	if (FP_Options.userdefine) then
		msg = FP_FindFrameAdText:GetText();
		FP_UserDefinedAdMsg = msg; -- For save
		if (not msg or string.len(msg) == 0) then
			-- 알림 메세지 by 영원이란
			DEFAULT_CHAT_FRAME:AddMessage("|cffffff00광고글을 작성하셔야 합니다.");
			FP_StopAnnounce();
			return;
		end
	else
		if (Party_Find_Info.selected and table.getn(Party_Find_Info.class) > 0) then
			if Party_Find_Info.mode then
				msg = Party_Find_Info.dungeon.." ("..Party_Find_Info.mode..")";
			else
				msg = Party_Find_Info.dungeon;
			end
			msg = msg.." -->";
			for v,k in pairs(Party_Find_Info.class) do
				msg = msg.." "..k;
			end
			msg = msg.." <-- 오세요";
		else
			-- 알림 메세지 by 영원이란.
			DEFAULT_CHAT_FRAME:AddMessage("|cffffff00던전을 선택하고 클래스가 최소한 1개 이상 선택되어야 합니다.");
			FP_StopAnnounce();
			return;
		end
	end

	--FP_Debug(msg);
	for k,v in pairs(FP_Options.channel) do
		if (v) then
			local chaNum = GetChannelName(k);
			SendChatMessage(msg, "CHANNEL",  nil, chaNum);
		end
	end
end

function FP_StartAnnounce()
	DEFAULT_CHAT_FRAME:AddMessage("|cffffff00파티 모으기를 시작합니다.");

	announce_timer = GetTime() * 1000;
	Party_Find_Info.announcing = true;

	FP_FindFrameAnnounce:SetText("광고 중단");
	FP_TitleFrameAnnouncing:SetNormalTexture("Interface\\Icons\\INV_Misc_GroupNeedMore");

	FP_Announce();
end

function FP_StopAnnounce()
	DEFAULT_CHAT_FRAME:AddMessage("|cffffff00파티 모으기를 중단합니다.");
	Party_Find_Info.announcing = false;

	FP_FindFrameAnnounce:SetText("광고 시작");
	FP_TitleFrameAnnouncing:SetNormalTexture("Interface\\Icons\\INV_Misc_GroupLooking");
end

function FP_IsAnnoucing()
	return Party_Find_Info.announcing;
end

function FP_FindDungeonSelected(self)
	if self.value then
		if self.value.Dungeon then dungeon = self.value.Dungeon end;
		if self.value.Zone then zone = self.value.Zone end;
		if self.value.Mode then mode = self.value.Mode end;

		if dungeon then
			if mode then
				if Party_Find_Info.dungeon == dungeon and Party_Find_Info.mode == mode then
					FP_FindDungeonClear();
				else
					FP_FindDungeonAdd(zone, dungeon, mode);
				end
			else
				if Party_Find_Info.dungeon == dungeon then
					FP_FindDungeonClear();
				else
					FP_FindDungeonAdd(zone, dungeon, mode);
				end
			end
		else
			if Party_Find_Info.zone and zone then
				if Party_Find_Info.zone == zone then
					FP_FindDungeonClear();
				end
			end
		end
		
		if UIDROPDOWNMENU_MENU_LEVEL == 1 then
			local menu_cnt = 0;
			for c, n in pairs(FP_DUNGEON_LIST) do
				menu_cnt = menu_cnt + 1;
			end
			for i=1, menu_cnt do
				local button = getglobal("DropDownList1Button"..i);
				button.checked = false;
				getglobal("DropDownList1Button"..i.."Check"):Hide();
			end
		end
	end
	
	FP_FindDungeonAddColor();
end

function FP_FindDungeonAddColor()
	-- 프레임 색처리 세분화 / 수정
	if Party_Find_Info.mode then
		if (Party_Find_Info.mode == "25인 영웅") then
			FP_FindFrameDungeonNameText:SetTextColor(1.0, 0.7, 0.7);
		elseif (Party_Find_Info.mode == "25인") then
			FP_FindFrameDungeonNameText:SetTextColor(1.0, 0.7, 0);
		elseif (Party_Find_Info.mode == "10인 영웅") then
			FP_FindFrameDungeonNameText:SetTextColor(0, 1, 0.7);
		elseif (Party_Find_Info.mode == "10인") then
			FP_FindFrameDungeonNameText:SetTextColor(0, 1, 0);
		elseif (Party_Find_Info.mode == "영웅") then
			FP_FindFrameDungeonNameText:SetTextColor(0.5, 0.5, 0.8);
		elseif (Party_Find_Info.mode == "신화") then
			FP_FindFrameDungeonNameText:SetTextColor(1.0, 0.5, 0);
			
		else
			FP_FindFrameDungeonNameText:SetTextColor(1,1,1);
		end
	else
		FP_FindFrameDungeonNameText:SetTextColor(1,1,1);
	end
end

function FP_FindDungeonAdd(zone, dungeon, mode)
	Party_Find_Info.zone = zone;
	Party_Find_Info.dungeon = dungeon;
	Party_Find_Info.selected = true;
	if mode then
		Party_Find_Info.mode = mode;
		FP_FindFrameDungeonNameText:SetText(Party_Find_Info.dungeon.." ("..Party_Find_Info.mode..")");
	else
		Party_Find_Info.mode = nil;
		FP_FindFrameDungeonNameText:SetText(Party_Find_Info.dungeon);
	end
	ToggleDropDownMenu(1, nil, FP_DropDownMenu, FP_FindFrameDungeon, 0, 0);
end

function FP_FindDungeonClear()
	Party_Find_Info.zone = nil;
	Party_Find_Info.dungeon = nil;
	Party_Find_Info.mode = nil;
	Party_Find_Info.selected = false;
	FP_FindFrameDungeonNameText:SetText("선택해주세요");
	FP_FindFrameDungeonNameText:SetTextColor(1,1,1);
	ToggleDropDownMenu(1, nil, FP_DropDownMenu, FP_FindFrameDungeon, 0, 0);
end

function FP_DropDownMenuFindDungeon_Initialize(frame, level)
	FP_DropDownMenuDungeon_Initialize(
		self,
		level,
		{},
		FP_FindDungeonSelected,
		DropDownMenuFindDungeonCheck
	);
end

function DropDownMenuFindDungeonCheck(level, key, upLevelKey)
	if (level == 1) then
		return Party_Find_Info.zone == key;
	elseif (level == 2) then
		return Party_Find_Info.dungeon == key;
	elseif (level == 3) then
		return Party_Find_Info.dungeon == upLevelKey
		and
		Party_Find_Info.mode == key;
	end
end

function FP_DropDownMenuDungeon_Initialize(frame, level, info, targetFunc, checkFunc)
	level = level or 1;
	if (not checkFunc) then checkFunc = function() return false; end end

	if (level == 1) then
		info.hasArrow = true; -- creates submenu
		info.notCheckable = false;
		info.func = targetFunc;
		info.keepShownOnClick = true;

		for key, subarray in pairs(FP_DUNGEON_LIST) do
			info.text = key;
			info.checked = checkFunc(level, key);
			info.value = {
				["Zone"] = key,
				["level"] = level
			};
			UIDropDownMenu_AddButton(info, level);
		end -- for key, subarray

		info.text = "";
		info.disabled = true;
		info.func = nil;
		info.checked = false;
		info.hasArrow = false;
		UIDropDownMenu_AddButton(info, level);

		info.text = "닫기";
		info.keepShownOnClick = false;
		info.disabled = false;
		UIDropDownMenu_AddButton(info, level);

	end -- if level 1

	if (level == 2) then
		-- getting values of first menu
		local Level1_Key = UIDROPDOWNMENU_MENU_VALUE["Zone"];
		-- 공격대 순서대로 정렬을 위한 수정 - by 영원이란
		local raid_ckeck = false;
		local raid_count = 0;
		if (Level1_Key == "공격대") then
			for k, v in pairs(FP_DUNGEON_LIST["공격대"]) do
				raid_count = raid_count + 1;
			end
			if (raid_count == 24) then
				subarray = FP_RAID_LIST;
				raid_check = true;
			else
				subarray = FP_DUNGEON_LIST["공격대"];
				raid_check = false;
			end
		else
			subarray = FP_DUNGEON_LIST[Level1_Key];
			raid_check = false;
		end
		if (subarray) then
			if (raid_check) then
				info.hasArrow = true;
				info.func = targetFunc;

				for key, subsubarray in pairs(subarray) do
					info.text = subsubarray;
					info.checked = checkFunc(level, subsubarray);
					info.value = {
						["Zone"] = Level1_Key,
						["Dungeon"] = subsubarray,
						["level"] = level
					};
					UIDropDownMenu_AddButton(info, level);
				end -- for key,subsubarray
			else
				-- 아제로스 분류는 난이도 선택이 없으므로 삭제, 공격대 분류 상위로 이동 by 영원이란
				--info.hasArrow = (Level1_Key == "아웃랜드" or Level1_Key == "노스렌드" or Level1_Key == "공격대"); -- no submenues this time
				info.hasArrow = (Level1_Key == "공격대"); -- no submenues this time
				info.func = targetFunc;

				for key, subsubarray in pairs(subarray) do
					--info.notCheckable = (Level1_Key == "아웃랜드");
					info.text = key;
					info.checked = checkFunc(level, key);
					info.value = {
						["Zone"] = Level1_Key,
						["Dungeon"] = key,
						["level"] = level
					};
					UIDropDownMenu_AddButton(info, level);
				end -- for key,subsubarray
			end
		end
	end -- if level 2

	if (level == 3) then
		if (inputEditBox) then inputEditBox:Hide(); end
		local Level1_Key = UIDROPDOWNMENU_MENU_VALUE["Zone"];
		local Level2_Key = UIDROPDOWNMENU_MENU_VALUE["Dungeon"];
		info.func = targetFunc;

		--목록 던전 순서를 맞추기 위해 배열을 하나 더 만듬 by 영원이란
		--for key, subarray in pairs(FP_DUNGEON_MODE) do
		for key, subarray in pairs(FP_DUNGEON_MODE_ORDER) do
			--info.text = Level2_Key.." "..key;
			info.text = Level2_Key.." "..subarray;
			--info.checked = checkFunc(level, key, Level2_Key);
			info.checked = checkFunc(level, subarray, Level2_Key);
			info.value = {
				["Zone"] = Level1_Key,
				["Dungeon"] = Level2_Key,
				--["Mode"] = key,
				["Mode"] = subarray,
				["level"] = level
			};
			UIDropDownMenu_AddButton(info, level);
		end
	end
end

-- 던전 필터링 처리 함수 재작성 by 영원이란
function FP_FilterDungeonSelected(self)
	if (self.value) then
		if (self.value == "resetall") then
			FP_Filter_Dungeon_Info.dungeons = {};
			FP_Filter_Dungeon_Info.zones = {};
			FP_Filter_Dungeon_Info.filtered = false;
			FP_Filter_Dungeon_Info.num = 0;
		else
			FP_Filter_Dungeon_Info.filtered = true;

			local zone = self.value.Zone;
			local dungeon = self.value.Dungeon;
			local mode = self.value.Mode;
			
			-- 필터링 체크 재작성 및 FP_Filter_Dungeon_Info 구조 변경 by 영원이란
			-- mode 값이 있는 경우 : 난이도 전체 선택(1레벨), 던전별 난이도 세부 선택(3레벨)
			if (mode) then
				-- 1, 3 레벨 구분 : zone 값이 있으면 던전 난이도를 세부 선택한 3레벨이다.
				if (zone) then
					-- 필터 DB 에서 비교, 이미 던전이 필터에 있으므로 체크 난이도 제거 또는 추가
					if (dungeon and FP_Filter_Dungeon_Info.dungeons[dungeon]) then
						-- 필터 DB에서 체크 난이도가 존재하는지 확인. 확인 될 경우 제거
						if (FP_Filter_Dungeon_Info.dungeons[dungeon][mode] == true) then
							FP_Filter_Dungeon_Info.dungeons[dungeon][mode] = false;
							-- 필터 DB에서 체크 난이도를 제거하고 나서 모든 난이도가 체크 해제 될 경우 해당 던전을 DB에서 완전히 제거
							local cnt = 0;
							for k, v in pairs(FP_Filter_Dungeon_Info.dungeons[dungeon]) do
								if (v == true) then
									cnt = cnt + 1;
								end
							end
							if (cnt == 0) then
								FP_Filter_Dungeon_Info.dungeons[dungeon] = nil;
								local chk = 0;
								for k, v in pairs(FP_DUNGEON_LIST[zone]) do
									for v, j in pairs(FP_Filter_Dungeon_Info.dungeons) do
										if (v == k) then
											chk = chk + 1;
										end
									end
								end
								if (chk == 0) then
									FP_Filter_Dungeon_Info.zones[zone] = nil;
								end
								FP_Filter_Dungeon_Info.num = FP_Filter_Dungeon_Info.num - 1;
								FP_Filter_Dungeon_Info.filtered = not (FP_Filter_Dungeon_Info.num == 0);
							end
						-- 필터 DB에 체크 난이도를 추가
						else
							FP_Filter_Dungeon_Info.dungeons[dungeon][mode] = true
						end
					-- 필터 DB에 없으므로 체크 던전 및 난이도를 필터 DB에 추가
					else
						if (FP_Filter_Dungeon_Info.dungeons[dungeon] == nil) then
							--FP_Filter_Dungeon_Info.dungeons[dungeon] = {["25인 영웅"] = false, ["25인"] = false, ["10인 영웅"] = false, ["10인"] = false, ["영웅"] = false, ["일반"] = false, ["loc"] = false};
							FP_Filter_Dungeon_Info.dungeons[dungeon] = {["신화"] = false, ["영웅"] = false, ["일반"] = false, ["loc"] = false};
						end
						FP_Filter_Dungeon_Info.dungeons[dungeon][mode] = true;
						FP_Filter_Dungeon_Info.dungeons[dungeon]["loc"] = zone;
						FP_Filter_Dungeon_Info.zones[zone] = true;
						FP_Filter_Dungeon_Info.num = FP_Filter_Dungeon_Info.num + 1;
					end
				-- 1레벨 처리 부분 : 난이도 전체 선택
				else
					-- 난이도 전체 선택을 이미 했을 경우 취소. 토글형임 // zones 사용
					-- 필터 DB를 검색해서 해당 난이도를 전부 false 로 바꾼다
					if (FP_Filter_Dungeon_Info.zones[mode] == true) then
						for k, v in pairs(FP_Filter_Dungeon_Info.dungeons) do
							FP_Filter_Dungeon_Info.dungeons[k][mode] = false;
							-- 필터 DB 에서 해당 난이도를 제거하고 나서 모든 난이도가 체크 해제 될 경우 해당 던전을 DB에서 완전히 제거
							local cnt = 0;
							local temp = FP_Filter_Dungeon_Info.dungeons[k]["loc"];
							for v, j in pairs(FP_Filter_Dungeon_Info.dungeons[k]) do
								if (j == true) then
									cnt = cnt + 1;
								end
							end
							if (cnt == 0) then
								FP_Filter_Dungeon_Info.dungeons[k] = nil;
								local chk = 0;
								for t, n in pairs(FP_DUNGEON_LIST[temp]) do
									for n, p in pairs(FP_Filter_Dungeon_Info.dungeons) do
										if (n == t) then
											chk = chk + 1;
										end
									end
								end
								if (chk == 0) then
									FP_Filter_Dungeon_Info.zones[temp] = nil;
								end
							end
						end
						-- 필터된 갯수 재 계산
						FP_Filter_Dungeon_Info.num = 0;
						for a, b in pairs(FP_Filter_Dungeon_Info.dungeons) do
							FP_Filter_Dungeon_Info.num = FP_Filter_Dungeon_Info.num + 1;
						end
						FP_Filter_Dungeon_Info.filtered = not (FP_Filter_Dungeon_Info.num == 0);
						FP_Filter_Dungeon_Info.zones[mode] = nil;
					-- 선택된 난이도를 필터 DB에 추가 던전 목록을 전부 검색하여 필터 DB에 추가한다. (난이도는 아웃랜드, 노스렌드, 공격대 던전에만 해당)
					else
						for k, v in pairs(FP_DUNGEON_LIST) do
							--if (k == "아웃랜드" or k == "노스렌드" or  k == "공격대") then
							if (k == "공격대") then
								for v, j in pairs(FP_DUNGEON_LIST[k]) do
									if (FP_Filter_Dungeon_Info.dungeons[v] == nil) then
										--FP_Filter_Dungeon_Info.dungeons[v] = {["25인 영웅"] = false, ["25인"] = false, ["10인 영웅"] = false, ["10인"] = false, ["영웅"] = false, ["일반"] = false, ["loc"] = false};
										FP_Filter_Dungeon_Info.dungeons[v] = {["신화"] = false, ["영웅"] = false, ["일반"] = false, ["loc"] = false};
									end
									FP_Filter_Dungeon_Info.dungeons[v][mode] = true;
									FP_Filter_Dungeon_Info.dungeons[v]["loc"] = k;
									FP_Filter_Dungeon_Info.zones[k] = true;
								end
							end
						end
						-- 필터된 갯수 재 계산
						FP_Filter_Dungeon_Info.num = 0;
						for a, b in pairs(FP_Filter_Dungeon_Info.dungeons) do
							FP_Filter_Dungeon_Info.num = FP_Filter_Dungeon_Info.num + 1;
						end
						FP_Filter_Dungeon_Info.filtered = not (FP_Filter_Dungeon_Info.num == 0);
						FP_Filter_Dungeon_Info.zones[mode] = true;
					end
				end
			-- mode 값이 없는 경우 : 지역 전체 선택(1레벨), 던전 전체 선택(2레벨)
			else
				-- 1, 2레벨 구분 : dungeon 값이 있으면 던전을 전체 선택한 2레벨이다.
				if (dungeon) then
					-- 이미 DB에 있는 던전인가? 그렇구나. 그럼 제거 하자.
					if (FP_Filter_Dungeon_Info.dungeons[dungeon]) then
						FP_Filter_Dungeon_Info.dungeons[dungeon] = nil;
						local chk = 0;
						for k, v in pairs(FP_DUNGEON_LIST[zone]) do
							for v, j in pairs(FP_Filter_Dungeon_Info.dungeons) do
								if (v == k) then
									chk = chk + 1;
								end
							end
						end
						if (chk == 0) then
							FP_Filter_Dungeon_Info.zones[zone] = nil;
						end
						FP_Filter_Dungeon_Info.num = FP_Filter_Dungeon_Info.num - 1;
						FP_Filter_Dungeon_Info.filtered = not (FP_Filter_Dungeon_Info.num == 0);
					-- 아니네~ 그럼 추가하자.
					else
						FP_Filter_Dungeon_Info.dungeons[dungeon] = {["신화"] = true, ["영웅"] = true, ["일반"] = true, ["loc"] = zone};
						FP_Filter_Dungeon_Info.zones[zone] = true;
						FP_Filter_Dungeon_Info.num = FP_Filter_Dungeon_Info.num + 1;
					end
				-- 1레벨 처리 부분 : 지역 전체 선택
				else
					-- 세부 항목이 하나라도 선택되어 있을 경우 전체 삭제. zones 이용
					if (FP_Filter_Dungeon_Info.zones[zone] == true) then
						for k,v in pairs(FP_DUNGEON_LIST[zone]) do
							FP_Filter_Dungeon_Info.dungeons[k] = nil;
						end
						-- 필터된 갯수 재 계산
						FP_Filter_Dungeon_Info.num = 0;
						for a, b in pairs(FP_Filter_Dungeon_Info.dungeons) do
							FP_Filter_Dungeon_Info.num = FP_Filter_Dungeon_Info.num + 1;
						end
						FP_Filter_Dungeon_Info.filtered = not (FP_Filter_Dungeon_Info.num == 0);
						FP_Filter_Dungeon_Info.zones[zone] = nil;
					-- 없으면 지역 아래 던전 전체 DB에 추가
					else
						for k,v in pairs(FP_DUNGEON_LIST[zone]) do
							FP_Filter_Dungeon_Info.dungeons[k] = {["신화"] = true, ["영웅"] = true, ["일반"] = true, ["loc"] = zone};
						end
						-- 필터된 갯수 재 계산
						FP_Filter_Dungeon_Info.num = 0;
						for a, b in pairs(FP_Filter_Dungeon_Info.dungeons) do
							FP_Filter_Dungeon_Info.num = FP_Filter_Dungeon_Info.num + 1;
						end
						FP_Filter_Dungeon_Info.filtered = not (FP_Filter_Dungeon_Info.num == 0);
						FP_Filter_Dungeon_Info.zones[zone] = true;
					end
				end
			end

			-- For GUI (동기화를 위해 코드 새로 작성)
			ToggleDropDownMenu(self.value.level + 1, self.value, FP_DropDownMenu, self, 0, 0, nil, self);
			ToggleDropDownMenu(self.value.level + 1, self.value, FP_DropDownMenu, self, 0, 0, nil, self);

			if (self.value.level == 1) then
				local menu_cnt = 0;
				for c, n in pairs(FP_DUNGEON_LIST) do
					menu_cnt = menu_cnt + 1;
				end
				local dun_cnt = 0;
				for a, b in pairs(FP_Filter_Dungeon_Info.dungeons) do
					dun_cnt = dun_cnt + 1;
				end
				if (dun_cnt == 0) then
					FP_Filter_Dungeon_Info.zones = {};
				end
				for i=1, menu_cnt + 9 do
					local button = getglobal("DropDownList1Button"..i);
					local text = button.value.Zone or button.value.Mode;
					local btn1_chk = false;
					for k, v in pairs(FP_Filter_Dungeon_Info.zones) do
						if (k == text) then
							btn1_chk = true;
						end
					end
					if (btn1_chk == true) then
						button.checked = true;
						getglobal("DropDownList1Button"..i.."Check"):Show();
					else
						button.checked = false;
						getglobal("DropDownList1Button"..i.."Check"):Hide();
					end
				end
			end

			if (self.value.level == 2) then
				local btn2_chk = 0;
				for i=1, UIDROPDOWNMENU_MAXBUTTONS do
					local button = getglobal("DropDownList2Button"..i);
					if (button.checked) then
						btn2_chk = btn2_chk + 1;
					end
				end
				local point, upLevelButton = self:GetParent():GetPoint();
				if (upLevelButton.checked) then
					if (btn2_chk == 0) then
						upLevelButton.checked = nil;
						getglobal(upLevelButton:GetName().."Check"):Hide();
					end
				else
					if (btn2_chk ~= 0) then
						upLevelButton.checked = true;
						getglobal(upLevelButton:GetName().."Check"):Show();
					end
				end
				local dun_cnt = 0;
				for a, b in pairs(FP_Filter_Dungeon_Info.dungeons) do
					dun_cnt = dun_cnt + 1;
				end
				if (dun_cnt == 0) then
					FP_Filter_Dungeon_Info.zones = {};
					for i=2, 7 do
						local mode_btn = getglobal("DropDownList1Button"..i);
						mode_btn.checked = false;
						getglobal("DropDownList1Button"..i.."Check"):Hide();
					end
				end
			end

			if (self.value.level == 3) then
				local btn2_chk = 0;
				local btn3_chk = 0;
				for i=1, UIDROPDOWNMENU_MAXBUTTONS do
					local button = getglobal("DropDownList3Button"..i);
					if (button.checked) then
						btn3_chk = btn3_chk + 1;
					end
				end
				local point, upLevelButton = self:GetParent():GetPoint();
				local point2, upLevelButton2 = upLevelButton:GetParent():GetPoint();
				if (upLevelButton.checked) then
					if (btn3_chk == 0) then
						upLevelButton.checked = nil;
						getglobal(upLevelButton:GetName().."Check"):Hide();
						for j=1, UIDROPDOWNMENU_MAXBUTTONS do
							local button2 = getglobal("DropDownList2Button"..j);
							if (button2.checked) then
								btn2_chk = btn2_chk + 1;
							end
						end
						if (btn2_chk == 0) then
							upLevelButton2.checked = nil;
							getglobal(upLevelButton2:GetName().."Check"):Hide();
						end
					end
				else
					if (btn3_chk ~= 0) then
						upLevelButton.checked = true;
						upLevelButton2.checked = true;
						getglobal(upLevelButton:GetName().."Check"):Show();
						getglobal(upLevelButton2:GetName().."Check"):Show();
					end
				end
				local dun_cnt = 0;
				for a, b in pairs(FP_Filter_Dungeon_Info.dungeons) do
					dun_cnt = dun_cnt + 1;
				end
				if (dun_cnt == 0) then
					FP_Filter_Dungeon_Info.zones = {};
					for i=2, 7 do
						local mode_btn = getglobal("DropDownList1Button"..i);
						mode_btn.checked = false;
						getglobal("DropDownList1Button"..i.."Check"):Hide();
					end
				end
			end
		end -- end of if (self.value=="resetall")...
	end -- end of if (self.value) then...

	FP_ListFrameFilterDungeonText:SetText("던전: "..FP_GetDungeonFilterDesc());
end

-- 필터링 함수의 변경으로 인해 필터 문자열을 얻어오는 함수도 전체적으로 수정하였다. by 영원이란
function FP_GetDungeonFilterDesc()
	local desc = "모두(정렬)";

	if (FP_Filter_Dungeon_Info.filtered) then
		if (FP_Filter_Dungeon_Info.num > 15) then
			desc = "15곳 초과";
		else
			desc = "";
			count = 0;
			for d, m in pairs(FP_Filter_Dungeon_Info.dungeons) do
				if (count > 0) then desc = desc..","; end
				desc = desc..d;
				--FP_Debug("desc = "..desc);
				--if (m and (m.loc == "아웃랜드" or m.loc == "노스렌드" or m.loc == "공격대")) then
				if (m and (m.loc == "공격대")) then
					desc2 = "(";
					count2 = 0;
					if (m["일반"] == true) then
						if (count2 > 0) then desc2 = desc2..","; end
						desc2 = desc2.."N";
						count2 = count2 + 1;
					end
					if (m["영웅"] == true) then
						if (count2 > 0) then desc2 = desc2..","; end
						desc2 = desc2.."H";
						count2 = count2 + 1;
					end
					if (m["신화"] == true) then
						if (count2 > 0) then desc2 = desc2..","; end
						desc2 = desc2.."M";
						count2 = count2 + 1;
					end
--					if (m["10인"] == true) then
--						if (count2 > 0) then desc2 = desc2..","; end
--						desc2 = desc2.."10";
--						count2 = count2 + 1;
--					end
--					if (m["25인"] == true) then
--						if (count2 > 0) then desc2 = desc2..","; end
--						desc2 = desc2.."25";
--						count2 = count2 + 1;
--					end
--					if (m["10인 영웅"] == true) then
--						if (count2 > 0) then desc2 = desc2..","; end
--						desc2 = desc2.."10H";
--						count2 = count2 + 1;
--					end
--					if (m["25인 영웅"] == true) then
--						if (count2 > 0) then desc2 = desc2..","; end
--						desc2 = desc2.."25H";
--						count2 = count2 + 1;
--					end
--					if (m["탄력"] == true) then
--						if (count2 > 0) then desc2 = desc2..","; end
--						desc2 = desc2.."탄력";
--						count2 = count2 + 1;
--					end
					desc2 = desc2..")";
					if (count2 == 6) then
						desc2 = "(전체)";
					end
					desc = desc..desc2;
					FP_Debug("desc = "..desc);
				end
				count = count + 1
			end
			if (count == 0) then
				desc = "선택 없음";
			end
			if (count > 1) then
				desc = count.."곳:"..desc;
			end
		end
	end
	return desc;
end

function FP_DropDownMenuFilterDungeon_Initialize(frame, level)
	level = level or 1;
	local info = {};
	info.func = FP_FilterDungeonSelected;
	info.keepShownOnClick = true;

	if (level == 1) then
		info.text = "난이도별 선택";
		info.notCheckable = true;
		info.isTitle = true;
		UIDropDownMenu_AddButton(info, level);

		info.disabled = false;
		info.notCheckable = false;
		info.isTitle = false;
		--목록 던전 순서를 맞추기 위해 배열을 하나 더 만듬 by 영원이란
		--for key, subarray in pairs(FP_DUNGEON_MODE) do
		for key, subarray in pairs(FP_DUNGEON_MODE_ORDER) do
			--info.text = key.." 던전 모두";
			info.text = subarray.." 던전 모두";
			--info.checked = (FP_Filter_Dungeon_Info.dungeons["ALL"] and FP_Filter_Dungeon_Info.dungeons["ALL"].mode == key);
			--info.checked = FP_Filter_Dungeon_Info.zones[key];
			info.checked = FP_Filter_Dungeon_Info.zones[subarray];
			info.value = {
				["Dungeon"] = "ALL",
				--["Mode"] = key,
				["Mode"] = subarray,
				["level"] = level;
			};
			UIDropDownMenu_AddButton(info, level);
		end

		-- 한줄 비움
		info.checked = false;
		info.text = "";
		info.disabled = true;
		info.value = {["Zone"] = no};
		UIDropDownMenu_AddButton(info, level);

		info.text = "인던별 선택";
		info.notCheckable = true;
		info.isTitle = true;
		info.value = {["Zone"] = no};
		UIDropDownMenu_AddButton(info, level);
		info.disabled = false;
		info.isTitle = false;
		info.notCheckable = false;
		info.hasArrow = true; -- creates submenu
		
	  for i=1, table.getn(FP_ZONE_ORDER) do
      local insertflag = true;
  		for key, subarray in pairs(FP_DUNGEON_LIST) do
    		if(FP_ZONE_ORDER[i] == key and insertflag) then
    			info.text = key;
    			info.checked = FP_Filter_Dungeon_Info.zones[key];
    			info.value = {
    				["Zone"] = key,
    				["level"] = level,
    			};
    			UIDropDownMenu_AddButton(info, level);
    			insertflag = false;
    		end
  		end -- for key, subarray
  	end
	else
		FP_DropDownMenuDungeon_Initialize(
			self,
			level,
			info,
			FP_FilterDungeonSelected,
			DropDownMenuFilterDungeonCheck
		);
	end

	if (level == 1) then
		-- 한줄 비움
		info.checked = false;
    info.text = "";
    info.disabled = true;
    info.value = {["Zone"] = no};
    info.hasArrow = false;
    UIDropDownMenu_AddButton(info, level);

		info.text = "* 모두 초기화 *";
		info.value = "resetall";
		info.func = FP_FilterDungeonSelected;
		info.notCheckable = false;
		info.disabled = false;
		info.keepShownOnClick = false;
		info.textR = 0.95;
		info.textG = 0.30;
		info.textB = 0.30;
		UIDropDownMenu_AddButton(info, level);
		info.text = "닫기";
		info.func = nil;
		info.keepShownOnClick = false;
		UIDropDownMenu_AddButton(info, level);
	end
end

function DropDownMenuFilterDungeonCheck(level, key, upLevelKey)
	if (level == 2) then
		return FP_Filter_Dungeon_Info.dungeons[key];
	elseif (level == 3) then
		--return (FP_Filter_Dungeon_Info.dungeons[upLevelKey] and (FP_Filter_Dungeon_Info.dungeons[upLevelKey].mode == "전체" or key == FP_Filter_Dungeon_Info.dungeons[upLevelKey].mode));
		if (FP_Filter_Dungeon_Info.dungeons[upLevelKey]) then
			return FP_Filter_Dungeon_Info.dungeons[upLevelKey][key];
		else
			return false;
		end
	end
	return false;
end

-- 옵션 메뉴 변경 --
function FP_OptionSelected(self)
--  FP_Debug("FP_OptionSelected : "..tostring(self));

	if self.value then

		if not self.value.istitle then

			local option = self.value.Option;
			local value = self.value.Value;

			local opName = FP_OPTION_NAME[option];
			local opType = type(FP_Options[opName]);

      FP_Debug("opName : "..tostring(opName));
      FP_Debug("opType : "..tostring(opType));

			if (opType == "number") then
				FP_Options[opName] = tonumber(value);
			elseif (opType == "string") then
				FP_Options[opName] = tostring(value);
			elseif (opType == "nil" or opType == "boolean") then
				FP_Options[opName] = not FP_Options[opName];
			elseif (opType == "table") then
				FP_Options[opName][value] = self.checked;
			end

			if (opName == "scale") then
				FP_UIResize(FP_Options.scale);
			elseif (opName == "fontsize") then
				FP_FontResize()
			elseif (opName == "reset") then
				FP_Options[opName] = nil;
				if (value == "창 위치") then
					FP_ListFrame:SetPoint("CENTER", UIParent, "CENTER", 0, 0);
				elseif (value == "창 크기") then
					FP_Options.scale = 1;
					FP_UIResize(FP_Options.scale);
					FP_ListAdjust(MAX);
					FP_ListFrame:SetWidth(750);
				elseif (value == "전체 옵션 초기화(Reload UI)") then
					FP_LoadDefaultOption();
				end
			end

			if (opName=="esc") then
				if( FP_Options[FP_OPTION_NAME["ESC로 창 닫기"]] ) then
					tinsert(UISpecialFrames, "FP_Frame");
				else
					for i=1, #UISpecialFrames do
						local v = UISpecialFrames[i];
						if (v == "FP_Frame") then
							-- ESC 창 닫기 오류 수정 by 영원이란
							table.remove(UISpecialFrames, i)
						end
					end
				end
			end

      if (opName=="minimaptoggle") then
        FP_Debug("minimaptoggle");
        if(FP_Minimap_Button) then
          if( FP_Options[FP_OPTION_NAME["미니맵 버튼 활성/비활성"]] ) then
            FP_Debug("minimaptoggle : Show");
            FP_Minimap_Button:Show();
            FP_Options.MinimapToggle = true;
          else
            FP_Debug("minimaptoggle : Hide");
            FP_Minimap_Button:Hide();
            FP_Options.MinimapToggle = false;
          end
        end
      end
--      if (opName=="charservername") then
--        if(FP_Options.charservername == true) then
--          FP_Options.charservername = false;
--          FP_Debug("charservername 2076 : "..tostring(FP_Options.charservername));
--        else
--          FP_Options.charservername = true;
--          FP_Debug("charservername 2079 : "..tostring(FP_Options.charservername));
--        end
--      end
      
		end
	end

	if (UIDROPDOWNMENU_MENU_LEVEL == 1) then
		local menu_cnt = 0;
		for c, n in pairs(FP_OPTION_LIST) do
			menu_cnt = menu_cnt + 1;
		end
		for i=1, menu_cnt do
			local button = getglobal("DropDownList1Button"..i);
			if button.value.istitle then
				button.checked = false;
				getglobal("DropDownList1Button"..i.."Check"):Hide();
			end
		end
	end

	if (UIDROPDOWNMENU_MENU_LEVEL == 2) then
		local option = self.value.Option;
		local value = self.value.Value;

		local opName = FP_OPTION_NAME[option];
		local opType = type(FP_Options[opName]);
		
		if (opType == "number") then
			opCnt = table.getn(UIDROPDOWNMENU_MENU_VALUE.subarray) or 1;
			for i = 1, opCnt do
				local button = getglobal("DropDownList2Button"..i);
				if button.value then
					if button.value.Value == value then
						button.checked = true;
						getglobal("DropDownList2Button"..i.."Check"):Show();
					else
						button.checked = false;
						getglobal("DropDownList2Button"..i.."Check"):Hide();
					end
				end
			end
		end
	end

end

function FP_ColorSelected(previousValues)
	if (not previousValues) then
		FP_Options.color.r, FP_Options.color.g, FP_Options.color.b = ColorPickerFrame:GetColorRGB();
		FP_Options.color.opacity = OpacitySliderFrame:GetValue();
	else
		FP_Options.color=previousValues;
	end

	--FP_Debug("color r="..FP_Options.color.r.." g="..FP_Options.color.g.." b="..FP_Options.color.b.." a="..FP_Options.color.opacity);
	FP_SetListColor();
end

function FP_DropDownMenuOption_Initialize(frame, level)
FP_Debug(">>>>2140 FP_DropDownMenuOption_Initialize Start!!!!!!!!!!!!!!");
	level = level or 1;

	if (level == 1) then
    for idx, tbl in ipairs(FP_OPTION_LIST) do
			local info = UIDropDownMenu_CreateInfo();
			name = next(tbl);

			info.text = name;
			info.hasArrow = name ~= ""; -- creates submenu
			info.disabled = name == "";
			info.hasColorSwatch = false;
			info.hasOpacity = false;
			info.func = FP_OptionSelected;
			info.keepShownOnClick = true;
			info.notCheckable = false;

			info.value = {
				["Option"] = name,
				["subarray"] = FP_OPTION_LIST[idx][name],
				["istitle"] = true,
				["level"] = level,
			};
			if (name == "창 색상 편집") then
				info.hasArrow = false;
				info.hasColorSwatch = true;
				info.hasOpacity = true;
				info.value.istitle = nil;
				info.keepShownOnClick = false;
				info.r = FP_Options.color.r;
				info.g = FP_Options.color.g;
				info.b = FP_Options.color.b;
				info.opacity = FP_Options.color.opacity;
				info.func = UIDropDownMenuButton_OpenColorPicker
				info.swatchFunc = FP_ColorSelected;
				info.opacityFunc = FP_ColorSelected;
				info.cancelFunc = FP_ColorSelected;
			end

--			if (name == "캐릭명에 서버명 표기") then
--				info.hasArrow = false;
--				info.value.istitle = nil;
--				if (FP_Options[FP_OPTION_NAME[name]]) then
--					info.checked = true;
--				end
--				FP_Debug(">>>>2182 FP_Options[FP_OPTION_NAME[name]] : "..tostring(FP_Options[FP_OPTION_NAME[name]]));
--			end
			if (name == "귀속던전 제외") then
				info.hasArrow = false;
				info.value.istitle = nil;
				if (FP_Options[FP_OPTION_NAME[name]]) then
					info.checked = true;
				end
			end
			if (name == "레이드 중 자동 끄기") then
				info.hasArrow = false;
				info.value.istitle = nil;
				if (FP_Options[FP_OPTION_NAME[name]]) then
					info.checked = true;
				end
			end
			if (name == "ESC로 창 닫기") then
				info.hasArrow = false;
				info.value.istitle = nil;
				if (FP_Options[FP_OPTION_NAME[name]]) then
					info.checked = true;
				end
			end
      if (name == "미니맵 버튼 활성/비활성") then
        info.hasArrow = false;
        info.value.istitle = nil;
        if (FP_Options[FP_OPTION_NAME[name]]) then
          info.checked = true;
        end
      end
			if (name == "레이드 진행 중에 자동 끄기") then
				info.hasArrow = false;
				info.value.istitle = nil;
				if (FP_Options[FP_OPTION_NAME[name]]) then
					info.checked = true;
				end
			end
			if (name == "5인던전 진행 중에 자동 끄기") then
				info.hasArrow = false;
				info.value.istitle = nil;
				if (FP_Options[FP_OPTION_NAME[name]]) then
					info.checked = true;
				end
			end
			if (name == "전장/투기장에 있을시 자동 끄기") then
				info.hasArrow = false;
				info.value.istitle = nil;
				if (FP_Options[FP_OPTION_NAME[name]]) then
					info.checked = true;
				end
			end
			if (name == "닫기") then
				info.hasArrow = false;
				info.keepShownOnClick = false;
			end

			UIDropDownMenu_AddButton(info, level);
		end -- for key, subarray
	end -- if level 1

	if (level == 2) then
		local info = UIDropDownMenu_CreateInfo();
		local Level1_Key = UIDROPDOWNMENU_MENU_VALUE["Option"];
		local opName = FP_OPTION_NAME[Level1_Key];
		if (Level1_Key == "던전 편집") then
			FP_DropDownMenuEditDungeon_Initialize(frame, level);
		else
			subarray = UIDROPDOWNMENU_MENU_VALUE["subarray"];
			info.func = FP_OptionSelected;
			info.keepShownOnClick = true;

			for i=1, table.getn(subarray) do
				local item = subarray[i];
				info.text = item;
				info.value = {
					["Option"] = Level1_Key,
					["Value"] = item,
					["level"] = level,
				};

				if (opName == "channel") then
					info.checked = FP_Options[opName][item];
				elseif (Level1_Key == "초기화") then
					info.notCheckable = true;
					info.keepShownOnClick = false;
				else
					info.checked = (item == tostring(FP_Options[opName]));
				end

				UIDropDownMenu_AddButton(info, level);
			end -- for key,subsubarray
		end
	end -- if level 2

	if (level > 2) then
		FP_DropDownMenuEditDungeon_Initialize(frame, level);
	end

end

local inputEditBox;

function FP_DropDownMenuEditDungeon_Initialize(frame, level)
	local info = {};
	local menuValue = UIDROPDOWNMENU_MENU_VALUE;
	info.notCheckable = true;
	--info.keepShownOnClick = true;

	if (level == 2) then
		info.text = "기본값 불러오기(Reload UI)";
		info.func = FP_LoadDefaultDungeonList;
		info.hasArrow = false;
		info.notCheckable = true;
		UIDropDownMenu_AddButton(info, level);

		-- 한줄 비움
		info.text = "";
		info.disabled = true;
		UIDropDownMenu_AddButton(info, level);
		info.disabled = false;
	end

	if (level > 2 and not menuValue["command"]) then
		if (inputEditBox) then inputEditBox:Hide(); end

		if (level == 3) then
			info.text= "<---"..menuValue["Zone"].." 삭제";
		elseif (level == 4) then
			info.text= "<---"..menuValue["Dungeon"].." 삭제";
		elseif (level == 5) then
			info.text= "<---"..menuValue["Alias"].." 삭제";
		end
		info.disabled = false;
		info.hasArrow = false;
		info.func = FP_RemoveDungeonList;
		info.level = level;
		info.value = {
			["command"] = "remove",
			["Zone"] = menuValue["Zone"],
			["Dungeon"] = menuValue["Dungeon"],
			["Alias"] = menuValue["Alias"],
			["level"] = level
		}
		UIDropDownMenu_AddButton(info, level);
		info.func = nil;

		if (level < 5) then
		-- 한줄 비움
			info.text = "";
			info.disabled = true;
			info.hasArrow = false;
			UIDropDownMenu_AddButton(info, level);
			info.disabled = false;
		end
	end

	-- 레벨별 메뉴 제목
	if (level == 2) then
		info.text = "지역 구분";
	elseif (level == 3) then
		info.text = "던전 이름";
	elseif (level == 4) then
		info.text = "던전 별명";
	end
	if (level < 5 and not menuValue["command"]) then
		info.isTitle = true;
		info.justifyH = "CENTER";
		UIDropDownMenu_AddButton(info, level);
		info.isTitle = false;
		info.justifyH = nil;
	end
	info.isTitle = false;

	-- 각 레벨별 추가 메뉴
	if (level < 5  and not menuValue["command"]) then
		-- 한줄 비움
		info.text = "------------------";
		info.isTitle = true;
		info.justifyH = "CENTER";
		UIDropDownMenu_AddButton(info, level);
		info.isTitle = false;
		info.justifyH = nil;

		info.disabled = false;
		info.text= "항목 추가";
		info.hasArrow = true;
		info.value = {
			["Option"] = "던전 편집",
			["command"] = "add",
			["Zone"] = menuValue["Zone"],
			["Dungeon"] = menuValue["Dungeon"],
			["Alias"] = menuValue["Alias"],
			["level"] = level
		}
		UIDropDownMenu_AddButton(info, level);

		-- 한줄 비움
		info.text = "";
		info.disabled = true;
		info.hasArrow = false;
		UIDropDownMenu_AddButton(info, level);
		info.disabled = false;

		info.func = nil;
		info.hasArrow = true;
	end

	-- 던전 리스트출력
	if (level == 2) then
		menuValue["subarray"] = FP_DUNGEON_LIST;
	end

	if (level > 1 and level < 6) then
		if (menuValue["command"] == "add") then
			info.text ="                            ";
			info.hasArrow = false;
			UIDropDownMenu_AddButton(info, level);

			local tempParent = getglobal("DropDownList"..level.."Button1");
			if (not inputEditBox) then
				inputEditBox = CreateFrame("EditBox", nil, tempParent , "InputBoxTemplate");
				inputEditBox:SetScript("OnEnterPressed", FP_AddDungeonList);
			end
			inputEditBox:SetParent(tempParent);
			inputEditBox:ClearAllPoints();
			inputEditBox:SetAllPoints(tempParent);
			inputEditBox:Show();
			inputEditBox:SetFocus();
		elseif (type(menuValue["subarray"]) == "table") then
			local subarray = menuValue["subarray"];
			local idx, v;
			while(true) do
				idx,v = next(subarray, idx);
				if (not idx) then break; end

				if (type(idx) == "number") then
					info.text = v;
				else
					info.text = idx;
				end
				info.value = {};
				info.value.subarray = v;
				info.level = level;

				if (not menuValue.Alias) then
					if (not menuValue.Dungeon) then
						if (not menuValue.Zone) then
							info.value.Zone = idx;
						else
							info.value.Dungeon = idx;
							info.value.Zone = menuValue.Zone;
						end
					else
						info.value.Alias = v;
						info.value.Zone = menuValue.Zone;
						info.value.Dungeon = menuValue.Dungeon;
					end
				end

				UIDropDownMenu_AddButton(info, level);
			end
		end
	end
end

function FP_AddDungeonList(self)
	--FP_Debug("FP_AddDungeonList start.");
	local value = UIDROPDOWNMENU_MENU_VALUE;

	-- trimming text
	local item = self:GetText();
	local useless, useless, str = string.find(item, "(%S+.*)");
	if (str) then
		useless, useless, str = string.find(str, "(.*%S+)");
	else
		return;
	end

	item = str;

	self:SetText(""); -- edit box
	info = {};
	info.notCheckable = true;
	info.hasArrow = true;
	info.value = {
		["level"] = value.level,
		["Zone"] = item,
	}
	local add_ok = true;

	if (value.level == 2) then
		for a, b in pairs(FP_DUNGEON_LIST) do
			if item == a then add_ok = false; break; end;
		end
		if add_ok == false then
			DEFAULT_CHAT_FRAME:AddMessage("|cffffff00이미 존재하는 지역 이름입니다. 다른 이름으로 등록하세요.");
		else
			FP_DUNGEON_LIST[item] = {};

			info.text = item;
			info.value.Zone = item;
			info.value.subarray = FP_DUNGEON_LIST[item];
			UIDropDownMenu_AddButton(info, value.level);
		end
	elseif (value.level == 3) then
		for a, b in pairs(FP_DUNGEON_LIST) do
			for c, d in pairs(FP_DUNGEON_LIST[a]) do
				if item == c then add_ok = false; break; end;
			end
		end
		if add_ok == false then
			DEFAULT_CHAT_FRAME:AddMessage("|cffffff00이미 존재하는 던전 이름입니다. 다른 이름으로 등록하세요.");
		else
			FP_DUNGEON_LIST[value.Zone][item] = {item};

			info.text = item;
			info.value.Zone = value.Zone;
			info.value.Dungeon = item;
			info.value.subarray = FP_DUNGEON_LIST[value.Zone][item];
			UIDropDownMenu_AddButton(info, value.level);
		end
	elseif (value.level == 4) then
		table.insert(FP_DUNGEON_LIST[value.Zone][value.Dungeon], item);

		info.text = item;
		info.value.Zone = value.Zone;
		info.value.Dungeon = value.Dungeon;
		info.value.Alias = item;
		info.value.index = #FP_DUNGEON_LIST[value.Zone][value.Dungeon];
		UIDropDownMenu_AddButton(info, value.level);
	end

	--오류 수정을 위한 주석 처리 by 영원이란
	----FP_Debug("zone-dungeon-alias-index"..info.value.Zone.."-"..info.value.Dungeon.."-"..info.value.Alias.."-"..info.value.index);
	--UIDropDownMenu_Refresh(self, value, value.level);
end

function FP_RemoveDungeonList(self)
	value = self.value;

	if (value.level == 3) then
		if (next(FP_DUNGEON_LIST[value.Zone])) then
			DEFAULT_CHAT_FRAME:AddMessage("|cffffff00하위 항목이 하나도 없을 때에만 삭제가 가능합니다.");
		else
			FP_DUNGEON_LIST[value.Zone] = nil;

--			HideDropDownMenu(value.level);
			for i=1,UIDROPDOWNMENU_MAXBUTTONS do
				local button = getglobal("DropDownList"..(value.level-1).."Button"..i);
				if (button and button.value and button.value.Zone == value.Zone) then
					button:Hide();
					break;
				end
			end
		end
	elseif (value.level == 4) then
		-- 오류 방지를 위해 FP_RAID_ORDER에 있는 던전은 삭제가 불가능 하게 한다 by 영원이란
		local delete_ok = true;
		if (value.Zone == "공격대") then
			for k, v in pairs(FP_RAID_ORDER) do
				if (v == value.Dungeon) then delete_ok = false; break;
				end
			end
		end
		if (delete_ok == false) then
			DEFAULT_CHAT_FRAME:AddMessage("|cffffff00이 공격대 던전은 삭제하실 수 없습니다.");
		else
		-- 수정 끝
			FP_DUNGEON_LIST[value.Zone][value.Dungeon] = nil;

--			HideDropDownMenu(value.level);
			for i=1,UIDROPDOWNMENU_MAXBUTTONS do
				local button= getglobal("DropDownList"..(value.level-1).."Button"..i);
				if (button and button.value and button.value.Dungeon == value.Dungeon) then
					button:Hide();
					break;
				end
			end
		end
	elseif (value.level == 5) then
		local array = FP_DUNGEON_LIST[value.Zone][value.Dungeon];

		for i=1, #FP_DUNGEON_LIST[value.Zone][value.Dungeon] do
			if (FP_DUNGEON_LIST[value.Zone][value.Dungeon][i] == value.Alias) then
				table.remove(FP_DUNGEON_LIST[value.Zone][value.Dungeon], i);
				break;
			end
		end
--		HideDropDownMenu(value.level);
		for i=1,UIDROPDOWNMENU_MAXBUTTONS do
			local button= getglobal("DropDownList"..(value.level-1).."Button"..i);
			if (button and button.value and  button.value.Alias == value.Alias) then
				button:Hide();
				break;
			end
		end
	end
end

function FP_AutoDeactivate()
	if FP_Activated_Status then
		local _, instancetype = GetInstanceInfo()
		if FP_Options.activated then
			if instancetype == "raid" and FP_Options.noraid then FP_Activate(not FP_Activated_Status); end;
			if instancetype == "party" and FP_Options.noparty then FP_Activate(not FP_Activated_Status); end;
			if instancetype == "pvp" and FP_Options.nopvp then FP_Activate(not FP_Activated_Status); end;
		else
			if FP_Options.noraid and FP_Options.noparty and FP_Options.nopvp then
				if instancetype == "none" then FP_Activate(FP_Activated_Status) end;
			elseif FP_Options.noraid and FP_Options.noparty then
				if instancetype == "pvp" or instancetype == "none" then FP_Activate(FP_Activated_Status) end;
			elseif FP_Options.noraid and FP_Options.nopvp then
				if instancetype == "party" or instancetype == "none" then FP_Activate(FP_Activated_Status) end;
			elseif FP_Options.noparty and FP_Options.nopvp then
				if instancetype == "raid" or instancetype == "none" then FP_Activate(FP_Activated_Status) end;
			elseif FP_Options.noraid then
				if instancetype ~= "raid" then FP_Activate(FP_Activated_Status) end;
			elseif FP_Options.noparty then
				if instancetype ~= "party" then FP_Activate(FP_Activated_Status) end;
			elseif FP_Options.nopvp then
				if instancetype ~= "pvp" then FP_Activate(FP_Activated_Status) end;
			end
		end
	else
	end
end

function FP_LoadDefaultOption()
FP_Debug("☆☆☆☆☆☆☆ FP_LoadDefaultOption Start!!!!! ☆☆☆☆☆☆☆");
	DEFAULT_CHAT_FRAME:AddMessage("|cffffff00옵션 초기값을 불러옵니다.");
	FP_Options = {};
	for k,v in pairs(FP_Default_Options) do
		FP_Options[k] = v;
	end
	FP_Options.channel = {};
	for k,v in pairs(FP_Default_Options.channel) do
		FP_Options.channel[k] = v;
	end
	FP_Options.color = {};
	for  k,v in pairs(FP_Default_Options.color) do
		FP_Options.color[k] = v;
	end

	FP_Scroll_Info = {
		["max"] = MAX_VIEW_LINE,
		["height"] = 25,
		["viewLines"] = MAX_VIEW_LINE,
	};

	FP_Filter_Dungeon_Info = {
		["filtered"] = false,
		["zones"] = {},
		["dungeons"] = {},
		["num"] = 0;
	}

	FP_ListFrame:SetPoint("CENTER", UIParent, "CENTER", 0, 0);
	FP_Options.scale = 1;
	FP_UIResize(FP_Options.scale);
	FP_ListAdjust(MAX);
	FP_ListFrame:SetWidth(750);

	FP_Filter_Class = "모두";
	FP_Version = FP_CURRENT_VERSION;

	FP_Frame:Hide();

  FP_LoadDefaultDungeonList();
	
end

function FP_LoadDefaultDungeonList()
FP_Debug("☆☆☆☆☆☆☆ FP_LoadDefaultDungeonList Start!!!!! ☆☆☆☆☆☆☆");
--	DEFAULT_CHAT_FRAME:AddMessage("|cffffff00던전 리스트 기본값을 불러옵니다.");

--	--sort(FP_DEFAULT_DUNGEON_LIST);
--	for z, dTbl in pairs(FP_DEFAULT_DUNGEON_LIST) do
--		FP_Debug("zone : "..z)
--		FP_DUNGEON_LIST[z] = {};

--		--sort(dTbl);
--		for d,aTbl in pairs(dTbl) do
--			FP_Debug("dungeon : "..d)
--			FP_DUNGEON_LIST[z][d] = {};

--			--sort(aTbl);
--			for i, alias in ipairs(aTbl) do
--        FP_Debug("alias : "..i)
--				FP_DUNGEON_LIST[z][d][i] = alias;
--			end
--		end
--	end
	--FP_OPTION_LIST["던전 편집"] = FP_DUNGEON_LIST;

  FP_IsDungeonInit = true;
	ReloadUI();
	
end

function FP_OnLoad()
	FP_InviteControlFrame:RegisterEvent("VARIABLES_LOADED");
	FP_InviteControlFrame:RegisterEvent("ADDON_LOADED");
--	FP_InviteControlFrame:RegisterEvent("CHAT_MSG_SAY");
	FP_InviteControlFrame:RegisterEvent("CHAT_MSG_CHANNEL");
--	FP_InviteControlFrame:RegisterEvent("CHAT_MSG_WHISPER");
	FP_InviteControlFrame:RegisterEvent("CHAT_MSG_SYSTEM");
--	FP_InviteControlFrame:RegisterEvent("CHAT_MSG_CHANNEL_LEAVE");
--	FP_InviteControlFrame:RegisterEvent("CHAT_MSG_CHANNEL_JOIN");
--	FP_InviteControlFrame:RegisterEvent("CHAT_MSG_CHANNEL_LIST");
--	FP_InviteControlFrame:RegisterEvent("RAID_ROSTER_UPDATE");
--	FP_InviteControlFrame:RegisterEvent("PARTY_MEMBERS_CHANGED");
--	FP_InviteControlFrame:RegisterEvent("PARTY_MEMBER_ENABLE");
	FP_InviteControlFrame:RegisterEvent("WHO_LIST_UPDATE");
--	FP_InviteControlFrame:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE");
	FP_InviteControlFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
	FP_InviteControlFrame:RegisterEvent("ZONE_CHANGED");
	FP_InviteControlFrame:RegisterEvent("ZONE_CHANGED_INDOORS");
	FP_InviteControlFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA");
end

function FP_DungeonListInit()
FP_Debug("□□□□□□□ FP_DungeonListInit Start!!!!! □□□□□□□");
  if(FP_IsDungeonInit) then
FP_Debug(">>>>>>>2709 FP_DungeonListInit Start!!!!! □□□□□□□");
    FP_DUNGEON_LIST = {};
    FP_DUNGEON_LIST = FP_DEFAULT_DUNGEON_LIST;
    FP_IsDungeonInit = false;
  end
end

--최상위 던전 zone order by : 사용안함. 샘플로 유지시킴
function FP_DungeonListSort()
--  FP_Debug("■■■■■■■ FP_DungeonListSort Start!!!!! ■■■■■■■");

  for i=1, table.getn(FP_ZONE_ORDER) do
    local insertflag = true;
    for zone,dlist in pairs(FP_DEFAULT_DUNGEON_LIST) do
      
      if(FP_ZONE_ORDER[i] == zone and insertflag) then
--        FP_Debug("■■■■■■■ FP_ZONE_ORDER["..i.."] : "..tostring(FP_ZONE_ORDER[i]).." and zone : "..tostring(zone));
        FP_DUNGEON_LIST[zone] = FP_DEFAULT_DUNGEON_LIST[zone];
        insertflag = false;
      end
    end
  end

end

function FP_SortButton(targetTable, sortTable, isChecked,menuInfo, menuLevel)

    for i=1, table.getn(sortTable) do
      local insertflag = true;
      for key, subarray in pairs(targetTable) do
        if(sortTable[i] == key and insertflag) then
          info.text = key;
          info.checked = isChecked;
          info.value = {
            ["Zone"] = key,
            ["level"] = level,
          };
          UIDropDownMenu_AddButton(info, level);
          insertflag = false;
        end
      end -- for key, subarray
    end
end

function FP_OnEvent(event, ...)
	if (event=="ADDON_LOADED") then
		ADDON_LOADED();
    FP_DungeonListInit();
	end
	if (event=="VARIABLES_LOADED") then
		FP_InviteControlFrame:UnregisterEvent("VARIABLES_LOADED");
		FP_Init();
	end
	if (not FP_Options) then return; end
	if (event == "PLAYER_ENTERING_WORLD") then
		if FP_Options.noraid or FP_Options.noparty or FP_Options.nopvp then FP_AutoDeactivate(); end;
	elseif (event == "ZONE_CHANGED") then
		if FP_Options.noraid or FP_Options.noparty or FP_Options.nopvp then FP_AutoDeactivate(); end;
	elseif (event == "ZONE_CHANGED_INDOORS") then
		if FP_Options.noraid or FP_Options.noparty or FP_Options.nopvp then FP_AutoDeactivate(); end;
	elseif (event == "ZONE_CHANGED_NEW_AREA") then
		if FP_Options.noraid or FP_Options.noparty or FP_Options.nopvp then FP_AutoDeactivate(); end;
	end	
	if (not FP_Options.activated) then return; end

	if (event == "CHAT_MSG_CHANNEL") then
		local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12 = ...;
		if arg1 and FP_Options.channel[arg9] then
			local msg = arg1;
			-- 불필요한 문자열 제거
			msg = string.gsub(msg, "{해골}", "");
			msg = string.gsub(msg, "{별}", "");
			msg = string.gsub(msg, "{다이아몬드}", "");
			msg = string.gsub(msg, "{세모}", "");
			msg = string.gsub(msg, "{가위표}", "");
			msg = string.gsub(msg, "{동그라미}", "");
			msg = string.gsub(msg, "{달}", "");
			msg = string.gsub(msg, "{네모}", "");
--FP_Debug(">>>>>>2766 arg2 "..tostring(arg2).." : "..string.find(arg2, "-", 1));
--.."arg1 : "..tostring(arg1)
--.."arg2 : "..tostring(arg2)
--.."arg3 : "..tostring(arg3)
--.."arg4 : "..tostring(arg4)
--.."arg5 : "..tostring(arg5)
--.."arg6 : "..tostring(arg6)
--.."arg7 : "..tostring(arg7)
--.."arg8 : "..tostring(arg8)
--.."arg9 : "..tostring(arg9)
--.."arg10 : "..tostring(arg10)
--.."arg11 : "..tostring(arg11));

      local displayName = nil;

--      if(FP_Options.charservername) then
--        name = arg5;
--      else
        for i, v in ipairs(FP_SERVER_LIST) do
          displayName = string.gsub(arg5, "-"..v, "");
          FP_Debug( "idx=".. i.. " value=".. v .. " name = "..displayName);
          if(displayName ~= arg5) then break end;
        end
--      end
      
			FP_AddList(arg5, displayName, msg, arg12);
		end
		
	elseif (event == "CHAT_MSG_SYSTEM" or event == "WHO_LIST_UPDATE") then
		if (GetNumWhoResults() > 0 and ShouterSelected) then
			for i=1,GetNumWhoResults() do
				local charname, guildname, level, race, class, zone = GetWhoInfo(i);
				if (ShouterSelected.name == charname) then
					ShouterSelected.class = class;
					ShouterSelected.level = level;
					FP_Refresh(true);
					break;
				end
			end
		end
--	elseif (event == "CHAT_MSG_CHANNEL_NOTICE") then
--		FP_GetChannels();
	elseif (event == "PLAYER_ENTERING_WORLD") then
		User_Realm = GetRealmName();
		User_Faction = UnitFactionGroup("player");
	end
end

function FP_OnUpdate()
	if (Party_Find_Info.announcing == true) then
		local time = GetTime() * 1000;
		local elapsed =  time - announce_timer;

		if (elapsed > FP_Options.interval * 1000) then
			FP_Announce();
			announce_timer = time;
		end
	end

	if (not FP_Options.activated) then return; end

	local time = GetTime() * 1000;
	local elapsed =  time - valdating_timer;

	if (elapsed > 1000 and table.getn(FP_Datas) > 0) then
		local i=1;
		while(i <= table.getn(FP_Datas)) do
			FP_Datas[i].time = FP_Datas[i].time + 1;

			if (FP_Datas[i].time > FP_Options.valid) then
				FP_RemoveList(FP_Datas[i].name);
			else
				i = i +1;
			end
		end
		valdating_timer = time;

		FP_Refresh(true);
	end
end

SLASH_FINDPARTY1 = "/FP";
SLASH_FINDPARTY2 = "/fp";
SLASH_FINDPARTY3 = "/findparty";

SlashCmdList["FINDPARTY"] = function(msg)
	--FP_Debug("SlashCmdList");
	local _, _, command, args = string.find(msg, "(%S+)%s?(.*)");

	FP_Frame:Show();

end

function ADDON_LOADED()
	FP_InviteControlFrame:UnregisterEvent("ADDON_LOADED")
end

function FP_Debug(msg)
--  if(debugSwitch) then 
--  DEFAULT_CHAT_FRAME:AddMessage(tostring(msg));
--  end
end