
local addon = {}
local modName = "bcf_options"
_G[modName] = addon

local db
local tabs = {"일반", "피해", "치유", "버프/디버프", "스크롤", "이벤트"}
local confirmFrame, subConditionFrame

local tinsert = table.insert
local tremove = table.remove
local fonts = {
	{
		text = "굵은 글꼴",
		value = "Fonts\\2002b.TTF",
	},
	{
		text = "기본 글꼴",
		value = "Fonts\\2002.TTF",
	},
	{
		text = "데미지 글꼴",
		value = "Fonts\\K_Damage.TTF",
	},
	{
		text = "퀘스트 글꼴",
		value = "Fonts\\K_Pagetext.TTF",
	},
}
local outlines = {
	{
		text = "외각선 없음",
		value = "",
	},
	{
		text = "MONOCHROME",
		value = "MONOCHROME",
	},
	{
		text = "얇은 외각선",
		value = "OUTLINE",
	},
	{
		text = "두꺼운 외각선",
		value = "THICKOUTLINE",
	},
}
local animationTypes
local messageAligns = {
	{
		text = "왼쪽 정렬",
		value = "left",
	},
	{
		text = "가운데 정렬",
		value = "center",
	},
	{
		text = "오른쪽 정렬",
		value = "right",
	},
}
local iconAligns = {
	{
		text = "메세지 왼쪽에",
		value = "left",
	},
	{
		text = "메세지 오른쪽에",
		value = "right",
	},
}

local conditions = {
	{
		text = "치명 피해",
		options = {
			{
				text = "플레이어가 치명 피해 입힘",
				value = "outgoingCrit",
			},
			{
				text = "플레이어가 치명 피해 받음",
				value = "incomingCrit",
			},
			{
				text = "소환수가 치명 피해 입힘",
				value = "outgoingPetCrit",
			},
			{
				text = "소환수가 치명 피해 받음",
				value = "incomingPetCrit",
			},
		},
	},
	{
		text = "플레이어의 방어 관련 조건",
		options = {
			{
				text = "플레이어의 방어성공",
				options = {
					{
						text = "방어함",
						value = "incomingBlock",
					},
					{
						text = "회피함",
						value = "incomingDodge",
					},
					{
						text = "공격막음",
						value = "incomingParry",
					},
					{
						text = "저항함",
						value = "incomingResist",
					},
					{
						text = "면역",
						value = "incomingImmune",
					},
				},
			},
			{
				text = "플레이어의 공격실패",
				options = {
					{
						text = "방어당함",
						value = "outgoingBlock",
					},
					{
						text = "회피당함",
						value = "outgoingDodge",
					},
					{
						text = "공격막힘",
						value = "outgoingParry",
					},
					{
						text = "저항당함",
						value = "outgoingResist",
					},
					{
						text = "면역당함",
						value = "outgoingImmune",
					},
				},
			},
		},
	},
	{
		text = "소환수의 방어 관련 조건",
		options = {
			{
				text = "소환수의 방어성공",
				options = {
					{
						text = "소환수 - 방어함",
						value = "incomingPetBlock",
					},
					{
						text = "소환수 - 회피함",
						value = "incomingPetDodge",
					},
					{
						text = "소환수 - 공격막음",
						value = "incomingPetParry",
					},
					{
						text = "소환수 - 저항함",
						value = "incomingPetResist",
					},
					{
						text = "소환수 - 면역",
						value = "incomingPetImmune",
					},
				},
			},
			{
				text = "소환수의 공격실패",
				options = {
					{
						text = "소환수 - 방어당함",
						value = "outgoingPetBlock",
					},
					{
						text = "소환수 - 회피당함",
						value = "outgoingPetDodge",
					},
					{
						text = "소환수 - 공격막힘",
						value = "outgoingPetParry",
					},
					{
						text = "소환수 - 저항당함",
						value = "outgoingPetResist",
					},
					{
						text = "소환수 - 면역당함",
						value = "outgoingPetImmune",
					},
				},
			},
		},
	},
	{
		text = "버프/디버프 관련",
		options = {
			{
				text = "플레이어",
				options = {
					{
						text = "플레이어가 버프 얻음",
						value = "selfBuff",
					},
					{
						text = "플레이어가 디버프 얻음",
						value = "selfDebuff",
					},
					{
						text = "플레이어 버프 사라짐",
						value = "selfBuffFade",
					},
					{
						text = "플레이어 디버프 사라짐",
						value = "selfDebuffFade",
					},
				},
			},
			{
				text = "소환수",
				options = {
					{
						text = "소환수가 버프 얻음",
						value = "petBuff",
					},
					{
						text = "소환수가 디버프 얻음",
						value = "petDebuff",
					},
					{
						text = "소환수 버프 사라짐",
						value = "petfBuffFade",
					},
					{
						text = "소환수 디버프 사라짐",
						value = "petfDebuffFade",
					},
				},
			},
			{
				text = "대상",
				options = {
					{
						text = "대상이 버프 얻음",
						value = "targetBuff",
					},
					{
						text = "대상이 디버프 얻음",
						value = "targetDebuff",
					},
					{
						text = "대상 버프 사라짐",
						value = "targetBuffFade",
					},
					{
						text = "대상 디버프 사라짐",
						value = "targetDebuffFade",
					},
				},
			},
		},
	},
	{
		text = "체력/파워 관련",
		options = {
			{
				text = "플레이어의 체력 회복",
				value = "selfHealthGain",
			},
			{
				text = "플레이어의 체력 소실",
				value = "selfHealthLoss",
			},
			{
				text = "소환수의 체력 회복",
				value = "petHealthGain",
			},
			{
				text = "소환수의 체력 소실",
				value = "petHealthLoss",
			},
			{
				text = "대상의 체력 회복",
				value = "targetHealthGain",
			},
			{
				text = "대상의 체력 소실",
				value = "targetHealthLoss",
			},
			{
				text = "플레이어의 파워 회복",
				value = "selfManaGain",
			},
			{
				text = "플레이어의 파워 소실",
				value = "selfManaLoss",
			},
		},
	},
	{
		text = "주문/스킬 시전 관련",
		options = {
			{
				text = "플레이어가 적에게",
				options = {
					{
						text = "(플레이어->적) 시전/사용 시작",
						value = "outgoingCastStart",
					},
					{
						text = "(플레이어->적) 시전/사용 성공",
						value = "outgoingCastSuccess",
					},
					{
						text = "(플레이어->적) 시전/사용 실패",
						value = "outgoingCastFail",
					},
				},
			},
			{
				text = "적이 플레이어에게",
				options = {
					{
						text = "(적->플레이어) 시전/사용 시작",
						value = "incomingCastStart",
					},
					{
						text = "(적->플레이어)시전/사용 성공",
						value = "incomingCastSuccess",
					},
					{
						text = "(적->플레이어)시전/사용 실패",
						value = "incomingCastFail",
					},
				},
			},
		},
	},
	{
		text = "대상 죽임",
		value = "killblow",
	},
}
local subConditions = { -- and check
	{
		text = "주문 및 능력 준비됐는지 확인",
		value = "SpellReady",
	},
	{
		text = "주문 및 능력 사용가능한지 확인",
		value = "SpellUsable",
	},
	{
		text = "최소 파워요구량(%) 확인",
		value = "MinPower",
	},
	{
		text = "지정 버프가 있는지 확인",
		value = "hasBuff",
	},
	{
		text = "지정 버프가 없는지 확인",
		value = "hasNoBuff",
	},
	{
		text = "지정 디버프 있는지 확인",
		value = "hasDebuff",
	},
	{
		text = "지정 디버프 없는지 확인",
		value = "hasNoDebuff",
	},
	{
		text = "재사용대기 시간 확인",
		value = "Cooldown",
	},
	{
		text = "대상이 PC인지 확인",
		value = "TargetIsPlayer",
	},
	{
		text = "대상이 아군인지 확인",
		value = "TargetIsFriend",
	},
	{
		text = "대상이 적인지 확인",
		value = "TargetIsEnemy",
	},
	{
		text = "경험치/명예 얻을 수 있는 대상인지 확인",
		value = "HonorKillLevel",
	},
	{
		text = "전사 태세 확인",
		value = "WarriorStance",
	},
	{
		text = "드루이드 변신 확인",
		value = "DruidForm",
	},
}
local print
local set
local get
local digit2
local copyTable
local tcopy
local hexToDec
local FloatToText
local updateScrollAreaNameDB
local updateScrollAreaDeleteTo
local refreshAll
local resetDB
local createGraBar
local createPanel
local createNullPanel
local createString
local createCheckBox
local createCheckBox2
local controlRadioButton
local createRadioButton
local createCheckGroupButton
local createButton
local controlButton
local createSubConditionElement
local createHeaderButton
local createColorPicker
local createEditBox
local createSlider
local createDropdown
local createWindowFrame
local createMainFrame
local drawConfigFrame
local enableCheckbox
local disableCheckbox
local drawComplexOption
local drawCheckAndButtonOpt
local drawCheckOpt
local __drawChildControls
local drawScrollFrame
local getSubConditionFrame

function print(msg)
	ChatFrame1:AddMessage(msg, 1.0, 1.0, 0.2)
end

function set(v, k, k2)
	if k2 then
		db[k][k2] = v
	else
		db[k] = v
	end
end
function get(k,k2)
	if k2 then
		return db[k][k2]
	else
		return db[k]
	end
end

function digit2(num)
	num = (num + 0.05) * 10
	num = math.floor(num)
	return num/10
end
function copyTable(src)
	local dest = {}
	for k, v in pairs(src) do
		if type(v)=='table' then
			dest[k] = copyTable(v)
		else
			dest[k] = v
		end
	end
	return dest
end

function tcopy(to, from) -- "to" must be a table (possibly empty)
	for k,v in pairs(from) do
		if(type(v)=="table") then
			if not to then to = {} end
			to[k] = {}
			tcopy(to[k], v)
		else
			to[k] = v
		end
	end
end

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

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

function updateScrollAreaNameDB(prevValue, newValue)
	if addon.bcf.bScroll:RenameScrollArea(newValue, prevValue) then
		for k, v in pairs(db) do
			if type(v)=='table' then
				if v.scrollArea and v.scrollArea==prevValue then
					v.scrollArea = newValue
				end
				if v.crit and type(v.crit)=='table' then
					if v.crit.scrollArea and v.crit.scrollArea==prevValue then
						v.crit.scrollArea = newValue
					end
				end
			end
			if k == 'customEvents' then
				for i=1, #v do
					if v[i].scrollArea and v[i].scrollArea==prevValue then
						v[i].scrollArea = newValue
					end
				end
				addon.bcf:UpdateCustomEventDB()
			end
		end
		return true
	end
end
function updateScrollAreaDeleteTo(name)
	addon.bcf.bScroll:DeleteScrollArea(name)
	local me = db.scrollAreas[1].name
	for k, v in pairs(db) do
		if type(v)=='table' then
			if v.scrollArea and v.scrollArea==name then
				v.scrollArea = me
			end
			if v.crit and type(v.crit)=='table' then
				if v.crit.scrollArea and v.crit.scrollArea==name then
					v.crit.scrollArea = me
				end
			end
		end
		if k == 'customEvents' then
			for i=1, #v do
				if v[i].scrollArea and v[i].scrollArea==prevValue then
					v[i].scrollArea = me
				end
			end
			addon.bcf:UpdateCustomEventDB()
		end
	end
end

function refreshAll()
	addon.frame.enableButton.refresh()
	local str = ""
	for i=1, #addon.frame.tabs do
		if addon.frame.tabs[i].frame and addon.frame.tabs[i].frame.groups and #addon.frame.tabs[i].frame.groups>0 then
			for j=1, #addon.frame.tabs[i].frame.groups do
				if addon.frame.tabs[i].frame.groups[j].controls and #addon.frame.tabs[i].frame.groups[j].controls>0 then
					for k=1, #addon.frame.tabs[i].frame.groups[j].controls do
						local control = addon.frame.tabs[i].frame.groups[j].controls[k]
						if control.refresh and type(control.refresh)=='function' then
							control.refresh()
						end
					end
				end
			end
		end
	end
	addon.bcf:UpdateCustomEventDB()
end

function resetDB()
	for k, v in pairs(db) do
		db[k] = nil
	end

	tcopy(db, addon.bcf.defaultDB)
	local sas = addon.bcf.bScroll:GetScrollAreas()
	db.scrollAreas = {}
	for i=1, #sas do
		tinsert(db.scrollAreas,{
			name = sas[i].name,
			width = sas[i].width,
			height = sas[i].height,
			x = sas[i].x,
			y = sas[i].y,
			scrollTime = sas[i].scrollTime,
		})
	end
--
--	--db = copyTable(addon.bcf.defaultDB)
--	for k, v in pairs(addon.bcf.defaultDB) do
--		if type(v)=='table' then
--			db[k] = {}
--			for k2, v2 in pairs(v) do
--				if type(v2)=='table' then
--					db[k][k2] = {}
--					for k3, v3 in pairs(v2) do
--						db[k][k2][k3] = {}
--						if type(v3)=='table' then
--							db[k][k2][k3] = {}
--							for k4, v4 in pairs(v3) do
--								db[k][k2][k3][k4] = v4
--							end
--						else
--							db[k][k2][k3] = v3
--						end
--					end
--				else
--					db[k][k2] = v2
--				end
--			end
--		else
--			db[k] = v
--		end
--	end

	-- 하위 컨트롤 전부 찾아서 refresh할것!;
	refreshAll()
end

function createGraBar(parent, text)
	local title = CreateFrame("Frame", nil, parent)
	local t = title:CreateTexture(nil, "BACKGROUND")
	t:SetPoint("TOPLEFT", title, "TOPLEFT", 0, 0)
	t:SetPoint("BOTTOMRIGHT", title, "BOTTOMRIGHT", 0, 0)
	t:SetTexture("Interface\\ChatFrame\\ChatFrameBackground")
	t:SetBlendMode("BLEND")
	title:SetBackdropColor(0,0,0,0)
	t:SetGradientAlpha("HORIZONTAL", 0.0392, 0.1411, 0.4156, 1,    0.6509, 0.7921, 0.9411, 1)

	title:SetPoint("TOPLEFT", parent, "TOPLEFT", 0, 0)
	title:SetPoint("BOTTOMRIGHT", parent, "TOPRIGHT", 0, -20)
	--title:SetFrameLevel(parent:GetFrameLevel()+10)

	title.text = title:CreateFontString(nil, "OVERLAY","ChatFontNormal")
	title.text:SetPoint("LEFT", title, "LEFT", 25, 0)
	title.text:SetText(text)
	title.text:SetTextColor(1,1,1)
	return title
end

function createPanel(parent, name, width, height, r, g, b, a)
	local frame = CreateFrame("Frame", name, parent)
	frame:SetWidth(width)
	frame:SetHeight(height)
	frame:SetBackdrop({
		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
		edgeFile = "",
		tile = true, tileSize = 5, edgeSize = 0,
		insets={left = 0, right = 0, top = 0, bottom = 0}
	})
	frame:SetBackdropColor(r, g, b, a)
	return frame
end

function createNullPanel(parent, name, text, width, height)
	local panel = CreateFrame("Frame", name, parent)
	panel:SetWidth(width or parent:GetWidth())
	panel:SetHeight(height or 20)
	panel.type = "null"
	return panel
end

function createString(parent, name, text, width, height)
	local panel = CreateFrame("Frame", name, parent)
	panel:SetWidth(width or parent:GetWidth())
	panel:SetHeight(height or 20)
	panel.type = "text"

	panel.text = panel:CreateFontString(nil, "OVERLAY","GameFontNormalSmall")
	panel.text:SetPoint("LEFT", panel, "LEFT", 2, 0)
	if text and type(text)=='function' then
		panel.text:SetText(text())
	else
		panel.text:SetText(text)
	end
	return panel
end

function createCheckBox(parent, text, tooltip, anchor)
	local btn = CreateFrame("CheckButton", nil, parent, "UICheckButtonTemplate")
	btn.text = btn:CreateFontString(nil, "OVERLAY")
	btn.text:SetPoint("LEFT", btn, "RIGHT", 0, 0)
	btn.text:SetFont("Fonts\\2002B.ttf", 14)
	btn.text:SetText(text)
	if tooltip then
		btn:SetScript("OnEnter", function(this)
			GameTooltip:SetOwner(this, anchor or "ANCHOR_BOTTOMLEFT")
			GameTooltip:SetText(tooltip, nil, nil, nil, nil, 1)
			GameTooltip:Show()
		end)
		btn:SetScript("OnLeave", function() GameTooltip:Hide() end)
	end
	return btn
end

function createCheckBox2(ground, parent, name, text, tooltip, width, height, dbkey, dbkey2)

	local panel = createString(parent, name, text, width, height)
	panel.type = "check"

	panel.checkButton = CreateFrame("CheckButton", nil, panel, "UICheckButtonTemplate")
	panel.checkButton:SetScript("OnEnter", function(this)
		GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
		GameTooltip:SetText(tooltip, nil, nil, nil, nil, 1)
		GameTooltip:Show()
	end)
	panel.checkButton:SetScript("OnLeave", function() GameTooltip:Hide() end)
	if type(dbkey)=='table' then
		panel.checkButton:SetChecked(dbkey.get() and true or false)
	else
		panel.checkButton:SetChecked(get(dbkey,dbkey2) and true or false)
	end
	panel.checkButton:SetScript("OnClick", function()
		if type(dbkey)=='table' then
			dbkey.set(this:GetChecked() and true or false)
			if dbkey.needRefresh then
				if ground and ground.refresh then
					ground.refresh()
				end
			end
		else
			set(this:GetChecked() and true or false, dbkey, dbkey2)
		end
	end)
	panel.checkButton:SetPoint("RIGHT", panel, "RIGHT")
	panel.checkButton:SetWidth(28)
	panel.checkButton:SetHeight(28)

	panel.refresh = function ()
		if type(dbkey)=='table' then
			panel.checkButton:SetChecked(dbkey.get() and true or false)
		else
			panel.checkButton:SetChecked(get(dbkey,dbkey2) and true or false)
		end
	end
	return panel
end

function controlRadioButton(parent, text, tooltip)
	local button = CreateFrame("CheckButton", nil, parent, "UIRadioButtonTemplate")
	button.text = button:CreateFontString(nil, "OVERLAY","GameFontNormalSmall")
	button.text:SetPoint("LEFT", button, "LEFT", 20, 0)
	button.text:SetText(text)

	if tooltip then
		button:SetScript("OnEnter", function(this)
			GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
			GameTooltip:SetText(tooltip, nil, nil, nil, nil, 1)
			GameTooltip:Show()
		end)
		button:SetScript("OnLeave", function() GameTooltip:Hide() end)
	end
	return button
end
function createRadioButton(ground, parent, name, width, dbkey, dbkey2, options)
	if not options then
		return
	end
	local panel = createPanel(parent, name, width, 20, 0, 0, 0, .3)
	local opt
	if type(options)=='function' then
		opt = options()
	else
		opt = options
	end
	panel.type = "radio"
	panel.controls = {}
	local rdo
	local innerHeight = 0
	for i=1, #opt do
		rdo = controlRadioButton(panel, opt[i].text, opt[i].tooltip)
		rdo.value = opt[i].value
		if i==1 then
			rdo:SetPoint("TOPLEFT", 3, -3 )
		else
			rdo:SetPoint("TOPLEFT", panel.controls[#panel.controls], "BOTTOMLEFT", 0, -3)
		end
		if type(dbkey)=='table' then
			if rdo.value == dbkey.get() then
				rdo:SetChecked(true)
			end
		else
			if rdo.value == get(dbkey, dbkey2) then
				rdo:SetChecked(true)
			end
		end
		if opt[i].tooltip then
			rdo:SetScript("OnEnter", function(this)
				GameTooltip:SetOwner(this, anchor or "ANCHOR_BOTTOMLEFT")
				GameTooltip:SetText(opt[i].tooltip, nil, nil, nil, nil, 1)
				GameTooltip:Show()
			end)
			rdo:SetScript("OnLeave", function() GameTooltip:Hide() end)
		end
		rdo:SetScript("OnClick", function ()
			for j=1, #panel.controls do
				if panel.controls[j]~=this then
					panel.controls[j]:SetChecked(nil)
				else
					panel.controls[j]:SetChecked(true)
				end
			end
			if type(dbkey)=='table' then
				dbkey.set(this.value)
				if dbkey.needRefresh then
					if ground and ground.refresh then
						ground.refresh()
					end
				end
			else
				set(this.value, dbkey, dbkey2)
			end
			if opt[i].func and type(opt[i].func)=='function' then
				opt[i].func()
			elseif opt[i].func and type(opt[i].func)=='string' then
				local f = getglobal(opt[i].func)
				if f and type(f)=='function' then
					f()
				end
			end
		end)

		if opt[i].deleteFunc then
			rdo.deleteButton = CreateFrame("Button", nil, panel, "UIPanelCloseButton")
			rdo.deleteButton:SetWidth(18)
			rdo.deleteButton:SetHeight(18)
			rdo.deleteButton:SetPoint("LEFT", rdo.text, "RIGHT", 1, 0)
			rdo.deleteButton:SetScript("OnClick", function ()
				if opt[i].deleteFunc and type(opt[i].deleteFunc)=='function' then
					opt[i].deleteFunc()
				elseif opt[i].deleteFunc and type(opt[i].deleteFunc)=='string' then
					local f = getglobal(opt[i].deleteFunc)
					if f and type(f)=='function' then
						f()
					end
				end
			end)
			rdo.deleteButton:SetScript("OnEnter", function()
				GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
				GameTooltip:SetText("삭제하기", nil, nil, nil, nil, 1)
				GameTooltip:Show()
			end)
			rdo.deleteButton:SetScript("OnLeave", function() GameTooltip:Hide() end)
		end

		tinsert(panel.controls, rdo)
		innerHeight = innerHeight + rdo:GetHeight() + 3
	end
	panel:SetHeight(innerHeight+3)

	panel.refresh = function ()
		local checkedValue
		if type(dbkey)=='table' then
			checkedValue = dbkey.get()
		else
			checkedValue = get(dbkey, dbkey2)
		end
		for j=1, #panel.controls do
			if (panel.controls[j].value == checkedValue) or (panel.controls[j].value=="" and not checkedValue) then
				panel.controls[j]:SetChecked(true)
			else
				panel.controls[j]:SetChecked(nil)
			end
		end
	end
	return panel
end

function createCheckGroupButton(ground, parent, name, width, dbkey, dbkey2, options, col)
	if not options then
		return
	end
	local panel = createPanel(parent, name, width, 20, 0, 0, 0, .3)
	panel.type = "choice"
	local opt
	col = col or 1
	if type(options)=='function' then
		opt = options()
	else
		opt = options
	end

	local values
	if type(dbkey)=='table' then
		values = dbkey.get()
	else
		values = get(dbkey, dbkey2)
	end

	panel.controls = {}
	panel.values = {}
	local chk
	local innerHeight = 0
	local column
	for i=1, #opt do
		chk = CreateFrame("CheckButton", nil, panel, "UICheckButtonTemplate")
		chk:SetWidth(24)
		chk:SetHeight(24)
		chk.text = chk:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
		chk.text:SetPoint("LEFT", chk, "RIGHT", 0, 0)
		chk.text:SetText(opt[i].text)
		if opt[i].r and opt[i].g and opt[i].b then
			chk.text:SetTextColor(opt[i].r, opt[i].g, opt[i].b, 1)
		end
		if opt[i].tooltip then
			chk:SetScript("OnEnter", function(this)
				GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
				GameTooltip:SetText(opt[i].tooltip, nil, nil, nil, nil, 1)
				GameTooltip:Show()
			end)
			chk:SetScript("OnLeave", function() GameTooltip:Hide() end)
		end

		chk.value = opt[i].value
		chk.exclusion = opt[i].exclusion -- 배타 옵션..이게 true인 chk는 다른 chk들과 같이 체크될수 없다.(radio버튼같은거..)

		column = (i-1) % col
		if i==1 then
			chk:SetPoint("TOPLEFT", 3, -3 )
			innerHeight = innerHeight + chk:GetHeight() + 3
		else
			if column==0 then
				chk:SetPoint("TOPLEFT", panel.controls[i-col], "BOTTOMLEFT", 0, -3)
				innerHeight = innerHeight + chk:GetHeight() + 3
			else
				chk:SetPoint("LEFT", panel.controls[#panel.controls], "LEFT", width/col, 0)
			end
		end
		if values[chk.value] then
			chk:SetChecked(true)
		end

		chk:SetScript("OnClick", function ()
			local chked = this:GetChecked()
			if chked then
				for j=1, #panel.controls do
					if this.exclusion then
						if panel.controls[j]~=this then
							panel.controls[j]:SetChecked(not chked)
						end
					else
						if panel.controls[j].exclusion~=this.exclusion then
							panel.controls[j]:SetChecked(not chked)
						end
					end
				end
			end

			for k, v in pairs(panel.values) do panel.values[k] = nil end
			for j=1, #panel.controls do
				if panel.controls[j]:GetChecked() then
					panel.values[panel.controls[j].value] = true
				end
			end
			if type(dbkey)=='table' then
				dbkey.set(panel.values)
				if dbkey.needRefresh then
					if ground and ground.refresh then
						ground.refresh()
					end
				end
			else
				set(panel.values, dbkey, dbkey2)
			end

			if opt[i].func and type(opt[i].func)=='function' then
				opt[i].func(chked)
			elseif opt[i].func and type(opt[i].func)=='string' then
				local f = getglobal(opt[i].func)
				if f and type(f)=='function' then
					f(chked)
				end
			end
		end)
		tinsert(panel.controls, chk)
	end
	panel:SetHeight(innerHeight+3)

	panel.refresh = function ()
		local values
		if type(dbkey)=='table' then
			values = dbkey.get()
		else
			values = get(dbkey, dbkey2)
		end
		for j=1, #panel.controls do
			if values[panel.controls[j].value] then
				panel.controls[j]:SetChecked(true)
			else
				panel.controls[j]:SetChecked(nil)
			end
		end
	end
	return panel
end

function createButton(parent, text, tooltip, isGrayButton)
	local btn
	if isGrayButton then
		btn = CreateFrame("Button", nil, parent, "UIPanelButtonGrayTemplate")
	else
		btn = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
	end

	btn:SetText(text)
	btn:SetFrameLevel(parent:GetFrameLevel()+1)
	if tooltip then
		btn:SetScript("OnEnter", function(this)
			GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
			GameTooltip:SetText(tooltip, nil, nil, nil, nil, 1)
			GameTooltip:Show()
		end)
		btn:SetScript("OnLeave", function() GameTooltip:Hide() end)
	end
	return btn
end

function controlButton(parent, frontCtrl, text, tooltip, func, width, height, isGrayButton)
	local btn = createButton(parent, text, tooltip, isGrayButton)
	btn:SetWidth(width or 80)
	btn:SetHeight(height or 21)
	if func and type(func)=='function' then
		btn:SetScript("OnClick", function ()
			func()
		end)
	end
	btn.refresh = function () end
	return btn
end

function createSubConditionElement(ground, parent, getTextFunc, tooltip, width, height, func, deleteFunc)
	local panel = createString(parent, nil, getTextFunc(), width, height)
	panel.type = "subCondition"

	local textWidth = width

	if deleteFunc then
		panel.deleteButton = CreateFrame("Button", nil, panel, "UIPanelCloseButton")
		panel.deleteButton:SetWidth(height*0.9)
		panel.deleteButton:SetHeight(height*0.9)
		panel.deleteButton:SetPoint("RIGHT", -1, 0)
		panel.deleteButton:SetScript("OnClick", function ()
			if deleteFunc and type(deleteFunc)=='function' then
				deleteFunc()
			elseif deleteFunc and type(deleteFunc)=='string' then
				local f = getglobal(deleteFunc)
				if f and type(f)=='function' then
					f()
				end
			end
		end)
		panel.deleteButton:SetScript("OnEnter", function()
			GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
			GameTooltip:SetText("삭제하기", nil, nil, nil, nil, 1)
			GameTooltip:Show()
		end)
		panel.deleteButton:SetScript("OnLeave", function() GameTooltip:Hide() end)
		textWidth = textWidth - panel.deleteButton:GetWidth() - 1
	end

	panel.button = createButton(panel, "변경", tooltip, isGrayButton)
	panel.button:SetWidth(45)
	panel.button:SetHeight(21)
	if panel.deleteButton then
		panel.button:SetPoint("RIGHT", panel.deleteButton, "LEFT", -5, 0)
		textWidth = textWidth - panel.button:GetWidth() - 5
	else
		panel.button:SetPoint("RIGHT")
		textWidth = textWidth - panel.button:GetWidth()
	end
	panel.button:SetScript("OnClick", function()
		if func and type(func)=='function' then
			func()
		elseif func and type(func)=='string' then
			local f = getglobal(func)
			if f and type(f)=='function' then
				f()
			end
		end
	end)

	panel.text:SetJustifyH("LEFT")
	panel.text:SetWidth(textWidth)
	panel.text:SetNonSpaceWrap(true)

	panel.refresh = function ()
		panel.text:SetText(getTextFunc())
	end

	return panel
end

function createHeaderButton(panel, parent, controls, text, width, height, func, deleteFunc)
	local button = CreateFrame("CheckButton", nil, parent)
	button.type = 'header'
	button:SetBackdrop({
		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
		edgeFile = "",
		tile = true, tileSize = 5, edgeSize = 16,
		insets={left = 0, right = 0, top = 0, bottom = 0}
	})
	button:SetWidth(width or 100)
	button:SetHeight(height or 20)
	button:SetFrameLevel(parent:GetFrameLevel()+1)
	button:SetBackdropColor(0, 0, 0, 0)

	button.text = button:CreateFontString(nil, "OVERLAY")
	button.text:SetPoint("LEFT", button, "LEFT", 4, 0)
	button.text:SetFont("Fonts\\2002B.ttf", 14)
	button.text:SetTextColor(1, 1, 1)
	button.text:SetText(text)

	button:SetScript("OnEnter", function()
		this:SetBackdropColor(0.6, .6, 1, 0.3)
		this.text:SetTextColor(1, 1, 1)
	end)
	button:SetScript("OnLeave", function()
		if this:GetChecked() then
			this:SetBackdropColor(0.6, .6, 1, 0.3)
			this.text:SetTextColor(1, 0.82, 0)
		else
			this:SetBackdropColor(0, 0, 0, 0)
			this.text:SetTextColor(1, 1, 1)
		end
	end)
	button:SetScript("OnClick", function (this)
		this:SetChecked(true)
		this:SetBackdropColor(0.6, .6, 1, 0.3)
		this.text:SetTextColor(1, 0.82, 0)
		for i=1, #controls do
			if controls[i]~=this then
				controls[i]:SetChecked(nil)
				controls[i]:SetBackdropColor(0, 0, 0, 0)
				controls[i].text:SetTextColor(1, 1, 1)
			else
				panel.selectedIndex = i
			end
		end
		if func and type(func)=='function' then
			func(panel.selectedIndex)
		elseif func and type(func)=='string' then
			local f = getglobal(func)
			if f and type(f)=='function' then
				f(panel.selectedIndex)
			end
		end
	end)

	if deleteFunc then
		button.deleteButton = CreateFrame("Button", nil, button, "UIPanelCloseButton")
		button.deleteButton:SetWidth(height*0.9)
		button.deleteButton:SetHeight(height*0.9)
		button.deleteButton:SetPoint("RIGHT", -5, 0)
		button.deleteButton:SetScript("OnClick", function ()
			selectedIndex = 0
			for i=1, #controls do
				if controls[i]==button then
					selectedIndex = i
					break
				end
			end
			if selectedIndex > 0 then
				if deleteFunc and type(deleteFunc)=='function' then
					deleteFunc(selectedIndex)
				elseif deleteFunc and type(deleteFunc)=='string' then
					local f = getglobal(deleteFunc)
					if f and type(f)=='function' then
						f(selectedIndex)
					end
				end
			end
		end)
		button.deleteButton:SetScript("OnEnter", function()
			GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
			GameTooltip:SetText("삭제하기", nil, nil, nil, nil, 1)
			GameTooltip:Show()
		end)
		button.deleteButton:SetScript("OnLeave", function() GameTooltip:Hide() end)
	end

	return button
end

function createColorPicker(ground, parent, name, text, tooltip, width, height, dbkey, dbkey2)
	local panel = createString(parent, name, text, width, height)
	panel.type = "color"

	local r,g,b
	if type(dbkey)=='table' then
		r,g,b = hexToDec(dbkey.get())
	else
		r,g,b = hexToDec(get(dbkey, dbkey2))
	end
	panel:SetWidth(width)
	panel:SetHeight(height)
	panel.type = "color"

	panel.button = CreateFrame("Button", nil, panel)
	panel.button:SetWidth(20)
	panel.button:SetHeight(20)
	panel.button:SetNormalTexture("Interface\\ChatFrame\\ChatFrameColorSwatch")
	panel.button:SetPoint("RIGHT", panel, "RIGHT")
	panel.button.texture = panel.button:GetNormalTexture()
	panel.button.texture:SetVertexColor(r, g, b)

	local bg = panel.button:CreateTexture(nil, "BACKGROUND")
	bg:SetWidth(18)
	bg:SetHeight(18)
	bg:SetPoint("CENTER", panel.button)
	bg:SetVertexColor(1, 1, 1, 1)
	panel.button.bg = bg

	panel.button:SetScript("OnEnter", function ()
		panel.button.bg:SetVertexColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
		if tooltip then
			GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
			GameTooltip:SetText(tooltip, nil, nil, nil, nil, 1)
			GameTooltip:Show()
		end
	end)
	panel.button:SetScript("OnLeave", function ()
		panel.button.bg:SetVertexColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
		GameTooltip:Hide()
	end)
	panel.button:SetScript("OnClick", function()
		ColorPickerFrame:Hide()
		ColorPickerFrame.func = function() end
		local r,g,b
		if type(dbkey)=='table' then
			r,g,b = hexToDec(dbkey.get())
		else
			r,g,b = hexToDec(get(dbkey, dbkey2))
		end

		ColorPickerFrame:SetColorRGB(r, g, b)
		panel.button.previousValues = {r = r, g = g, b = b, a = 1}
		ColorPickerFrame.hasOpacity = nil
		ColorPickerFrame.func = function()
			local alpha = 1
			local color = {ColorPickerFrame:GetColorRGB()}
			panel.button.texture:SetVertexColor(color[1], color[2], color[3], alpha)
			local tc = FloatToText(color[1], color[2], color[3])
			if type(dbkey)=='table' then
				dbkey.set(tc)
				if dbkey.needRefresh then
					if ground and ground.refresh then
						ground.refresh()
					end
				end
			else
				set(tc, dbkey, dbkey2)
			end
		end
		ColorPickerFrame.cancelFunc = function()
			panel.button.texture:SetVertexColor(panel.button.previousValues.r,
						panel.button.previousValues.g,
						panel.button.previousValues.b,
						panel.button.previousValues.a)
			local tc = FloatToText(panel.button.previousValues.r,
						panel.button.previousValues.g,
						panel.button.previousValues.b)
			if type(dbkey)=='table' then
				dbkey.set(tc)
				if dbkey.needRefresh then
					if ground and ground.refresh then
						ground.refresh()
					end
				end
			else
				set(tc, dbkey, dbkey2)
			end
		end
		ColorPickerFrame:Show()
	end)

	panel.refresh = function ()
		local r,g,b
		if type(dbkey)=='table' then
			r,g,b = hexToDec(dbkey.get())
		else
			r,g,b = hexToDec(get(dbkey, dbkey2))
		end
		panel.button.texture:SetVertexColor(r, g, b, 1)
	end

	return panel
end

function createEditBox(ground, parent, name, text, tooltip, width, height, dbkey, dbkey2, wide, allowBlank)
	local t
	if text and type(text)=='function' then
		t = text()
	else
		t = text
	end

	local panel = CreateFrame("Frame", name, parent)
	panel:SetWidth(width or parent:GetWidth())
	panel:SetHeight(height or 20)
	panel.type = "editbox"

	local editWidth = 0
	if t then
		panel.text = panel:CreateFontString(nil, "OVERLAY","GameFontNormalSmall")
		if wide then
			panel.text:SetPoint("TOPLEFT", panel, "TOPLEFT", 2, 0)
		else
			panel.text:SetPoint("LEFT", panel, "LEFT", 2, 0)
		end
		panel.text:SetText(text)

		editWidth = width - panel.text:GetStringWidth() - 20
		if editWidth > width/2 then
			editWidth = width/2
		end
		if wide then
			editWidth = width
		end
	else
		editWidth = width
	end

	panel.bg = createPanel(panel, nil, editWidth, 18, .2, .2, .2, 1)
	if wide then
		if panel.text then
			panel.bg:SetPoint("TOPLEFT", panel.text, "BOTTOMLEFT", -2, -3)
		else
			panel.bg:SetPoint("CENTER")
		end
	else
		panel.bg:SetPoint("RIGHT", panel, "RIGHT")
	end

	panel.edit = CreateFrame("EditBox", name, panel.bg)
	panel.edit:ClearAllPoints()
	panel.edit:SetTextColor(1,1,1)
	panel.edit:SetFontObject("ChatFontNormal")
	panel.edit:SetPoint("CENTER")
	panel.edit:SetWidth(editWidth-2)
	panel.edit:SetHeight(20)
	panel.edit:SetAutoFocus(nil)
	if type(dbkey)=='table' then
		panel.edit:SetText(dbkey.get() or "")
	else
		panel.edit:SetText(get(dbkey, dbkey2) or "")
	end
	if tooltip then
		panel.edit:SetScript("OnEnter", function(this)
			local tt
			if tooltip and type(tooltip)=='function' then
				tt = tooltip()
			elseif tooltip then
				tt = tooltip
			end
			GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
			GameTooltip:SetText(tt, nil, nil, nil, nil, 1)
			GameTooltip:Show()
		end)
		panel.edit:SetScript("OnLeave", function() GameTooltip:Hide() end)
	end

	panel.edit:SetScript("OnEditFocusGained", panel.edit.HighlightText)
	panel.edit:SetScript("OnEditFocusLost", function()
		this:HighlightText(0,0)
		local text = this:GetText()
		local ab
		if allowBlank and type(allowBlank)=='function' then
			ab = allowBlank()
		elseif allowBlank then
			ab = allowBlank
		end
		if (not text or text=="") and not ab then
			if type(dbkey)=='table' then
				this:SetText(dbkey.get() or "")
			else
				this:SetText(get(dbkey, dbkey2) or "")
			end
		else
			if type(dbkey)=='table' then
				dbkey.set(this:GetText())
				if dbkey.needRefresh then
					if ground and ground.refresh then
						ground.refresh()
					end
				end
			else
				set(this:GetText(), dbkey, dbkey2)
			end
		end
	end)
	panel.edit:SetScript("OnEscapePressed", function()
		if type(dbkey)=='table' then
			this:SetText(dbkey.get() or "")
		else
			this:SetText(get(dbkey, dbkey2) or "")
		end
		this:ClearFocus()
	end)
	panel.edit:SetScript("OnEnterPressed", function()
		local text = this:GetText()
		local ab
		if allowBlank and type(allowBlank)=='function' then
			ab = allowBlank()
		elseif allowBlank then
			ab = allowBlank
		end
		if (not text or text=="") and not ab then
			if type(dbkey)=='table' then
				this:SetText(dbkey.get() or "")
			else
				this:SetText(get(dbkey, dbkey2) or "")
			end
		else
			if type(dbkey)=='table' then
				dbkey.set(this:GetText())
				if dbkey.needRefresh then
					if ground and ground.refresh then
						ground.refresh()
					end
				end
			else
				set(this:GetText(), dbkey, dbkey2)
			end
		end
		this:ClearFocus()
	end)

	panel.refresh = function ()
		if type(dbkey)=='table' then
			panel.edit:SetText(dbkey.get() or "")
		else
			panel.edit:SetText(get(dbkey, dbkey2) or "")
		end
	end

	if wide and panel.text then
		panel:SetHeight(panel.text:GetHeight() + panel.edit:GetHeight()+3)
	end

	return panel
end

local sliderCount = 1
function createSlider(ground, parent, name, text, tooltip, width, height, dbkey, dbkey2, minv, maxv, step)
	local t
	if text and type(text)=='function' then
		t = text()
	else
		t = text
	end
	local panel = createString(parent, name, t, width, height)
	panel.type = "slider"

	panel.bgcolor = createPanel(panel, nil, 42, 18, .2, .2, .2, 1)
	panel.bgcolor:SetPoint("RIGHT", panel, "RIGHT")

	panel.edit = CreateFrame("EditBox", name, panel.bgcolor)
	panel.edit:ClearAllPoints()
	panel.edit:SetTextColor(1,1,1)
	panel.edit:SetFontObject("ChatFontNormal")
	panel.edit:SetPoint("CENTER")
	panel.edit:SetWidth(40)
	panel.edit:SetHeight(20)
	panel.edit:SetAutoFocus(nil)
	panel.edit:SetJustifyH("RIGHT")
	if type(dbkey)=='table' then
		panel.edit:SetText(dbkey.get() or minv)
	else
		panel.edit:SetText(get(dbkey, dbkey2) or minv)
	end
	if tooltip then
		panel.edit:SetScript("OnEnter", function(this)
			local tt
			if tooltip and type(tooltip)=='function' then
				tt = tooltip()
			elseif tooltip then
				tt = tooltip
			end
			GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
			GameTooltip:SetText(tt, nil, nil, nil, nil, 1)
			GameTooltip:Show()
		end)
		panel.edit:SetScript("OnLeave", function() GameTooltip:Hide() end)
	end

	panel.edit:SetScript("OnEditFocusGained", panel.edit.HighlightText)
	panel.edit:SetScript("OnEditFocusLost", function()
		this:HighlightText(0,0)
		if type(tonumber(this:GetText())) ~= "number" then
			this:SetText(digit2(panel.slider:GetValue()))
			this:ClearFocus()
			return
		end
		if type(dbkey)=='table' then
			dbkey.set(tonumber(this:GetText()))
			if dbkey.needRefresh then
				if ground and ground.refresh then
					ground.refresh()
				end
			end
		else
			set(tonumber(this:GetText()), dbkey, dbkey2)
		end
		panel.slider:SetValue(tonumber(this:GetText()))
	end)
	panel.edit:SetScript("OnEscapePressed", function()
		if type(dbkey)=='table' then
			this:SetText(dbkey.get() or minv)
			panel.slider:SetValue(dbkey.get() or minv)
		else
			this:SetText(get(dbkey, dbkey2) or minv)
			panel.slider:SetValue(get(dbkey, dbkey2) or minv)
		end
		this:ClearFocus()
	end)
	panel.edit:SetScript("OnEnterPressed", function()
		if type(tonumber(this:GetText())) ~= "number" then
			this:SetText(digit2(panel.slider:GetValue()))
			this:ClearFocus()
			return
		end
		if type(dbkey)=='table' then
			dbkey.set(tonumber(this:GetText()))
			if dbkey.needRefresh then
				if ground and ground.refresh then
					ground.refresh()
				end
			end
		else
			set(tonumber(this:GetText()), dbkey, dbkey2)
		end
		panel.slider:SetValue(tonumber(this:GetText()))
		this:ClearFocus()
	end)

	local slider_name
	if name then
		slider_name = name and name.."Slider"
	else
		slider_name = "bcf_options_slider_"..sliderCount
		sliderCount = sliderCount + 1
	end
	local sliderWidth = width - panel.text:GetStringWidth() - 55
	if sliderWidth > width/2 then
		sliderWidth = width/2
	end
	panel.slider = CreateFrame("Slider", slider_name, panel, "OptionsSliderTemplate")
	panel.slider:SetWidth(sliderWidth)
	panel.slider:SetMinMaxValues(minv, maxv)
	panel.slider:SetValueStep(step)
	if type(dbkey)=='table' then
		panel.slider:SetValue(dbkey.get() or minv)
	else
		panel.slider:SetValue(get(dbkey, dbkey2) or minv)
	end
	panel.slider:SetPoint("RIGHT", panel.bgcolor, "LEFT", -5, 0)
	panel.slider:SetScript("OnValueChanged", function ()
		if type(dbkey)=='table' then
			dbkey.set(digit2(tonumber(this:GetValue())))
			if dbkey.needRefresh then
				if ground and ground.refresh then
					ground.refresh()
				end
			end
		else
			set(digit2(tonumber(this:GetValue())), dbkey, dbkey2)
		end
		panel.edit:SetText(digit2(tonumber(this:GetValue())))
	end)
	getglobal(panel.slider:GetName().."Low"):Hide()
	getglobal(panel.slider:GetName().."High"):Hide()
	if tooltip then
		panel.slider:SetScript("OnEnter", function(this)
			local tt
			if tooltip and type(tooltip)=='function' then
				tt = tooltip()
			elseif tooltip then
				tt = tooltip
			end
			GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
			GameTooltip:SetText(tt, nil, nil, nil, nil, 1)
			GameTooltip:Show()
		end)
		panel.slider:SetScript("OnLeave", function() GameTooltip:Hide() end)
	end
	panel.refresh = function ()
		if type(dbkey)=='table' then
			panel.edit:SetText(dbkey.get() or minv)
			panel.slider:SetValue(dbkey.get() or minv)
		else
			panel.edit:SetText(get(dbkey, dbkey2) or minv)
			panel.slider:SetValue(get(dbkey, dbkey2) or minv)
		end
	end

	return panel
end

local ddCount = 1
function createDropdown(ground, parent, name, text, tooltip, width, height, dbkey, dbkey2, values)
	local panel = createString(parent, name, text, width, height)
	panel.type = "dropdown"

	local tvalue
	if type(values)=='function' then
		tvalue = values()
	else
		tvalue = values
	end

	local dd_name
	if name then
		dd_name = name and name.."Dropdown"
	else
		dd_name = "bcf_options_dd_"..ddCount
		ddCount = ddCount + 1
	end
	panel.dropdown = CreateFrame("Frame", dd_name, panel, "UIDropDownMenuTemplate")

	panel.button = CreateFrame("Button", nil, panel)
	panel.button:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up")
	panel.button:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down")
	panel.button:SetDisabledTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled")
	local t = panel.button:CreateTexture(nil, "BACKGROUND")
	t:SetPoint("TOPLEFT", panel.button, "TOPLEFT", 0, 0)
	t:SetPoint("BOTTOMRIGHT", panel.button, "BOTTOMRIGHT", 0, 0)
	t:SetTexture("Interface\\Buttons\\UI-Common-MouseHilight")
	t:SetBlendMode("ADD")
	panel.button:SetHighlightTexture(t)
	panel.button:SetWidth(28)
	panel.button:SetHeight(28)
	panel.button:SetPoint("RIGHT", panel, "RIGHT", 2, 0)
	panel.button:SetScript("OnClick", function ()
		local function init(level)
			local temp_value, tvalue
			if type(values)=='function' then
				temp_value = values()
			else
				temp_value = values
			end
			if level==3 then
				for i=1, #temp_value do
					if type(temp_value[i])=='table' and type(temp_value[i].options)=='table' then
						for j=1, #temp_value[i].options do
							if type(temp_value[i].options[j])=='table' then
								if temp_value[i].options[j].text == UIDROPDOWNMENU_MENU_VALUE then
									tvalue = temp_value[i].options[j].options
									break
								end
							end
						end
					end
				end
			elseif level==2 then
				for i=1, #temp_value do
					if type(temp_value[i])=='table' then
						if temp_value[i].text == UIDROPDOWNMENU_MENU_VALUE then
							tvalue = temp_value[i].options
							break
						end
					end
				end
			elseif not level or level == 1 then
				tvalue = temp_value
			end
			if not tvalue then
				tvalue = {}
			end
			for i=1, #tvalue do
				local v = tvalue[i]
				local info = UIDropDownMenu_CreateInfo()
				if not v.value and v.options then
					info.hasArrow = true
					info.text = v.text
					info.value = v.text
					UIDropDownMenu_AddButton(info, level)
				else
					info.func = function ()
						UIDropDownMenu_SetSelectedValue(panel.dropdown, this.value)
						if type(dbkey)=='table' then
							dbkey.set(this.value)
							if dbkey.needRefresh then
								if ground and ground.refresh then
									ground.refresh()
								end
							end
						else
							set(this.value, dbkey, dbkey2)
						end
						panel.text:SetText(v.text)
						if v.func and type(v.func)=='function' then
							v.func()
						elseif v.func and type(v.func)=='string' then
							local f = getglobal(v.func)
							if f and type(f)=='function' then
								f()
							end
						end
					end
					local checked
					if type(dbkey)=='table' then
						checked = dbkey.get() == v.value
					else
						checked = get(dbkey, dbkey2) == v.value
					end
					info.checked = checked
					info.text = v.text
					info.value = v.value
					UIDropDownMenu_AddButton(info, level)
				end
			end
		end

		UIDropDownMenu_Initialize(panel.dropdown, init, "MENU")
		ToggleDropDownMenu(1, nil, panel.dropdown, panel.button, 20, 10);
	end)

	panel.text = panel:CreateFontString(nil, "OVERLAY","ChatFontNormal")
	panel.text:SetFontObject("ChatFontNormal")
	panel.text:SetTextColor(1,1,1)
	panel.text:SetPoint("RIGHT", panel.button, "LEFT", -2, 0)

	local getted_value
	if type(dbkey)=='table' then
		getted_value = dbkey.get()
	else
		getted_value = get(dbkey,dbkey2)
	end
	if getted_value then
		for i=1, #tvalue do
			if tvalue[i].value and tvalue[i].value == getted_value then
				panel.text:SetText(tvalue[i].text)
				break
			elseif tvalue[i].options and type(tvalue[i].options)=='table' then
				for j=1, #tvalue[i].options do
					if tvalue[i].options[j].value and tvalue[i].options[j].value == getted_value then
						panel.text:SetText(tvalue[i].options[j].text)
						break
					elseif tvalue[i].options[j].options and type(tvalue[i].options[j].options)=='table' then
						for k=1, #tvalue[i].options[j].options do
							if tvalue[i].options[j].options[k].value and tvalue[i].options[j].options[k].value == getted_value then
								panel.text:SetText(tvalue[i].options[j].options[k].text)
								break
							end
						end
					end
				end
			end
		end
	end
	panel.refresh = function ()
		local tvalue
		if type(values)=='function' then
			tvalue = values()
		else
			tvalue = values
		end
		local getted_value
		if type(dbkey)=='table' then
			getted_value = dbkey.get()
		else
			getted_value = get(dbkey,dbkey2)
		end
		if getted_value then
			for i=1, #tvalue do
				if tvalue[i].value and tvalue[i].value == getted_value then
					panel.text:SetText(tvalue[i].text)
					break
				elseif tvalue[i].options and type(tvalue[i].options)=='table' then
					for j=1, #tvalue[i].options do
						if tvalue[i].options[j].value and tvalue[i].options[j].value == getted_value then
							panel.text:SetText(tvalue[i].options[j].text)
							break
						elseif tvalue[i].options[j].options and type(tvalue[i].options[j].options)=='table' then
							for k=1, #tvalue[i].options[j].options do
								if tvalue[i].options[j].options[k].value and tvalue[i].options[j].options[k].value == getted_value then
									panel.text:SetText(tvalue[i].options[j].options[k].text)
									break
								end
							end
						end
					end
				end
			end
		end
	end

	return panel
end

function createWindowFrame(name, titletext, width, height, border, level)
	local frame = CreateFrame("Frame", name, UIParent)
	frame:SetWidth(width)
	frame:SetHeight(height)
	frame:SetFrameStrata(border and "DIALOG" or "LOW")
	frame:SetPoint("CENTER", UIParent)
	frame:SetMovable(1)
	frame:SetClampedToScreen(1)
	frame:SetFrameLevel(level or 4)
	frame:SetFrameStrata(border and "DIALOG" or "MEDIUM")
	frame:EnableMouse(true)
	frame:RegisterForDrag("LeftButton")
	frame:SetScript("OnDragStart", frame.StartMoving)
	frame:SetScript("OnDragStop", frame.StopMovingOrSizing)

	local title = createGraBar(frame, titletext)
	frame:SetBackdrop({
		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
		edgeFile = border and "Interface\\Tooltips\\UI-Tooltip-Border" or "",
		tile = true, tileSize = border and 16 or 0, edgeSize = border and 16 or 0,
		insets={left = border and 5 or 0, right = border and 5 or 0, top = border and 5 or 10, bottom = border and 5 or 0}
	})
	frame:SetBackdropColor(0,0,0, border and 0.9 or 0.5)

	if border then
		title:SetPoint("TOPLEFT", frame, "TOPLEFT", 4, -4)
		title:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", -4, -24)
	else
		title:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0)
		title:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", 0, -20)
	end


	local tex = title:CreateTexture(nil, "ARTWORK")
	tex:SetWidth(20)
	tex:SetHeight(20)
	tex:SetTexture("Interface\\AddOns\\bcf_options\\resting.tga")
	tex:SetPoint("LEFT")
	title.texture = tex

	frame.title = title

	local dot = CreateFrame("Button", nil, title)
	dot:SetBackdrop({
		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
		edgeFile = "",
		tile = true, tileSize = 5, edgeSize = 16,
		insets={left = 0, right = 0, top = 0, bottom = 0}
	})
	dot:SetWidth(12)
	dot:SetHeight(12)
	dot:SetFrameLevel(title:GetFrameLevel()+1)
	dot:SetBackdropColor(0.0392, 0.1411, 0.4156, 1)
	dot:SetPoint("RIGHT", title, "RIGHT", -20+15, 0)
	dot:SetScript("OnClick", function() frame:Hide() end)
	dot:SetScript("OnEnter", function()
		GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
		GameTooltip:SetText("닫기", nil, nil, nil, nil, 1)
		GameTooltip:Show()
		this:SetBackdropColor(.7,0,0,0.8)
	end)
	dot:SetScript("OnLeave", function()
		GameTooltip:Hide()
		this:SetBackdropColor(0.0392, 0.1411, 0.4156, 1)
	end)
	frame.closeButton = dot

	frame:SetScript("OnShow", function ()
		if this.controls and #this.controls>0 then
			for i=1, #this.controls do
				local e = this.controls[i]
				if e.refresh then
					e.refresh()
				end
			end
		end
	end)

	return frame
end

function createMainFrame()
	local frame = createWindowFrame("BCFOptions", "bcf options", 600, 400, nil, 3)
	addon.frame = frame
	frame.subFrames = {}
	frame:SetScript("OnHide", function (this)
		if #addon.frame.subFrames>0 then
			for i=1, #addon.frame.subFrames do
				addon.frame.subFrames[i]:Hide() -- 부모창 닫으면 자식창들도 닫음
			end
		end
	end)

	frame:RegisterEvent("PLAYER_REGEN_ENABLED")
	frame:RegisterEvent("PLAYER_REGEN_DISABLED")
	local function show()
		if addon.inCombatLockdown then
			frame:Hide()
		end
	end
	frame:SetScript("OnEvent", function()
		addon.inCombatLockdown = event == "PLAYER_REGEN_DISABLED"
		show()
	end)

	local dot = CreateFrame("Button", nil, frame.title)
	dot:SetBackdrop({
		bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
		edgeFile = "",
		tile = true, tileSize = 5, edgeSize = 16,
		insets={left = 0, right = 0, top = 0, bottom = 0}
	})
	dot:SetWidth(12)
	dot:SetHeight(12)
	dot:SetFrameLevel(frame.title:GetFrameLevel()+1)
	dot:SetBackdropColor(0.0392, 0.1411, 0.4156, 1)
	dot:SetPoint("RIGHT", frame.closeButton, "LEFT", -5, 0)
	dot:SetScript("OnClick", function() addon:ConfirmFrame("bcf의 모든 설정을 초기화 하시겠습니까?", "초기화", resetDB) end)
	dot:SetScript("OnEnter", function()
		GameTooltip:SetOwner(this, "ANCHOR_BOTTOMLEFT")
		GameTooltip:SetText("설정 초기화", nil, nil, nil, nil, 1)
		GameTooltip:Show()
		this:SetBackdropColor(.7,0,0,0.8)
	end)
	dot:SetScript("OnLeave", function()
		GameTooltip:Hide()
		this:SetBackdropColor(0.0392, 0.1411, 0.4156, 1)
	end)
	frame.resetButton = dot

	frame:Hide()

end

function drawConfigFrame(win, opt, opt_name)
	win.controls = win.controls or {}

	if not opt then
		return
	end

	for i=1, #win.controls do
		if win.controls[i] then
			win.controls[i]:Hide() -- 아...이거 메모리 누순데..ㅠ_ㅠ 콜렉터가 잘 처리해주길~_~;;
			win.controls[i] = nil
		end
	end

	local width = win:GetWidth()-20
	local tooltip = "'표시 문자열'은 다음과같은 태그를 이용하실수 있습니다.|n|cffffffff%a|r = 피해량/치유량 등의 수치|n|cffffffff%ea|r = 추가 피해량/치유량|n|cffffffff%s|r = 스킬/주문 이름|n|cffffffff%es|r = 추가 스킬/주문 이름|n|cffffffff%m|r = 방어타입(저항,막음,방어,흡수..)|n|cffffffff%c|r = 피해속성(물리,화염,냉기..)|n|cffffffff%sc|r = 행동주체,행위자(source)|n|cffffffff%t|r = 피해자, 대상자(target)|n|cffffffff%p|r = 파워타입(마나,분노,기력)"
	if opt.showMiss then
		local chk1 = createCheckBox2(win, win, nil, "방어행동 메세지 표시", "피함/저항/흡수/막음/방어/빗맞음 등의 방어관련 메세지를 출력할지 선택합니다.", width, 20, opt_name, "showMiss")
		chk1:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		tinsert(win.controls, chk1)
	end
	if opt.showDot then
		local chk_dot = createCheckBox2(win, win, nil, "주기적인 피해 표시", "DOT 피해 메세지를 출력할지 선택합니다.", width, 20, opt_name, "showDot")
		if #win.controls>0 then
			chk_dot:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			chk_dot:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, chk_dot)
	end
	if opt.showHot then
		local chk_hot = createCheckBox2(win, win, nil, "주기적인 회복 표시", "주기적인 회복 메세지를 출력할지 선택합니다.", width, 20, opt_name, "showHot")
		if #win.controls>0 then
			chk_hot:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			chk_hot:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, chk_hot)
	end
	if opt.enterMsg then
		local edit_enterMsg = createEditBox(win, win, nil, "전투 시작 표시 문자열", "설정 가능한 태그가 없습니다.ㅋ", width, 20, opt_name, 'enterMsg')
		if #win.controls>0 then
			edit_enterMsg:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			edit_enterMsg:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, edit_enterMsg)
	end
	if opt.leaveMsg then
		local edit_leaveMsg = createEditBox(win, win, nil, "전투 종료 표시 문자열", "설정 가능한 태그가 없습니다.ㅋ", width, 20, opt_name, 'leaveMsg')
		if #win.controls>0 then
			edit_leaveMsg:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			edit_leaveMsg:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, edit_leaveMsg)
	end
	if opt.msg then
		local edit1 = createEditBox(win, win, nil, "표시 문자열", tooltip, width, 20, opt_name, 'msg')
		if #win.controls>0 then
			edit1:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			edit1:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, edit1)
	end

	if opt.missMsg then
		local edit2 = createEditBox(win, win, nil, "피함 표시 문자열", tooltip, width, 20, opt_name, 'missMsg')
		if #win.controls>0 then
			edit2:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			edit2:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, edit2)
	end

	if opt.drainMsg then
		local edit3 = createEditBox(win, win, nil, "파워소진 표시 문자열", "적에 의해 자신의 마나/분노/기력이 소진될때 나타나는 메시지입니다.|n"..tooltip, width, 20, opt_name, 'drainMsg')
		if #win.controls>0 then
			edit3:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			edit3:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, edit3)
	end
	if opt.leechMsg then
		local edit_leech = createEditBox(win, win, nil, "파워흡수 표시 문자열", "대상의 마나/분노/기력을 흡수할때나 대상에 의해 흡수 당할때 나타나는 메시지입니다.|n"..tooltip, width, 20, opt_name, 'leechMsg')
		if #win.controls>0 then
			edit_leech:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			edit_leech:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, edit_leech)
	end

	if opt.filter then
		local slider_filter = createSlider(win, win, nil, "필터", "지정한 필터수치 미만의 피해/치유/파워획득량은 표시하지 않습니다.|n|cffff7f00필터수치를 0으로 설정할경우 필터링하지 않습니다.|n범위 0~5000|r", width, 20, opt_name, 'filter', 0, 5000, 1)
		if #win.controls>0 then
			slider_filter:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			slider_filter:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, slider_filter)
	end

	if opt.size then
		local slider1 = createSlider(win, win, nil, "글자 크기", "메세지 글자 크기를 설정합니다.", width, 20, opt_name, 'size', 10, 30, 1)
		if #win.controls>0 then
			slider1:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			slider1:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, slider1)
	end

	if opt.color then
		local color1 = createColorPicker(win, win, nil, "색상", "메세지의 색상을 설정합니다.", width, 20, opt_name, "color")
		if #win.controls>0 then
			color1:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color1:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color1)
	end
	if opt.font then
		local dd1 = createDropdown(win, win, nil, "글꼴", "메시지의 글꼴을 설정합니다.", width, 20, opt_name, "font", function () return fonts end)
		if #win.controls>0 then
			dd1:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			dd1:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, dd1)
	end

	if opt.outline then
		local dd2 = createDropdown(win, win, nil, "글꼴 외각선", "출력되는 메세지 글꼴의 외각선을 선택합니다.", width, 20, opt_name, "outline", function () return outlines end)
		if #win.controls>0 then
			dd2:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			dd2:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, dd2)
	end

	if opt.scrollArea and db.scrollAreas then
		local function getAreas()
			local sa = {}
			for i=1, #db.scrollAreas do
				tinsert(sa, { text=db.scrollAreas[i].name, value=db.scrollAreas[i].name })
			end
			return sa
		end
		local dd3 = createDropdown(win, win, nil, "스크롤 영역", "메세지를 출력할 스크롤 영역을 선택합니다.", width, 20, opt_name, "scrollArea", getAreas)
		if #win.controls>0 then
			dd3:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			dd3:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, dd3)
	end
	if opt.scrollType then
		local dd4 = createDropdown(win, win, nil, "애니메이션 효과", "출력되는 메세지의 움직임 효과를 선택합니다.", width, 20, opt_name, "scrollType", animationTypes)
		if #win.controls>0 then
			dd4:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			dd4:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, dd4)
	end
	if opt.align then
		local dd_align = createDropdown(win, win, nil, "메세지 정렬", "메세지 정렬 방식을 선택합니다.", width, 20, opt_name, "align", messageAligns)
		if #win.controls>0 then
			dd_align:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			dd_align:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, dd_align)
	end
	if opt.iconalign then
		local dd_iconalign = createDropdown(win, win, nil, "아이콘 위치", "아이콘이 표시되는 위치를 선택합니다.", width, 20, opt_name, "iconalign", iconAligns)
		if #win.controls>0 then
			dd_iconalign:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			dd_iconalign:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, dd_iconalign)
	end

	if opt.none then
		local color_none = createColorPicker(win, win, nil, "일반 피해 색상*", "속성별 색상 표시 기능을 해제했을때 대신 표시할 색상을 설정합니다.", width, 20, opt_name, "none")
		color_none.text:SetTextColor(1,1,1)
		if #win.controls>0 then
			color_none:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_none:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_none)
	end
	if opt.physical then
		local color_physical = createColorPicker(win, win, nil, "물리 피해 색상", "물리 피해 색상을 설정합니다.", width, 20, opt_name, "physical")
		if #win.controls>0 then
			color_physical:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_physical:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_physical)
	end
	if opt.holy then
		local color_holy = createColorPicker(win, win, nil, "신성 피해 색상", "신성 피해 색상을 설정합니다.", width, 20, opt_name, "holy")
		if #win.controls>0 then
			color_holy:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_holy:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_holy)
	end
	if opt.fire then
		local color_fire = createColorPicker(win, win, nil, "화염 피해 색상", "화염 피해 색상을 설정합니다.", width, 20, opt_name, "fire")
		if #win.controls>0 then
			color_fire:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_fire:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_fire)
	end
	if opt.frost then
		local color_frost = createColorPicker(win, win, nil, "냉기 피해 색상", "냉기 피해 색상을 설정합니다.", width, 20, opt_name, "frost")
		if #win.controls>0 then
			color_frost:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_frost:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_frost)
	end
	if opt.arcane then
		local color_arcane = createColorPicker(win, win, nil, "비전 피해 색상", "비전 피해 색상을 설정합니다.", width, 20, opt_name, "arcane")
		if #win.controls>0 then
			color_arcane:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_arcane:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_arcane)
	end
	if opt.nature then
		local color_nature = createColorPicker(win, win, nil, "자연 피해 색상", "자연 피해 색상을 설정합니다.", width, 20, opt_name, "nature")
		if #win.controls>0 then
			color_nature:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_nature:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_nature)
	end
	if opt.shadow then
		local color_shadow = createColorPicker(win, win, nil, "암흑 피해 색상", "암흑 피해 색상을 설정합니다.", width, 20, opt_name, "shadow")
		if #win.controls>0 then
			color_shadow:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_shadow:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_shadow)
	end

	if opt.mana then
		local color_mana = createColorPicker(win, win, nil, "마나 색상", "마나 색상을 설정합니다.", width, 20, opt_name, "mana")
		if #win.controls>0 then
			color_mana:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_mana:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_mana)
	end
	if opt.rage then
		local color_rage = createColorPicker(win, win, nil, "분노 색상", "분노 색상을 설정합니다.", width, 20, opt_name, "rage")
		if #win.controls>0 then
			color_rage:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_rage:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_rage)
	end
	if opt.energy then
		local color_energy = createColorPicker(win, win, nil, "기력 색상", "기력 색상을 설정합니다.", width, 20, opt_name, "energy")
		if #win.controls>0 then
			color_energy:SetPoint("TOPLEFT", win.controls[#win.controls], "BOTTOMLEFT", 0, -5)
		else
			color_energy:SetPoint("TOPLEFT", win, "TOPLEFT", 10, -30)
		end
		tinsert(win.controls, color_energy)
	end
	win:SetHeight( #win.controls*25 + 40 )
end

function enableCheckbox(button, r, g, b)
	button.checkButton:Enable()
	if r and g and b then
		button.checkButton.text:SetTextColor(r, g, b)
	else
		button.checkButton.text:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
	end
	if button.button then
		if button.checkButton:GetChecked() then
			button.button:Enable()
		else
			button.button:Disable()
		end
	end
end
function disableCheckbox(button)
	button.checkButton:Disable()
	button.checkButton.text:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b)
	if button.button then
		button.button:Disable()
	end
end

function drawComplexOption(parent, frontOpt, var, opt_var, text, tooltip, buttonText, buttonTooltip, width, height)

	local panel = CreateFrame("Frame", nil, parent)
	panel:SetWidth(parent:GetWidth()-20)
	panel:SetHeight(20)
	if frontOpt then
		panel:SetPoint("TOPLEFT", frontOpt, "BOTTOMLEFT", 0, -5)
	else
		panel:SetPoint("TOPLEFT", parent, "TOPLEFT", 10, -17)
	end

	panel.checkButton = createCheckBox(panel, text, tooltip)
	panel.checkButton:SetPoint("LEFT")
	panel.checkButton:SetChecked(get(var))
	panel.checkButton:SetScript("OnClick", function()
		if this:GetChecked() then
			panel.button:Enable()
		else
			panel.button:Disable()
			if panel.configFrame:IsShown() then
				panel.configFrame:Hide()
			end
		end
		set(this:GetChecked(), var)
	end)

	panel.configFrame = createWindowFrame(nil, buttonText, width or 300, height or 250, true)
	tinsert(addon.frame.subFrames, panel.configFrame) -- 최상위 설정창의 자식창으로 등록
	panel.configFrame:SetScript("OnShow", function (this)
		drawConfigFrame(this, db[opt_var], opt_var)
	end)

	panel.configFrame:Hide()

	panel.button = createButton(panel, "설정", buttonTooltip)
	panel.button:SetWidth(45)
	panel.button:SetHeight(21)
	panel.button:SetPoint("RIGHT")
	panel.button:SetScript("OnClick", function() panel.configFrame:Show() end)
	if not get(var) then
		panel.button:Disable()
	end

	panel.refresh = function ()
		if get(var) then
			panel.checkButton:SetChecked(true)
			panel.button:Enable()
			if panel.configFrame:IsShown() then
				if #panel.configFrame.controls then
					for i=1, #panel.configFrame.controls do
						if panel.configFrame.controls[i].refresh then
							panel.configFrame.controls[i].refresh()
						end
					end
				end
			end
		else
			panel.checkButton:SetChecked(false)
			panel.button:Disable()
			if panel.configFrame:IsShown() then
				if #panel.configFrame.controls then
					panel.configFrame:Hide()
				end
			end
		end
	end

	return panel
end

function drawCheckAndButtonOpt(parent, frontOpt, var, options, destPanel, text, tooltip, buttonTooltip, titleText)

	local panel = CreateFrame("Frame", nil, parent)
	panel:SetWidth(parent:GetWidth()-20)
	panel:SetHeight(20)
	if frontOpt then
		panel:SetPoint("TOPLEFT", frontOpt, "BOTTOMLEFT", 0, -5)
	else
		panel:SetPoint("TOPLEFT", parent, "TOPLEFT", 10, -17)
	end

	panel.checkButton = createCheckBox(panel, text, tooltip)
	panel.checkButton:SetPoint("LEFT")
	panel.checkButton:SetChecked(get(var))
	panel.checkButton:SetScript("OnClick", function()
		if this:GetChecked() then
			panel.button:Enable()
		else
			panel.button:Disable()
		end
		set(this:GetChecked(), var)
	end)

	panel.button = createButton(panel, "설정", buttonTooltip)
	panel.button:SetWidth(45)
	panel.button:SetHeight(21)
	panel.button:SetPoint("RIGHT")
	panel.button:SetScript("OnClick", function()
		if not destPanel then
			return
		end
		local opt
		local tooltip = "'표시 문자열'은 다음과같은 태그를 이용하실수 있습니다.|n|cffffffff%a|r = 피해량/치유량 등의 수치|n|cffffffff%ea|r = 추가 피해량/치유량|n|cffffffff%s|r = 스킬/주문 이름|n|cffffffff%m|r = 방어타입(저항,막음,방어,흡수..)|n|cffffffff%c|r = 피해속성(물리,화염,냉기..)|n|cffffffff%sc|r = 행동주체,행위자(source)|n|cffffffff%t|r = 피해자, 대상자(target)|n|cffffffff%p|r = 파워타입(마나,분노,기력)"
		if options and type(options)=='function' then
			opt = options()
		elseif options and type(options)=='table' then
			opt = options
		end
		
		if destPanel.controls and #destPanel.controls>0 then
			for i=1, #destPanel.controls do
				destPanel.controls[i]:Hide()
				destPanel.controls[i] = nil
			end
		end
		local function showHit()
			if options=="incomingHit"
			or options=="incomingPetHit"
			or options=="incomingFocusHit"
			or options=="outgoingHit"
			or options=="outgoingPetHit"
			or options=="outgoingFocusHit"
			then
				return true
			end
		end
		local values = {
			{
				type = "text",
				text = "일반 설정",
				size = 20,
				font = "Fonts\\2002b.TTF",
			},
			{
				type = "group",
				options = {
					{
						show = showHit,
						type = "check",
						text = "방어행동 메세지 표시",
						tooltip = "피함/저항/흡수/막음/방어/빗맞음 등의 방어관련 메세지를 출력할지 선택합니다.",
						value = {
							get = function ()
								return db[options].showMiss
							end,
							set = function (value)
								db[options].showMiss = value
							end,
						},
					},
					{
						show = showHit,
						type = "check",
						text = "주기적인 피해 표시",
						tooltip = "DOT 피해 메세지를 출력할지 선택합니다.",
						value = {
							get = function ()
								return db[options].showDot
							end,
							set = function (value)
								db[options].showDot = value
							end,
						},
					},
					{
						show = function ()
							if options=="incomingHeal" or options=="outgoingHeal" then
								return true
							end
						end,
						type = "check",
						text =  "주기적인 회복 표시",
						tooltip = "주기적인 회복 메세지를 출력할지 선택합니다.",
						value = {
							get = function ()
								return db[options].showHot
							end,
							set = function (value)
								db[options].showHot = value
							end,
						},
					},
					{
						type = "editbox",
						text = "표시 문자열",
						tooltip = tooltip,
						value = {
							get = function ()
								return db[options].msg
							end,
							set = function (value)
								db[options].msg = value
							end,
						},
					},
					{
						show = showHit,
						type = "editbox",
						text = "피함 표시 문자열",
						tooltip = tooltip,
						value = {
							get = function ()
								return db[options].missMsg
							end,
							set = function (value)
								db[options].missMsg = value
							end,
						},
					},
					{
						show = showHit,
						type = "editbox",
						text = "파워소진 표시 문자열",
						tooltip = "적에 의해 자신의 마나/분노/기력이 소진될때 나타나는 메시지입니다.|n"..tooltip,
						value = {
							get = function ()
								return db[options].drainMsg
							end,
							set = function (value)
								db[options].drainMsg = value
							end,
						},
					},
					{
						type = "slider",
						text = "필터",
						tooltip = "지정한 필터수치 미만의 피해/치유/파워획득량은 표시하지 않습니다.|n|cffff7f00필터수치를 0으로 설정할경우 필터링하지 않습니다.|n범위 0~5000|r",
						min = 0,
						max = 5000,
						step = 1,
						value = {
							get = function ()
								return db[options].filter or 0
							end,
							set = function (value)
								db[options].filter = tonumber(value)
							end,
						},
					},
					{
						type = "slider",
						text = "글자 크기",
						tooltip = "메세지 글자 크기를 설정합니다.",
						min = 10,
						max = 30,
						step = 1,
						value = {
							get = function ()
								return db[options].size or 0
							end,
							set = function (value)
								db[options].size = tonumber(value)
							end,
						},
					},
					{
						type = "dropdown",
						text = "글꼴",
						tooltip = "메세지의 글꼴을 설정합니다.",
						value = {
							get = function ()
								return db[options].font
							end,
							set = function (value)
								db[options].font = value
							end,
						},
						options = fonts,
					},
					{
						type = "dropdown",
						text = "글꼴 외각선",
						tooltip = "출력되는 메세지 글꼴의 외각선을 선택합니다.",
						value = {
							get = function ()
								return db[options].outline
							end,
							set = function (value)
								db[options].outline = value
							end,
						},
						options = outlines,
					},
					{
						type = "dropdown",
						text = "스크롤 영역",
						tooltip = "메세지를 출력할 스크롤 영역을 선택합니다.",
						value = {
							get = function ()
								return db[options].scrollArea
							end,
							set = function (value)
								db[options].scrollArea = value
							end,
						},
						options = function ()
							local sa = {}
							for i=1, #db.scrollAreas do
								tinsert(sa, { text=db.scrollAreas[i].name, value=db.scrollAreas[i].name })
							end
							return sa
						end,
					},
					{
						type = "dropdown",
						text = "애니메이션 효과",
						tooltip = "출력되는 메세지의 움직임 효과를 선택합니다.",
						value = {
							get = function ()
								return db[options].scrollType
							end,
							set = function (value)
								db[options].scrollType = value
							end,
						},
						options = animationTypes,
					},
					{
						type = "dropdown",
						text = "메세지 정렬",
						tooltip = "메세지 정렬 방식을 선택합니다.",
						value = {
							get = function ()
								return db[options].align
							end,
							set = function (value)
								db[options].align = value
							end,
						},
						options = messageAligns,
					},
					{
						type = "dropdown",
						text = "아이콘 위치",
						tooltip = "아이콘이 표시되는 위치를 선택합니다.",
						value = {
							get = function ()
								return db[options].iconalign
							end,
							set = function (value)
								db[options].iconalign = value
							end,
						},
						options = iconAligns,
					},
				},
			},
			{
				type = "null",
				height = 8,
			},
			{
				type = "text",
				text = "치명/극대화 설정",
				size = 20,
				font = "Fonts\\2002b.TTF",
			},
			{
				type = "group",
				options = {
					{
						type = "editbox",
						text = "표시 문자열",
						tooltip = tooltip,
						value = {
							get = function ()
								return db[options].crit.msg
							end,
							set = function (value)
								db[options].crit.msg = value
							end,
						},
					},
					{
						show = showHit,
						type = "editbox",
						text = "파워소진 표시 문자열",
						tooltip = "적에 의해 자신의 마나/분노/기력이 소진될때 나타나는 메시지입니다.|n"..tooltip,
						value = {
							get = function ()
								return db[options].crit.drainMsg
							end,
							set = function (value)
								db[options].crit.drainMsg = value
							end,
						},
					},
					{
						type = "slider",
						text = "필터",
						tooltip = "지정한 필터수치 미만의 피해/치유/파워획득량은 표시하지 않습니다.|n|cffff7f00필터수치를 0으로 설정할경우 필터링하지 않습니다.|n범위 0~5000|r",
						min = 0,
						max = 5000,
						step = 1,
						value = {
							get = function ()
								return db[options].crit.filter or 0
							end,
							set = function (value)
								db[options].crit.filter = tonumber(value)
							end,
						},
					},
					{
						type = "slider",
						text = "글자 크기",
						tooltip = "메세지 글자 크기를 설정합니다.",
						min = 10,
						max = 30,
						step = 1,
						value = {
							get = function ()
								return db[options].crit.size or 0
							end,
							set = function (value)
								db[options].crit.size = tonumber(value)
							end,
						},
					},
					{
						type = "dropdown",
						text = "글꼴",
						tooltip = "메세지의 글꼴을 설정합니다.",
						value = {
							get = function ()
								return db[options].crit.font
							end,
							set = function (value)
								db[options].crit.font = value
							end,
						},
						options = fonts,
					},
					{
						type = "dropdown",
						text = "글꼴 외각선",
						tooltip = "출력되는 메세지 글꼴의 외각선을 선택합니다.",
						value = {
							get = function ()
								return db[options].crit.outline
							end,
							set = function (value)
								db[options].crit.outline = value
							end,
						},
						options = outlines,
					},
					{
						type = "dropdown",
						text = "스크롤 영역",
						tooltip = "메세지를 출력할 스크롤 영역을 선택합니다.",
						value = {
							get = function ()
								return db[options].crit.scrollArea
							end,
							set = function (value)
								db[options].crit.scrollArea = value
							end,
						},
						options = function ()
							local sa = {}
							for i=1, #db.scrollAreas do
								tinsert(sa, { text=db.scrollAreas[i].name, value=db.scrollAreas[i].name })
							end
							return sa
						end,
					},
					{
						type = "dropdown",
						text = "애니메이션 효과",
						tooltip = "출력되는 메세지의 움직임 효과를 선택합니다.",
						value = {
							get = function ()
								return db[options].crit.scrollType
							end,
							set = function (value)
								db[options].crit.scrollType = value
							end,
						},
						options = animationTypes,
					},
					{
						type = "dropdown",
						text = "메세지 정렬",
						tooltip = "메세지 정렬 방식을 선택합니다.",
						value = {
							get = function ()
								return db[options].crit.align
							end,
							set = function (value)
								db[options].crit.align = value
							end,
						},
						options = messageAligns,
					},
					{
						type = "dropdown",
						text = "아이콘 위치",
						tooltip = "아이콘이 표시되는 위치를 선택합니다.",
						value = {
							get = function ()
								return db[options].crit.iconalign
							end,
							set = function (value)
								db[options].crit.iconalign = value
							end,
						},
						options = iconAligns,
					},
				},
			},
		}
		local config = drawScrollFrame(destPanel, nil, values, destPanel:GetWidth()-20, 226, false, 5)
		tinsert(destPanel.controls, config)
		destPanel.text:SetText(titleText.." 설정")
	end)
	if not get(var) then
		panel.button:Disable()
	end

	panel.refresh = function ()
		if get(var) then
			panel.checkButton:SetChecked(true)
			panel.button:Enable()
		else
			panel.checkButton:SetChecked(false)
			panel.button:Disable()
		end
	end

	return panel
end

function drawCheckOpt(parent, frontOpt, var, text, tooltip, disabled, dependency)
	local panel = CreateFrame("Frame", nil, parent)
	panel:SetWidth(parent:GetWidth()-20)
	panel:SetHeight(20)
	if frontOpt then
		panel:SetPoint("TOPLEFT", frontOpt, "BOTTOMLEFT", 0, -5)
	else
		panel:SetPoint("TOPLEFT", parent, "TOPLEFT", 10, -17)
	end

	panel.checkButton = createCheckBox(panel, text, tooltip)
	if dependency then
		panel.checkButton:SetPoint("LEFT", 17, 0)
	else
		panel.checkButton:SetPoint("LEFT")
	end
	panel.checkButton:SetChecked(get(var))
	panel.checkButton:SetScript("OnClick", function()
		set(this:GetChecked(), var)
		if panel.controls and #panel.controls > 0 then
			for i=1, #panel.controls do
				if this:GetChecked() then
					enableCheckbox(panel.controls[i])
				else
					disableCheckbox(panel.controls[i])
				end
			end
		end
	end)

	if disabled then
		disableCheckbox(panel)
	end

	panel.refresh = function ()
		if dependency then
			if not dependency.checkButton:GetChecked() then
				disableCheckbox(panel)
			else
				enableCheckbox(panel)
				panel.checkButton:SetChecked(get(var))
			end
		else
			panel.checkButton:SetChecked(get(var))
		end
	end

	if dependency then
		if not dependency.checkButton:GetChecked() then
			disableCheckbox(panel)
		end
		dependency.controls = dependency.controls or {}
		tinsert(dependency.controls, panel)
	end

	return panel
end

local groupStack = {}
function __drawChildControls(panel, parent, options, width, padding)
	local opt
	local innerHeight = 0
	if options and type(options)=='function' then
		opt = options()
	elseif options and type(options)=='table' then
		opt = options
	end
	local count = 0
	for i=1, #opt do
		local element
		if (opt[i].show and type(opt[i].show)=='function' and opt[i].show()) or not opt[i].show then
			if opt[i].type == 'header' then
				element = createHeaderButton(panel, parent, panel.controls, opt[i].text, width, 20, opt[i].click, opt[i].deleteClick)
			elseif opt[i].type == 'editbox' then
				element = createEditBox(panel, parent, nil, opt[i].text, opt[i].tooltip, width, 20, opt[i].value, nil, opt[i].wide, opt[i].allowBlank)
			elseif opt[i].type == 'slider' then
				element = createSlider(panel, parent, nil, opt[i].text, opt[i].tooltip, width, 20, opt[i].value, nil, opt[i].min, opt[i].max, opt[i].step)
			elseif opt[i].type == 'color' then
				element = createColorPicker(panel, parent, nil, opt[i].text, opt[i].tooltip, width, 20, opt[i].value)
			elseif opt[i].type == 'check' then
				element = createCheckBox2(panel, parent, nil, opt[i].text, opt[i].tooltip, width, 20, opt[i].value)
			elseif opt[i].type == 'dropdown' then
				element = createDropdown(panel, parent, nil, opt[i].text, opt[i].tooltip, width, 20, opt[i].value, nil, opt[i].options)
			elseif opt[i].type == 'null' then
				element = createNullPanel(parent, nil, width, opt[i].height or 20)
			elseif opt[i].type == 'text' then
				element = createString(parent, nil, opt[i].text, width, 20)
				if opt[i].fontobject then
					element.text:SetFontObject(opt[i].fontobject)
				elseif opt[i].font and opt[i].font~="" then
					element.text:SetFont(opt[i].font, opt[i].size or 20, opt[i].outline or "OUTLINE")
				elseif opt[i].size then
					element.text:SetTextHeight(opt[i].size)
				end
				if opt[i].r and opt[i].g and opt[i].b then
					element.text:SetTextColor(opt[i].r, opt[i].g, opt[i].b)
				end
				--element.text:SetNonSpaceWrap(true)
			elseif opt[i].type == 'radio' then
				element = createRadioButton(panel, parent, nil, width, opt[i].value, nil, opt[i].options)
			elseif opt[i].type == 'choice' then
				element = createCheckGroupButton(panel, parent, nil, width, opt[i].value, nil, opt[i].options, opt[i].col)
			elseif opt[i].type == 'button' then
				element = createButton(parent, opt[i].text, opt[i].tooltip, opt[i].isGrayButton)
				element.type = "button"
				element:SetWidth(opt[i].width or width)
				element:SetHeight(opt[i].height or 24)
				element:SetScript("OnClick", function ()
					if opt[i].func and type(opt[i].func)=='function' then
						opt[i].func()
					elseif opt[i].func and type(opt[i].func)=='string' then
						local func = getglobal(opt[i].func)
						if func and type(func)=='function' then
							func()
						end
					end
				end)
			elseif opt[i].type == "subCondition" then
				element = createSubConditionElement(panel, parent, opt[i].getText, opt[i].tooltip, width, 20, opt[i].func, opt[i].deleteFunc)
			elseif opt[i].type == 'group' then
				local group = createPanel(parent, nil, width, 20, 0, 0, 0, .3)
				if opt[i].text then
					group.title = createGraBar(group, opt[i].text)
				end
				if i==1 then
					group:SetPoint("TOPLEFT", padding, padding*-1 )
				else
					group:SetPoint("TOPLEFT", panel.controls[#panel.controls], "BOTTOMLEFT", 0, padding*-1)
				end
				group.type = "group"
				tinsert(panel.controls, group)
				group.index = #panel.controls

				local ih = 0
				ih = __drawChildControls(panel, group, opt[i].options, group:GetWidth()-10, padding)

				group:SetHeight(ih+padding)
				innerHeight = innerHeight + group:GetHeight() + padding
				tinsert(groupStack, group)
			end

			if element then
				if count==0 then
					element:SetPoint("TOPLEFT", padding, padding*-1 )
				else
					local lastGroup = tremove(groupStack)
					if lastGroup then
						element:SetPoint("TOPLEFT", lastGroup, "BOTTOMLEFT", 0, padding*-1)
					else
						element:SetPoint("TOPLEFT", panel.controls[#panel.controls], "BOTTOMLEFT", 0, padding*-1)
					end
				end
				tinsert(panel.controls, element)
				element.index = #panel.controls
				innerHeight = innerHeight + element:GetHeight() + padding
				count = count + 1
			end
			--hdr = nil
		end
	end
	return innerHeight
end

local sf_count = 1
function drawScrollFrame(parent, frontCtrl, optFunc, width, height, scrollBarHideable, padding)
	if not optFunc then
		return
	end

	padding = padding or 0

	local panel = createPanel(parent, nil, width, height, 0, 0, 0, .3)
	panel.selectedIndex = 1

	if frontCtrl then
		panel:SetPoint("TOPLEFT", frontCtrl, "BOTTOMLEFT", 0, -5)
	else
		panel:SetPoint("TOPLEFT", parent, "TOPLEFT", 10, -17)
	end

	local sf_name = "bcf_options_scroll_"..sf_count
	sf_count = sf_count + 1

	panel.scrollFrame = CreateFrame("ScrollFrame", sf_name, panel, "FauxScrollFrameTemplate")
	if scrollBarHideable~=false then
		panel.scrollFrame.scrollBarHideable = true
	end
	panel.scrollFrame:SetPoint("TOPLEFT", 1, -1)
	if panel.scrollFrame.scrollBarHideable then
		panel.scrollFrame:SetPoint("BOTTOMRIGHT", -1, 1)
	else
		panel.scrollFrame:SetPoint("BOTTOMRIGHT", -24, 1)
	end
	panel.scrollFrame:SetScript("OnScrollRangeChanged", function ()
		ScrollFrame_OnScrollRangeChanged(arg2)
		if this.scrollBarHideable then
			local scrollrange = arg2
			if ( not scrollrange ) then
				scrollrange = panel.scrollFrame:GetVerticalScrollRange()
			end
			if ( floor(scrollrange) == 0 ) then
				panel.scrollFrame:SetPoint("TOPLEFT", 1, -1)
				panel.scrollFrame:SetPoint("BOTTOMRIGHT", -1, 1)
				if #panel.controls > 0 then
					for i=1, #panel.controls do
						panel.controls[i]:SetWidth(panel:GetWidth())
					end
				end
			else
				panel.scrollFrame:SetPoint("TOPLEFT", 1, -1)
				panel.scrollFrame:SetPoint("BOTTOMRIGHT", -24, 1)
				if #panel.controls > 0 then
					for i=1, #panel.controls do
						panel.controls[i]:SetWidth(panel.scrollFrame:GetWidth())
					end
				end
			end
		end
	end)

	panel.scrollFrame.child = getglobal(panel.scrollFrame:GetName().."ScrollChildFrame")
	panel.scrollFrame.scrollBar = getglobal(panel.scrollFrame:GetName().."ScrollBar")

	panel.controls = {}

	panel.refresh = function ()
		if not panel.selectedIndex then
			panel.selectedIndex = 1
		end
		for i=1, #panel.controls do
			if panel.controls[i] then
				panel.controls[i]:Hide() -- 아...이거 메모리 누순데..ㅠ_ㅠ 콜렉터가 잘 처리해주길~_~;;
				panel.controls[i] = nil
			end
		end

		local innerWidth = width
		local innerHeight = 0
		if not panel.scrollFrame.scrollBarHideable then
			innerWidth = math.ceil(panel.scrollFrame:GetWidth()) - 10
		end
		innerHeight = __drawChildControls(panel, panel.scrollFrame.child, optFunc, innerWidth, padding)
		groupStack = {}


		panel.scrollFrame.child:SetWidth(innerWidth)
		panel.scrollFrame.child:SetHeight(innerHeight + padding)

--		local min, max = panel.scrollFrame.scrollBar:GetMinMaxValues()
--		if ( max > 0 and (panel.max ~= max) ) then
--			panel.max = max
--			panel.scrollFrame.scrollBar:SetValue(max)
--		end

		if #panel.controls>0 then
			if panel.selectedIndex > #panel.controls then
				panel.selectedIndex = 1
			end
			if panel.debug then
				for i=1, #panel.controls do
					if panel.controls[i] and panel.controls[i].type and type(panel.controls[i].type)=='string' then
						print(i.." => "..panel.controls[i].type)
					else
						print(i.."번째 뭔지 알수없는 type")
					end
				end
			end
			for i=1, #panel.controls do
				if panel.controls[i] then
					if panel.controls[i].type == 'header' then
						if panel.selectedIndex==i then
							panel.controls[i]:SetChecked(true)
							panel.controls[i]:Click()
						else
							panel.controls[i]:SetChecked(nil)
						end
					else
						if panel.controls[i].refresh and type(panel.controls[i].refresh)=='function' then
							panel.controls[i].refresh()
						end
					end
				end
			end
		end
	end
	panel.refresh()
	panel.type = "scrollFrame"

	return panel
end

function getSubConditionFrame(key, value, updateFunc)
	local tempCondition = {key=key, value=value}
	if not subConditionFrame then
		subConditionFrame = createWindowFrame("bcf_options_subConditionFrame", titleText or "이벤트 조건 추가", 300, 110, true, 5)
		subConditionFrame.controls = {}

		tinsert(addon.frame.subFrames, subConditionFrame) -- 최상위 설정창의 자식창으로 등록
	end

	subConditionFrame.refresh = function ()
		local height = 0
		for i=1, #subConditionFrame.controls do
			subConditionFrame.controls[i]:Hide() -- 아...이거 메모리 누순데..ㅠ_ㅠ 가비지콜렉터가 잘 처리해주길~_~;;
			subConditionFrame.controls[i] = nil
		end

		local innerWidth = subConditionFrame:GetWidth() - 20
		local element

		element = createDropdown(
			subConditionFrame,
			subConditionFrame,
			nil,
			"2차 조건 선택",
			"이벤트를 발생시킬 2차조건을 선택합니다. 2차조건은 모두 만족할때만 이벤트가 발동합니다.",
			innerWidth,
			20,
			{
				get = function ()
					return tempCondition.key or ""
				end,
				set = function (value)
					tempCondition.key = value
				end,
				needRefresh = true,
			},
			nil,
			subConditions
		)
		element:SetPoint("TOPLEFT", subConditionFrame, "TOPLEFT", 10, -30)
		tinsert(subConditionFrame.controls, element)
		height = height + element:GetHeight()

		if tempCondition.key == "SpellReady"
		or tempCondition.key == "SpellUsable"
		or tempCondition.key == "hasBuff"
		or tempCondition.key == "hasNoBuff"
		or tempCondition.key == "hasDebuff"
		or tempCondition.key == "hasNoDebuff"
		then
			element = createEditBox(
				subConditionFrame,
				subConditionFrame,
				nil,
				"2차 조건 값",
				"선택한 조건이 만족하기 위한 값을 입력해주십시오.",
				innerWidth,
				20,
				{
					get = function ()
						return tempCondition.value
					end,
					set = function (value)
						tempCondition.value = value
					end,
				}
			)
			element:SetPoint("TOPLEFT", subConditionFrame.controls[#subConditionFrame.controls], "BOTTOMLEFT", 0, -5)
			tinsert(subConditionFrame.controls, element)
			height = height + element:GetHeight() + 5
		end

		if tempCondition.key == "MinPower" then
			element = createSlider(
				subConditionFrame,
				subConditionFrame,
				nil,
				"최소 파워%",
				"조건을 만족시키기 위해서는 지정한 최소 파워(마나/분노/기력)%보다 많은량을 보유하고있어야합니다.",
				innerWidth,
				20,
				{
					get = function ()
						return tonumber(tempCondition.value) or 0
					end,
					set = function (value)
						tempCondition.value = tonumber(value)
					end,
				},
				nil,
				0,
				100,
				1
			)
			element:SetPoint("TOPLEFT", subConditionFrame.controls[#subConditionFrame.controls], "BOTTOMLEFT", 0, -5)
			tinsert(subConditionFrame.controls, element)
			height = height + element:GetHeight() + 5
		elseif tempCondition.key == "Cooldown" then
			element = createSlider(
				subConditionFrame,
				subConditionFrame,
				nil,
				"재사용대기 시간값",
				"조건이 짧은 시간동안 여러번 일어날수있는 경우 지정한 재사용대기 시간값동안 1번만 발생하게 됩니다.",
				innerWidth,
				20,
				{
					get = function ()
						return tonumber(tempCondition.value) or 0
					end,
					set = function (value)
						tempCondition.value = string.format("%.1f",tonumber(value))
					end,
				},
				nil,
				0,
				10,
				0.1
			)
			element:SetPoint("TOPLEFT", subConditionFrame.controls[#subConditionFrame.controls], "BOTTOMLEFT", 0, -5)
			tinsert(subConditionFrame.controls, element)
			height = height + element:GetHeight() + 5
		end

		if tempCondition.key == "WarriorStance" then
			element = createCheckGroupButton(
				subConditionFrame,
				subConditionFrame,
				nil,
				innerWidth,
				{
					get = function ()
						return tempCondition.value or {}
					end,
					set = function (value)
						tempCondition.value = value
					end,
				},
				nil,
				{
					{ text = "전투 태세", value = 1 },
					{ text = "방어 태세", value = 2 },
					{ text = "광폭 태세", value = 3 },
				},
				3
			)
			element:SetPoint("TOPLEFT", subConditionFrame.controls[#subConditionFrame.controls], "BOTTOMLEFT", 0, -5)
			tinsert(subConditionFrame.controls, element)
			height = height + element:GetHeight() + 5
		elseif tempCondition.key == "DruidForm" then
			element = createCheckGroupButton(
				subConditionFrame,
				subConditionFrame,
				nil,
				innerWidth,
				{
					get = function ()
						return tempCondition.value or {}
					end,
					set = function (value)
						tempCondition.value = value
					end,
				},
				nil,
				function ()
					local _, _, _, _, bf = GetTalentInfo(1, 18) -- 달빛야수 찍었나?
					local _, _, _, _, tf = GetTalentInfo(3, 20) -- 생명의 나무 찍었나?
					--/run _, _, _, _, bf = GetTalentInfo(1, 18);message(bf)
					if bf>0 or tf>0 then
						return {
							{ text = "인간형", value = 0 },
							{ text = "곰", value = 1 },
							{ text = "표범", value = 3 },
							{ text = "치타", value = 4 },
							{ text = "바다표범", value = 2 },
							{ text = "까마귀", value = 6 },
							{ text = "나무/달빛야수", value = 5 },
						}
					else
						return {
							{ text = "인간형", value = 0 },
							{ text = "곰", value = 1 },
							{ text = "표범", value = 3 },
							{ text = "치타", value = 4 },
							{ text = "바다표범", value = 2 },
							{ text = "까마귀", value = 5 },
						}
					end
				end,
				3
			)
			element:SetPoint("TOPLEFT", subConditionFrame.controls[#subConditionFrame.controls], "BOTTOMLEFT", 0, -5)
			tinsert(subConditionFrame.controls, element)
			height = height + element:GetHeight() + 5
		end

		-- 추가 버튼
		if key then
			element = createButton(subConditionFrame, "수정하기")
		else
			element = createButton(subConditionFrame, "추가하기")
		end
		element:SetWidth(70)
		element:SetHeight(24)
		element:SetPoint("TOPLEFT", subConditionFrame.controls[#subConditionFrame.controls], "BOTTOMLEFT", 0, -5)
		element:SetScript("OnClick", function ()
			if tempCondition.key == "TargetIsPlayer"
			or tempCondition.key == "TargetIsEnemy"
			or tempCondition.key == "TargetIsFriend"
			or tempCondition.key == "HonorKillLevel"
			then
				tempCondition.value = true
			elseif tempCondition.key == "SpellReady"
			or tempCondition.key == "SpellUsable"
			or tempCondition.key == "hasBuff"
			or tempCondition.key == "hasNoBuff"
			or tempCondition.key == "hasDebuff"
			or tempCondition.key == "hasNoDebuff"
			then
				if not tempCondition.value or tempCondition.value=="" then
					for i=1, #subConditionFrame.controls do
						if subConditionFrame.controls[i].type == "editbox" then
							local v = subConditionFrame.controls[i].edit:GetText()
							if v and v~="" then
								tempCondition.value = v
							else
								subConditionFrame.controls[i].edit:SetFocus()
								return
							end
						end
					end
				end
			elseif tempCondition.key == "Cooldown" or tempCondition.key == "MinPower" then
				if not tempCondition.value or tempCondition.value=="" then
					for i=1, #subConditionFrame.controls do
						if subConditionFrame.controls[i].type == "slider" then
							subConditionFrame.controls[i].edit:SetFocus()
							return
						end
					end
				end
			end
			if updateFunc and type(updateFunc)=='function' then
				updateFunc(tempCondition)
			end
			subConditionFrame:Hide()
		end)
		tinsert(subConditionFrame.controls, element)
		height = height + element:GetHeight() + 5

		element = createButton(subConditionFrame, "취소하기")
		element:SetWidth(70)
		element:SetHeight(24)
		element:SetPoint("LEFT", subConditionFrame.controls[#subConditionFrame.controls], "RIGHT", 10, 0)
		element:SetScript("OnClick", function ()
			subConditionFrame:Hide()
		end)
		tinsert(subConditionFrame.controls, element)

		subConditionFrame:SetHeight( height + 40 )

	end
	subConditionFrame.refresh()
	subConditionFrame:Show()
end

local function drawPanel()
	local frame = createPanel(addon.frame, "BCFOptionsPanel", 560, 320, 0, 0, 0, .8)
	frame:SetPoint("CENTER", 0, -20)
	addon.frame.panel = frame
end

local function drawTabs()
	local tab
	addon.frame.tabs = {}
	for i=1, #tabs do
		tab = CreateFrame("Button", "bcfTab"..i, addon.frame, "TabButtonTemplate")
		tab:SetText(tabs[i])
		tab:SetID(i)
		if i==1 then
			PanelTemplates_SelectTab(tab)
			PanelTemplates_TabResize(0, tab)
			getglobal(tab:GetName().."HighlightTexture"):SetWidth(tab:GetTextWidth() + 31)
			tab:SetPoint("BOTTOMLEFT", addon.frame.panel, "TOPLEFT", 0, 0)
		else
			PanelTemplates_DeselectTab(tab)
			PanelTemplates_TabResize(0, tab)
			tab:SetPoint("LEFT", "bcfTab"..(i-1), "RIGHT")
		end
		tab:SetScript("OnClick", function (this)
			local t
			for j=1, #tabs do
				if j~=i then
					t = getglobal("bcfTab"..j)
					PanelTemplates_DeselectTab(t)
					PanelTemplates_TabResize(0, t)
					if t.frame then
						t.frame:Hide()
					end
				end
			end
			PanelTemplates_SelectTab(this)
			PanelTemplates_TabResize(0, this)
			if this.frame then
				this.frame:Show()
			end
		end)
		tinsert(addon.frame.tabs, tab)
	end
end

local function drawEnableButton()
	local btn = createCheckBox(addon.frame, "사용", "bcf 애드온 사용")
	btn:SetPoint("BOTTOMRIGHT", addon.frame.panel, "TOPRIGHT", -1*(btn.text:GetWidth()), -3)
	btn:SetChecked(db.enable)
	btn:SetScript("OnClick", function() set(this:GetChecked(), "enable") end)
	btn.refresh = function ()
		btn:SetChecked(db.enable)
	end
	addon.frame.enableButton = btn
end

local function drawTab_Common()
	local frame = CreateFrame("Frame", "BCFOptionsPanelCommon", addon.frame.panel)
	frame:SetWidth(560)
	frame:SetHeight(330)
	frame:SetPoint("CENTER")
	addon.frame.tabs[1].frame = frame
	frame.groups = {}


			local commonPanel = createPanel(frame, nil, 267, 280, .3, .15, 0, .3)
			commonPanel:SetPoint("TOPLEFT", 10, -35)
			commonPanel.text = commonPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			commonPanel.text:SetTextColor(1, 0.82, 0)
			commonPanel.text:SetPoint("BOTTOMLEFT", commonPanel, "TOPLEFT", 2, 3)
			commonPanel.text:SetText("일반 설정")
			commonPanel.controls = {}

			tinsert(commonPanel.controls, drawComplexOption(
				commonPanel,
				nil,
				"showEnterCombat",
				"enterCombat",
				"전투 시작/종료 알림",
				"전투 시작/종료시 알림 메세지 표시",
				"전투 시작/종료 알림 설정",
				"전투 시작/종료시 알림 메세지 관련 설정"
			))
			tinsert(commonPanel.controls, drawComplexOption(
				commonPanel,
				commonPanel.controls[#commonPanel.controls],
				"showCombo",
				"combo",
				"연계점수 표시",
				"도적/표범드루이드의 연계점수 표시",
				"연계점수 설정",
				"연계점수 표시 관련 설정"
			))
			tinsert(commonPanel.controls, drawComplexOption(
				commonPanel,
				commonPanel.controls[#commonPanel.controls],
				"showInterrupt",
				"interrupt",
				"시전방해 메세지 표시",
				"적이 시전하는 주문을 성공적으로 차단하면 메세지를 보여줍니다.",
				"시전방해 메세지 설정",
				"시전방해 메세지 관련 설정"
			))
			tinsert(commonPanel.controls, drawComplexOption(
				commonPanel,
				commonPanel.controls[#commonPanel.controls],
				"showExtraAttack",
				"extraattack",
				"추가타격 표시",
				"추가타격 메세지를 보여줍니다.",
				"추가타격 설정",
				"추가타격 관련 설정"
			))
			tinsert(commonPanel.controls, drawComplexOption(
				commonPanel,
				commonPanel.controls[#commonPanel.controls],
				"showReputation",
				"reputation",
				"평판 수치변화 표시",
				"평판 수치변화 메세지를 보여줍니다.",
				"평판 수치변화 설정",
				"평판 수치변화 관련 설정"
			))
			tinsert(commonPanel.controls, drawComplexOption(
				commonPanel,
				commonPanel.controls[#commonPanel.controls],
				"showEnchant",
				"enchant",
				"아이템 강화 표시",
				"아이템 강화 메세지를 보여줍니다.",
				"아이템 강화 설정",
				"아이템 강화 관련 설정"
			))
			tinsert(commonPanel.controls, drawComplexOption(
				commonPanel,
				commonPanel.controls[#commonPanel.controls],
				"showSchoolColor",
				"schoolColor",
				"피해속성 색상 표시",
				"피해 속성을 색상별로 보여줍니다.",
				"피해속성 색상 설정",
				"피해속성 색상 관련 설정",
				150
			))
			tinsert(commonPanel.controls, drawCheckOpt(commonPanel, commonPanel.controls[#commonPanel.controls], "showSpellName", "스킬명/주문명 표시", "표시 문자열에 %s태그를 입력하면 스킬명/주문명으로 치환해서 표시해줍니다. 이 옵션을 끄거나 표시 문자열에 %s태그가 없으면 스킬명/주문명은 표시되지 않습니다."))
			tinsert(commonPanel.controls, drawCheckOpt(commonPanel, commonPanel.controls[#commonPanel.controls], "showDestName", "대상 이름 표시", "표시 문자열에 %t태그를 입력하면 공격받은 대상이나 힐을 받은 대상의 이름으로 치환해서 표시해줍니다. 이 옵션을 끄거나 표시 문자열에 %t태그가 없으면 대상 이름을 표시하지 않습니다."))
			tinsert(commonPanel.controls, drawCheckOpt(commonPanel, commonPanel.controls[#commonPanel.controls], "autoChangeReputation", "평판 자동 변경", "평판점수를 얻거나 잃으면 해당 평판으로 자동으로 변경합니다."))


	tinsert(frame.groups, commonPanel)


			local commonPanel2 = createPanel(frame, nil, 267, 280, .3, .15, 0, .3)
			commonPanel2:SetPoint("LEFT", commonPanel, "RIGHT", 6, 0)
			commonPanel2.controls = {}

			tinsert(commonPanel2.controls, drawCheckOpt(commonPanel2, nil, "showIcon", "스킬/주문 아이콘 표시", "메세지에 스킬/주문 아이콘을 표시해줍니다."))
			tinsert(commonPanel2.controls, drawCheckOpt(commonPanel2, commonPanel2.controls[#commonPanel2.controls], "showIconBorder", "아이콘 테두리 표시", "메세지에 스킬/주문 아이콘을 표시할때 테두리를 표시해줍니다.", nil, commonPanel2.controls[#commonPanel2.controls]))

			local lvl = {
				get = function ()
					return db.scrollLevel
				end,
				set = function (value)
					db.scrollLevel = value
					addon.bcf:UpdateScrollLevel()
				end
			}
			local level_opts = {
				{
					text = "배경(BACKGROUND)",
					value = "BACKGROUND",
					tooltip = "가장 낮은 계층입니다.",
				},
				{
					text = "낮음(LOW)",
					value = "LOW",
					tooltip = "낮은 계층입니다.",
				},
				{
					text = "중간(MEDIUM)",
					value = "MEDIUM",
					tooltip = "중간 계층입니다.",
				},
				{
					text = "높음(HIGH)",
					value = "HIGH",
					tooltip = "높은 계층입니다.",
				},
				{
					text = "대화상자(DIALOG)",
					value = "DIALOG",
					tooltip = "일반적인 창의 계층입니다. 높음(HIGH)계층보다 더 높습니다.",
				},
				{
					text = "전체화면(FULLSCREEN)",
					value = "FULLSCREEN",
					tooltip = "월드맵과 같은 등급의 계층입니다. 대화상자(DIALOG)계층보다 더 높습니다.",
				},
				{
					text = "툴팁(TOOLTIP)",
					value = "TOOLTIP",
					tooltip = "툴팁과 같은 등급의 계층입니다. 가장 높은 계층으로 항상 보이게 됩니다.",
				},
			}
			local text_level = createString(commonPanel2, nil, "메세지 계층", commonPanel2:GetWidth()-20, 20)
			text_level:SetPoint("TOPLEFT", commonPanel2.controls[#commonPanel2.controls], "BOTTOMLEFT", 0, -5)
			text_level.text:SetFont("Fonts\\2002B.ttf", 14)
			text_level.text:SetTextColor(1, 1, 1)
			--text_level:SetText(text)

			tinsert(commonPanel2.controls, text_level)

			local rdo_level = createRadioButton(commonPanel2, commonPanel2, nil, commonPanel2:GetWidth()-20, lvl, nil, level_opts)
			rdo_level:SetPoint("TOPLEFT", commonPanel2.controls[#commonPanel2.controls], "BOTTOMLEFT", 0, -5)
			tinsert(commonPanel2.controls, rdo_level)

	tinsert(frame.groups, commonPanel2)
	frame:Show()
end

local function drawTab_Damage()
	local frame = CreateFrame("Frame", "BCFOptionsPanelDamage", addon.frame.panel)
	frame:SetWidth(560)
	frame:SetHeight(330)
	frame:SetPoint("CENTER")
	addon.frame.tabs[2].frame = frame
	frame.groups = {}

			local cfgPanel = createPanel(frame, nil, 297, 280, .3, .3, .3, .3)
			cfgPanel.text = cfgPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			cfgPanel.text:SetTextColor(1, 0.82, 0)
			cfgPanel.text:SetPoint("BOTTOMLEFT", cfgPanel, "TOPLEFT", 2, 3)
			cfgPanel.text:SetText("상세 설정")
			cfgPanel.controls = {}

				local text = cfgPanel:CreateFontString(nil, "OVERLAY","ChatFontNormal")
				text:SetTextColor(1, 1, 1)
				text:SetPoint("CENTER")
				text:SetText("bcf_options")
				tinsert(cfgPanel.controls, text)

			local damagePanel = createPanel(frame, nil, 237, 125, .3, 0, 0, .3)
			damagePanel:SetPoint("TOPLEFT", 10, -35)
			damagePanel.text = damagePanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			damagePanel.text:SetTextColor(1, 0.82, 0)
			damagePanel.text:SetPoint("BOTTOMLEFT", damagePanel, "TOPLEFT", 2, 3)
			damagePanel.text:SetText("받은 피해 설정")
			damagePanel.controls = {}

			-- 내가 적에게 받은 피해 표시
			tinsert(damagePanel.controls, drawCheckAndButtonOpt(
				damagePanel,
				nil,
				"showIncomingHit",
				"incomingHit",
				cfgPanel,
				"받은 피해",
				"플레이어가 적에게 받은 피해량을 표시합니다.",
				"플레이어가 적에게 받은 피해 관련 설정",
				"받은 피해"
			))

			-- 소환수가 적에게 받은 피해 표시
			tinsert(damagePanel.controls, drawCheckAndButtonOpt(
				damagePanel,
				damagePanel.controls[#damagePanel.controls],
				"showIncomingPetHit",
				"incomingPetHit",
				cfgPanel,
				"펫이 받은 피해",
				"소환수/펫이 적에게 받은 피해량을 표시합니다.",
				"소환수/펫이 적에게 받은 피해 관련 설정",
				"소환수가 받은 피해"
			))

			-- 주시대상이 적에게 받은 피해 표시
			tinsert(damagePanel.controls, drawCheckAndButtonOpt(
				damagePanel,
				damagePanel.controls[#damagePanel.controls],
				"showIncomingFocusHit",
				"incomingFocusHit",
				cfgPanel,
				"주시대상이 받은 피해",
				"주시대상이 적에게 받은 피해량을 표시합니다.",
				"주시대상이 적에게 받은 피해 관련 설정",
				"주시대상이 받은 피해"
			))

	tinsert(frame.groups, damagePanel)





			local hitPanel = createPanel(frame, nil, 237, 125, 0, 0, .3, .3)
			hitPanel:SetPoint("TOPLEFT", damagePanel, "BOTTOMLEFT", 0, -28)
			hitPanel.text = hitPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			hitPanel.text:SetTextColor(1, 0.82, 0)
			hitPanel.text:SetPoint("BOTTOMLEFT", hitPanel, "TOPLEFT", 2, 3)
			hitPanel.text:SetText("입힌 피해 설정")
			hitPanel.controls = {}

			-- 내가 적에게 입힌 피해 표시
			tinsert(hitPanel.controls, drawCheckAndButtonOpt(
				hitPanel,
				nil,
				"showOutgoingHit",
				"outgoingHit",
				cfgPanel,
				"입힌 피해",
				"플레이어가 적에게 입힌 피해량을 표시합니다.",
				"플레이어가 적에게 입힌 피해 관련 설정",
				"입힌 피해"
			))

			-- 소환수가 적에게 입힌 피해
			tinsert(hitPanel.controls, drawCheckAndButtonOpt(
				hitPanel,
				hitPanel.controls[#hitPanel.controls],
				"showOutgoingPetHit",
				"outgoingPetHit",
				cfgPanel,
				"펫이 입힌 피해",
				"소환수/펫이 적에게 입힌 피해량을 표시합니다.",
				"소환수/펫이 적에게 입힌 피해 관련 설정",
				"펫이 입힌 피해"
			))

			-- 주시대상이 적에게 입힌 피해 표시
			tinsert(hitPanel.controls, drawCheckAndButtonOpt(
				hitPanel,
				hitPanel.controls[#hitPanel.controls],
				"showOutgoingFocusHit",
				"outgoingFocusHit",
				cfgPanel,
				"주시대상이 입힌 피해",
				"주시대상이 적에게 입힌 피해량을 표시합니다.",
				"주시대상이 적에게 입힌 피해 관련 설정",
				"주시대상이 입힌 피해"
			))

	tinsert(frame.groups, hitPanel)


			--cfgPanel = createPanel(frame, nil, 277, 280, .3, .3, .3, .3)
			cfgPanel:SetPoint("TOPLEFT", damagePanel, "TOPRIGHT", 6, 0)
			config = drawScrollFrame(cfgPanel, nil, getConfigOptions, cfgPanel:GetWidth()-20, 226, false, 5)
			tinsert(cfgPanel.controls, config)

	tinsert(frame.groups, cfgPanel)

	frame:Hide()
end

local function drawTab_Heal()
	local frame = CreateFrame("Frame", "BCFOptionsPanelHeal", addon.frame.panel)
	frame:SetWidth(560)
	frame:SetHeight(330)
	frame:SetPoint("CENTER")
	addon.frame.tabs[3].frame = frame
	frame.groups = {}

			local cfgPanel = createPanel(frame, nil, 297, 280, .3, .3, .3, .3)
			cfgPanel.text = cfgPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			cfgPanel.text:SetTextColor(1, 0.82, 0)
			cfgPanel.text:SetPoint("BOTTOMLEFT", cfgPanel, "TOPLEFT", 2, 3)
			cfgPanel.text:SetText("상세 설정")
			cfgPanel.controls = {}

				local text = cfgPanel:CreateFontString(nil, "OVERLAY","ChatFontNormal")
				text:SetTextColor(1, 1, 1)
				text:SetPoint("CENTER")
				text:SetText("bcf_options")
				tinsert(cfgPanel.controls, text)


			local healPanel = createPanel(frame, nil, 237, 280, 0, .3, 0, .3)
			healPanel:SetPoint("TOPLEFT", 10, -35)
			healPanel.text = healPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			healPanel.text:SetTextColor(1, 0.82, 0)
			healPanel.text:SetPoint("BOTTOMLEFT", healPanel, "TOPLEFT", 2, 3)
			healPanel.text:SetText("치유 설정")
			healPanel.controls = {}

			tinsert(healPanel.controls, drawCheckAndButtonOpt(
				healPanel,
				nil,
				"showIncomingHeal",
				"incomingHeal",
				cfgPanel,
				"받는 치유",
				"플레이어에게 들어오는 치유량을 표시해줍니다.",
				"받는 치유 표시 관련 설정",
				"받은 치유"
			))
			tinsert(healPanel.controls, drawCheckAndButtonOpt(
				healPanel,
				healPanel.controls[#healPanel.controls],
				"showOutgoingHeal",
				"outgoingHeal",
				cfgPanel,
				"아군 치유",
				"플레이어가 치유주문으로 아군을 치유해주는 메세지를 표시해줍니다.",
				"아군 치유 표시 관련 설정",
				"아군 치유"
			))
			tinsert(healPanel.controls, drawCheckOpt(healPanel, healPanel.controls[#healPanel.controls], "showOverHeal", "오버힐 표시", "오버힐량을 표시합니다."))
			tinsert(healPanel.controls, drawComplexOption(
				healPanel,
				healPanel.controls[#healPanel.controls],
				"showEnergize",
				"energize",
				"마나/분노/기력 회복",
				"마나/분노/기력 회복 메세지를 표시합니다.",
				"마나/분노/기력 회복 표시 설정",
				"마나/분노/기력 회복 표시 관련 설정"
			))
			tinsert(healPanel.controls, drawComplexOption(
				healPanel,
				healPanel.controls[#healPanel.controls],
				"showPowerColor",
				"powerColor",
				"마나/분노/기력에 색상",
				"마나/분노/기력 관련 메세지를 표시할때 색상을 표시할지 선택합니다.",
				"파워 색상 설정",
				"마나/분노/기력 색상 관련 설정",
				180
			))
	tinsert(frame.groups, healPanel)

			cfgPanel:SetPoint("TOPLEFT", healPanel, "TOPRIGHT", 6, 0)
			config = drawScrollFrame(cfgPanel, nil, getConfigOptions, cfgPanel:GetWidth()-20, 226, false, 5)
			tinsert(cfgPanel.controls, config)


	tinsert(frame.groups, cfgPanel)
	frame:Hide()
end

local function drawTab_Aura()
	local frame = CreateFrame("Frame", "BCFOptionsPanelAura", addon.frame.panel)
	frame:SetWidth(560)
	frame:SetHeight(330)
	frame:SetPoint("CENTER")
	addon.frame.tabs[4].frame = frame
	frame.groups = {}

			local auraPanel = createPanel(frame, nil, 267, 280, .3, .3, 0, .3)
			auraPanel:SetPoint("TOPLEFT", 10, -35)
			auraPanel.text = auraPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			auraPanel.text:SetTextColor(1, 0.82, 0)
			auraPanel.text:SetPoint("BOTTOMLEFT", auraPanel, "TOPLEFT", 2, 3)
			auraPanel.text:SetText("버프/디버프 설정")
			auraPanel.controls = {}

			tinsert(auraPanel.controls, drawComplexOption(
				auraPanel,
				nil,
				"showBuff",
				"buff",
				"버프 표시",
				"플레이어가 버프를 얻을때 메세지를 표시해줍니다.",
				"버프 표시 설정",
				"버프 표시 관련 설정"))
			tinsert(auraPanel.controls, drawComplexOption(
				auraPanel,
				auraPanel.controls[#auraPanel.controls],
				"showBuffFade",
				"bufffade",
				"버프 사라짐 표시",
				"플레이어의 버프가 사라질때 메세지를 표시해줍니다.",
				"버프 사라짐 설정",
				"버프 사라짐 표시 관련 설정"))
			tinsert(auraPanel.controls, drawComplexOption(
				auraPanel,
				auraPanel.controls[#auraPanel.controls],
				"showDebuff",
				"debuff",
				"디버프 표시",
				"플레이어가 디버프를 얻을때 메세지를 표시해줍니다.",
				"디버프 표시 설정",
				"디버프 표시 관련 설정"))
			tinsert(auraPanel.controls, drawComplexOption(
				auraPanel,
				auraPanel.controls[#auraPanel.controls],
				"showDebuffFade",
				"debufffade",
				"디버프 사라짐 표시",
				"플레이어의 디버프가 사라질때 메세지를 표시해줍니다.",
				"디버프 사라짐 설정",
				"디버프 사라짐 표시 관련 설정"))
			--tinsert(auraPanel.controls, drawCheckOpt(auraPanel, auraPanel.controls[#auraPanel.controls], "showOverHeal", "오버힐 표시", "오버힐량을 표시합니다."))

	tinsert(frame.groups, auraPanel)


			local exceptAuraPanel = createPanel(frame, nil, 267, 280, .3, .3, .3, .3)
			exceptAuraPanel:SetPoint("LEFT", auraPanel, "RIGHT", 6, 0)
			exceptAuraPanel.text = exceptAuraPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			exceptAuraPanel.text:SetTextColor(1, 0.82, 0)
			exceptAuraPanel.text:SetPoint("BOTTOMLEFT", exceptAuraPanel, "TOPLEFT", 2, 3)
			exceptAuraPanel.text:SetText("표시 제한 효과")
			exceptAuraPanel.controls = {}

			local text = exceptAuraPanel:CreateFontString(nil, "OVERLAY","GameFontNormalSmall")
			text:SetPoint("CENTER")
			text:SetText("표시 제한 효과는 아직 구현되지 않았습니다")
			tinsert(exceptAuraPanel.controls, text)

	tinsert(frame.groups, exceptAuraPanel)

	frame:Hide()
end

local function drawTab_Scroll()
	local frame = CreateFrame("Frame", "BCFOptionsPanelScroll", addon.frame.panel)
	frame:SetWidth(560)
	frame:SetHeight(330)
	frame:SetPoint("CENTER")
	addon.frame.tabs[5].frame = frame
	frame.groups = {}

			local scrollConfigPanel
			local scrollPanel = createPanel(frame, nil, 267, 280, 0, .15, .3, .3)
			scrollPanel:SetPoint("TOPLEFT", 10, -35)
			scrollPanel.text = scrollPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			scrollPanel.text:SetTextColor(1, 0.82, 0)
			scrollPanel.text:SetPoint("BOTTOMLEFT", scrollPanel, "TOPLEFT", 2, 3)
			scrollPanel.text:SetText("스크롤영역 목록")
			scrollPanel.controls = {}

			local btn1 = controlButton(scrollPanel, nil, "영역 표시", "스크롤 영역을 화면에 표시합니다.", function ()
				addon.bcf:ToggleScrollAreas()
			end, 80, 21)
			btn1:SetPoint("TOPLEFT", scrollPanel, "TOPLEFT", 10, -17)
			tinsert(scrollPanel.controls, btn1)

			local list
			local function deleteScrollArea(index)
				local sas = addon.bcf.bScroll:GetScrollAreas()
				addon:ConfirmFrame("'"..sas[index].name.."' 스크롤 영역을 삭제하시겠습니까?", "삭제 확인", function ()
					updateScrollAreaDeleteTo(sas[index].name)
					tremove(db.scrollAreas, list.selectedIndex)
					if list.selectedIndex > 1 then
						list.selectedIndex = list.selectedIndex - 1
					end
					list.refresh()
				end)
			end
			local function optclick(index)
				if scrollConfigPanel and #scrollConfigPanel.controls > 0 then
					for i=1, #scrollConfigPanel.controls do
						local c = scrollConfigPanel.controls[i]
						if c.refresh and type(c.refresh)=='function' then
							c.refresh()
						end
					end
				end
			end
			local function getScrollAreasOpt()
				local opt = {}
				local sas = addon.bcf.bScroll:GetScrollAreas()
				if #sas > 0 then
					for i=1, #sas do
						if addon.bcf.bScroll:IsDefaultScrollArea(sas[i].name) then
							tinsert(opt,{
								type = 'header',
								text = sas[i].name,
								click = optclick,
							})
						else
							tinsert(opt,{
								type = 'header',
								text = sas[i].name,
								click = optclick,
								deleteClick = deleteScrollArea,
							})
						end
					end
				end
				return opt
			end
			list = drawScrollFrame(scrollPanel, btn1, getScrollAreasOpt, scrollPanel:GetWidth()-20, 226)
			tinsert(scrollPanel.controls, list)

			local function makeNewScrollArea()
				local maxNum = 0
				local newName
				local sas = addon.bcf.bScroll:GetScrollAreas()
				for i=1, #sas do
					local name = sas[i].name
					local _, _, num = name:find("ScrollArea #(%d+)")
					if num then
						num = tonumber(num)
						if maxNum < num then
							maxNum = num
						end
					end
				end
				newName = "ScrollArea #"..(maxNum+1)
				local obj = {
					name = newName,
					width = 200,
					height = 200,
					x = 0,
					y = 0,
					scrollTime = 3,
					addonname = "bcf",
				}
				local hdr = createHeaderButton(list, list.scrollFrame.child, list.controls, obj.name, list:GetWidth(), 20, optclick, function () end)
				if #list.controls > 0 then
					hdr:SetPoint("TOPLEFT", list.controls[#list.controls], "BOTTOMLEFT")
				else
					hdr:SetPoint("TOPLEFT", 0, 0 )
				end
				tinsert(list.controls, hdr)
				tinsert(db.scrollAreas, {
					name = obj.name,
					width = obj.width,
					height = obj.height,
					x = obj.x,
					y = obj.y,
					scrollTime = obj.scrollTime,
				})
				addon.bcf.bScroll:UpdateScrollArea(
					obj.name,
					obj.width,
					obj.height,
					obj.x,
					obj.y,
					obj.scrollTime,
					function (x, y, width, height)
						if x then
							db.scrollAreas[#db.scrollAreas].x = x
						end
						if y then
							db.scrollAreas[#db.scrollAreas].y = y
						end
						if width then
							db.scrollAreas[#db.scrollAreas].width = width
						end
						if height then
							db.scrollAreas[#db.scrollAreas].height = height
						end
					end,
					obj.addonname
				)
				list.refresh()
			end
			local btn2 = controlButton(scrollPanel, nil, "만들기", "새로운 스크롤 영역을 생성합니다.", makeNewScrollArea, 80, 21)
			btn2:SetPoint("LEFT", btn1, "RIGHT", 5, 0)
			tinsert(scrollPanel.controls, btn2)

			local function resetSA()
				addon.bcf.bScroll:ResetScrollAreas()
				addon.bcf:SyncScrollAreas(true)
				list.refresh()
			end
			local btn3 = controlButton(scrollPanel, nil, "영역초기화", "스크롤 영역을 초기화합니다.", resetSA, 80, 21)
			btn3:SetPoint("LEFT", btn2, "RIGHT", 5, 0)
			tinsert(scrollPanel.controls, btn3)


	tinsert(frame.groups, scrollPanel)



			scrollConfigPanel = createPanel(frame, nil, 267, 280, .3, 0, .3, .3)
			scrollConfigPanel:SetPoint("LEFT", scrollPanel, "RIGHT", 6, 0)
			scrollConfigPanel.text = scrollConfigPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			scrollConfigPanel.text:SetTextColor(1, 0.82, 0)
			scrollConfigPanel.text:SetPoint("BOTTOMLEFT", scrollConfigPanel, "TOPLEFT", 2, 3)
			scrollConfigPanel.text:SetText("스크롤영역 설정")
			scrollConfigPanel.controls = {}


			local slider_st, slider_sw, slider_sh, slider_sx, slider_sy

			local sn = {
				get = function ()
					local sa = addon.bcf.bScroll:GetScrollArea(list.selectedIndex)
					return sa.name
				end,
				set = function (value)
					local sa = addon.bcf.bScroll:GetScrollArea(list.selectedIndex)
					if not addon.bcf.bScroll:IsDefaultScrollArea(sa.name) then
						local prevValue = sa.name
						if updateScrollAreaNameDB(prevValue, value) then
							list.controls[list.selectedIndex].text:SetText(value)
							addon.bcf:SyncScrollAreas(true)
						end
					else
						list.controls[list.selectedIndex].text:SetText(sa.name)
					end
				end
			}
			local edit_name = createEditBox(nil, scrollConfigPanel, nil, "스크롤 영역 이름", "스크롤 영역의 이름을 설정합니다.", scrollConfigPanel:GetWidth()-20, 20, sn)
			edit_name:SetPoint("TOPLEFT", scrollConfigPanel, "TOPLEFT", 10, -17)
			tinsert(scrollConfigPanel.controls, edit_name)

			local st = {
				get = function ()
					local sa = addon.bcf.bScroll:GetScrollArea(list.selectedIndex)
					return sa.scrollTime
				end,
				set = function (value)
					addon.bcf.bScroll:UpdateScrollArea(list.selectedIndex, nil, nil, nil, nil, tonumber(value))
					addon.bcf:SyncScrollAreas(true)
				end
			}
			slider_st = createSlider(nil, scrollConfigPanel, nil, "스크롤 속도", "스크롤 속도를 지정합니다.|n|cffff7f00단위 초(sec)|n1초~10초|r", scrollConfigPanel:GetWidth()-20, 20, st, nil, 1, 10, .25)
			slider_st:SetPoint("TOPLEFT", edit_name, "BOTTOMLEFT", 0, -5)
			tinsert(scrollConfigPanel.controls, slider_st)

			local sw = {
				get = function ()
					local sa = addon.bcf.bScroll:GetScrollArea(list.selectedIndex)
					return sa.width
				end,
				set = function (value)
					addon.bcf.bScroll:UpdateScrollArea(list.selectedIndex, tonumber(value))
					addon.bcf:SyncScrollAreas(true)
				end
			}
			slider_sw = createSlider(nil, scrollConfigPanel, nil, "넓이", "스크롤 영역의 폭을 지정합니다.", scrollConfigPanel:GetWidth()-20, 20, sw, nil, 10, 1000, 10)
			slider_sw:SetPoint("TOPLEFT", slider_st, "BOTTOMLEFT", 0, -5)
			tinsert(scrollConfigPanel.controls, slider_sw)

			local sh = {
				get = function ()
					local sa = addon.bcf.bScroll:GetScrollArea(list.selectedIndex)
					return sa.height
				end,
				set = function (value)
					addon.bcf.bScroll:UpdateScrollArea(list.selectedIndex, nil, tonumber(value))
					addon.bcf:SyncScrollAreas(true)
				end
			}
			slider_sh = createSlider(nil, scrollConfigPanel, nil, "높이", "스크롤 영역의 높이를 지정합니다.", scrollConfigPanel:GetWidth()-20, 20, sh, nil, 10, 1000, 10)
			slider_sh:SetPoint("TOPLEFT", slider_sw, "BOTTOMLEFT", 0, -5)
			tinsert(scrollConfigPanel.controls, slider_sh)

			local sx = {
				get = function ()
					local sa = addon.bcf.bScroll:GetScrollArea(list.selectedIndex)
					return sa.x
				end,
				set = function (value)
					addon.bcf.bScroll:UpdateScrollArea(list.selectedIndex, nil, nil, tonumber(value))
					addon.bcf:SyncScrollAreas(true)
				end
			}
			local mw = math.ceil(UIParent:GetWidth()/2)
			local slider_sx = createSlider(nil, scrollConfigPanel, nil, "X좌표", "스크롤 영역의 X좌표를 지정합니다.", scrollConfigPanel:GetWidth()-20, 20, sx, nil, mw*-1, mw, 1)
			slider_sx:SetPoint("TOPLEFT", slider_sh, "BOTTOMLEFT", 0, -5)
			tinsert(scrollConfigPanel.controls, slider_sx)

			local sy = {
				get = function ()
					local sa = addon.bcf.bScroll:GetScrollArea(list.selectedIndex)
					return sa.y
				end,
				set = function (value)
					addon.bcf.bScroll:UpdateScrollArea(list.selectedIndex, nil, nil, nil, tonumber(value))
					addon.bcf:SyncScrollAreas(true)
				end
			}
			local mh = math.ceil(UIParent:GetHeight()/2)
			slider_sy = createSlider(nil, scrollConfigPanel, nil, "Y좌표", "스크롤 영역의 Y좌표를 지정합니다.", scrollConfigPanel:GetWidth()-20, 20, sy, nil, mh*-1, mh, 1)
			slider_sy:SetPoint("TOPLEFT", slider_sx, "BOTTOMLEFT", 0, -5)
			tinsert(scrollConfigPanel.controls, slider_sy)


	tinsert(frame.groups, scrollConfigPanel)

	frame:Hide()
end

local function drawTab_Event()
	local frame = CreateFrame("Frame", "BCFOptionsPanelEvent", addon.frame.panel)
	frame:SetWidth(560)
	frame:SetHeight(330)
	frame:SetPoint("CENTER")
	addon.frame.tabs[6].frame = frame
	frame.groups = {}

			local eventConfigPanel
			local eventListPanel = createPanel(frame, nil, 217, 280, .3, .3, .3, .3)
			eventListPanel:SetPoint("TOPLEFT", 10, -35)
			eventListPanel.text = eventListPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			eventListPanel.text:SetTextColor(1, 0.82, 0)
			eventListPanel.text:SetPoint("BOTTOMLEFT", eventListPanel, "TOPLEFT", 2, 3)
			eventListPanel.text:SetText("이벤트")
			eventListPanel.controls = {}

			-- 스크롤 영역 만들기
			local list
			local function deleteEvent(index)
				addon:ConfirmFrame("'"..db.customEvents[index].msg.."' 사용자이벤트를 삭제하시겠습니까?", "삭제 확인", function ()
					tremove(db.customEvents, index)
					addon.bcf:UpdateCustomEventDB()
					if list.selectedIndex == index and index > 1 then
						list.selectedIndex = list.selectedIndex - 1
					end
					list.refresh()
				end)
			end
			local function optclick(index)
				if eventConfigPanel and #eventConfigPanel.controls > 0 then
					for i=1, #eventConfigPanel.controls do
						local c = eventConfigPanel.controls[i]
						if c.refresh and type(c.refresh)=='function' then
							c.refresh()
						end
					end
				end
			end

			local function getCustomEvents()
				local opt = {}
				if #db.customEvents > 0 then
					for i=1, #db.customEvents do
						tinsert(opt,{
							type = 'header',
							text = db.customEvents[i].msg,
							click = optclick,
							deleteClick = deleteEvent
						})
					end
				end
				return opt
			end
			list = drawScrollFrame(eventListPanel, nil, getCustomEvents, eventListPanel:GetWidth()-20, 226)
			tinsert(eventListPanel.controls, list)

			local function makeNewEvent()
				local maxNum = 0
				local newName
				for i=1, #db.customEvents do
					local name = db.customEvents[i].msg
					local _, _, num = name:find("Event #(%d+)")
					if num then
						num = tonumber(num)
						if maxNum < num then
							maxNum = num
						end
					end
				end
				newName = "Event #"..(maxNum+1)
				local obj = {
					msg = newName,
					size = 20,
					font = "Fonts\\2002b.TTF",
					outline = 'THICKOUTLINE',
					scrollArea = "notifyUp",
					scrollType = "up",
					align = "center",
					--condition = "outgoingCrit", -- 일단 이것을 디폴트로...
					color = "ffffff",
				}
				local hdr = createHeaderButton(list, list.scrollFrame.child, list.controls, obj.name, list:GetWidth(), 20, optclick, deleteEvent)
				if #list.controls > 0 then
					hdr:SetPoint("TOPLEFT", list.controls[#list.controls], "BOTTOMLEFT")
				else
					hdr:SetPoint("TOPLEFT", 0, 0 )
				end
				tinsert(list.controls, hdr)
				tinsert(db.customEvents, {
					msg = obj.msg,
					size = obj.size,
					font = obj.font,
					outline = obj.outline,
					scrollArea = obj.scrollArea,
					scrollType = obj.scrollType,
					align = obj.align,
					condition = obj.condition,
					color = obj.color,
				})
				addon.bcf:UpdateCustomEventDB()
				list.refresh()
			end
			local btnAddNew = controlButton(eventListPanel, nil, "추가", "사용자 정의 이벤트를 추가합니다.", makeNewEvent, 80, 21)
			btnAddNew:SetPoint("TOPLEFT", list, "BOTTOMLEFT", 0, -5)
			tinsert(eventListPanel.controls, btnAddNew)

			local chkUse = createCheckBox2(eventListPanel, eventListPanel, nil, "이벤트 사용", "사용자정의 이벤트 기능을 사용할 것인지 선택합니다.", 100, 20, {
				get = function ()
					return db.useCustomEvent or true
				end,
				set = function (value)
					db.useCustomEvent = value
				end,
			})
			chkUse:SetPoint("LEFT", btnAddNew, "RIGHT", 20, 0)
			tinsert(eventListPanel.controls, chkUse)

	tinsert(frame.groups, eventListPanel)


			eventConfigPanel = createPanel(frame, nil, 317, 280, .3, .3, .3, .3)
			eventConfigPanel:SetPoint("LEFT", eventListPanel, "RIGHT", 6, 0)
			eventConfigPanel.text = eventConfigPanel:CreateFontString(nil, "OVERLAY","QuestTitleFont")
			eventConfigPanel.text:SetTextColor(1, 0.82, 0)
			eventConfigPanel.text:SetPoint("BOTTOMLEFT", eventConfigPanel, "TOPLEFT", 2, 3)
			eventConfigPanel.text:SetText("설정")
			eventConfigPanel.controls = {}

			local config
			local function getConfigOptions()
				local opt = {
					{
						type = "text",
						text = "발동 조건 설정",
						size = 20,
						font = "Fonts\\2002b.TTF",
					},
					{
						type = "editbox",
						text = "메세지",
						tooltip = function ()
							if db.customEvents[list.selectedIndex].condition=="outgoingCrit"
							or db.customEvents[list.selectedIndex].condition=="incomingCrit"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetCrit"
							or db.customEvents[list.selectedIndex].condition=="incomingPetCrit"
							then
								return "화면에 표시할 메세지를 입력해주세요.|n사용가능 태그|n|cffffffff%v|r = 스킬명|n|cffffffff%1|r = 공격자이름|n|cffffffff%2|r = 피공격자이름|n|cffffffff%3|r = 피해량"
							elseif db.customEvents[list.selectedIndex].condition=="outgoingBlock"
							or db.customEvents[list.selectedIndex].condition=="incomingBlock"
							or db.customEvents[list.selectedIndex].condition=="outgoingDodge"
							or db.customEvents[list.selectedIndex].condition=="incomingDodge"
							or db.customEvents[list.selectedIndex].condition=="outgoingParry"
							or db.customEvents[list.selectedIndex].condition=="incomingParry"
							or db.customEvents[list.selectedIndex].condition=="outgoingResist"
							or db.customEvents[list.selectedIndex].condition=="incomingResist"
							or db.customEvents[list.selectedIndex].condition=="outgoingImmune"
							or db.customEvents[list.selectedIndex].condition=="incomingImmune"

							or db.customEvents[list.selectedIndex].condition=="outgoingPetBlock"
							or db.customEvents[list.selectedIndex].condition=="incomingPetBlock"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetDodge"
							or db.customEvents[list.selectedIndex].condition=="incomingPetDodge"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetParry"
							or db.customEvents[list.selectedIndex].condition=="incomingPetParry"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetResist"
							or db.customEvents[list.selectedIndex].condition=="incomingPetResist"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetImmune"
							or db.customEvents[list.selectedIndex].condition=="incomingPetImmune"

							or db.customEvents[list.selectedIndex].condition=="outgoingCastStart"
							or db.customEvents[list.selectedIndex].condition=="outgoingCastSuccess"
							or db.customEvents[list.selectedIndex].condition=="outgoingCastFail"
							or db.customEvents[list.selectedIndex].condition=="incomingCastStart"
							or db.customEvents[list.selectedIndex].condition=="incomingCastSuccess"
							or db.customEvents[list.selectedIndex].condition=="incomingCastFail"

							then
								return "화면에 표시할 메세지를 입력해주세요.|n사용가능 태그|n|cffffffff%v|r = 스킬명|n|cffffffff%1|r = 공격자이름|n|cffffffff%2|r = 피공격자이름"
							elseif db.customEvents[list.selectedIndex].condition=="selfBuff"
							or db.customEvents[list.selectedIndex].condition=="petBuff"
							or db.customEvents[list.selectedIndex].condition=="targetBuff"
							or db.customEvents[list.selectedIndex].condition=="selfDebuff"
							or db.customEvents[list.selectedIndex].condition=="petDebuff"
							or db.customEvents[list.selectedIndex].condition=="targetDebuff"
							or db.customEvents[list.selectedIndex].condition=="selfBuffFade"
							or db.customEvents[list.selectedIndex].condition=="selfDebuffFade"
							or db.customEvents[list.selectedIndex].condition=="petBuffFade"
							or db.customEvents[list.selectedIndex].condition=="petDebuffFade"
							or db.customEvents[list.selectedIndex].condition=="targetBuffFade"
							or db.customEvents[list.selectedIndex].condition=="targetDebuffFade"
							then
								return "화면에 표시할 메세지를 입력해주세요.|n사용가능 태그|n%v = 스킬명"
							elseif db.customEvents[list.selectedIndex].condition=="selfHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="selfHealthGain"
							or db.customEvents[list.selectedIndex].condition=="petHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="petHealthGain"
							or db.customEvents[list.selectedIndex].condition=="targetHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="targetHealthGain"
							or db.customEvents[list.selectedIndex].condition=="selfManaLoss"
							or db.customEvents[list.selectedIndex].condition=="selfManaGain"
							then
								return "화면에 표시할 메세지를 입력해주세요.|n사용가능 태그|n|cffffffff%v|r = 스킬명|n|cffffffff%1|r = 이름|n|cffffffff%2|r = 남은량"
							elseif db.customEvents[list.selectedIndex].condition=="killblow" then
								return "화면에 표시할 메세지를 입력해주세요.|n사용가능 태그|n|cffffffff%v|r = 죽인 대상 이름"
							else
								return "화면에 표시할 메세지를 입력해주세요."
							end
						end,
						value = {
							get = function ()
								return db.customEvents[list.selectedIndex].msg
							end,
							set = function (value)
								local prevValue = db.customEvents[list.selectedIndex].msg
								db.customEvents[list.selectedIndex].msg = value
								list.controls[list.selectedIndex].text:SetText(value)
								addon.bcf:UpdateCustomEventDB(true)
							end,
						},
					},
					{
						type = "dropdown",
						text = "1차 조건 선택",
						tooltip = "이벤트를 발생시킬 기본 조건을 선택해주세요.",
						value = {
							get = function ()
								return db.customEvents[list.selectedIndex].condition
							end,
							set = function (value)
								db.customEvents[list.selectedIndex].condition = value
								addon.bcf:UpdateCustomEventDB(true)
							end,
							needRefresh = true,
						},
						options = conditions,
					},
					{
						show = function ()
							if not 
							(db.customEvents[list.selectedIndex].condition=="selfHealthGain"
							or db.customEvents[list.selectedIndex].condition=="selfHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="petHealthGain"
							or db.customEvents[list.selectedIndex].condition=="petHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="targetHealthGain"
							or db.customEvents[list.selectedIndex].condition=="targetHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="selfManaGain"
							or db.customEvents[list.selectedIndex].condition=="selfManaLoss"
							or db.customEvents[list.selectedIndex].condition=="death")
							then
								return true
							end
						end,
						type = "editbox",
						allowBlank = function () -- boolean or function
							if db.customEvents[list.selectedIndex].condition=="outgoingCrit"
							or db.customEvents[list.selectedIndex].condition=="incomingCrit"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetCrit"
							or db.customEvents[list.selectedIndex].condition=="incomingPetCrit"
							
							or db.customEvents[list.selectedIndex].condition=="outgoingBlock"
							or db.customEvents[list.selectedIndex].condition=="incomingBlock"
							or db.customEvents[list.selectedIndex].condition=="outgoingDodge"
							or db.customEvents[list.selectedIndex].condition=="incomingDodge"
							or db.customEvents[list.selectedIndex].condition=="outgoingParry"
							or db.customEvents[list.selectedIndex].condition=="incomingParry"
							or db.customEvents[list.selectedIndex].condition=="outgoingResist"
							or db.customEvents[list.selectedIndex].condition=="incomingResist"
							or db.customEvents[list.selectedIndex].condition=="outgoingImmune"
							or db.customEvents[list.selectedIndex].condition=="incomingImmune"
							
							or db.customEvents[list.selectedIndex].condition=="outgoingPetBlock"
							or db.customEvents[list.selectedIndex].condition=="incomingPetBlock"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetDodge"
							or db.customEvents[list.selectedIndex].condition=="incomingPetDodge"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetParry"
							or db.customEvents[list.selectedIndex].condition=="incomingPetParry"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetResist"
							or db.customEvents[list.selectedIndex].condition=="incomingPetResist"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetImmune"
							or db.customEvents[list.selectedIndex].condition=="incomingPetImmune"

							then
								return true
							end
						end,
						text = "1차 조건 값(주문/기술)",
						tooltip = function ()
							if db.customEvents[list.selectedIndex].condition=="outgoingCrit"
							or db.customEvents[list.selectedIndex].condition=="incomingCrit"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetCrit"
							or db.customEvents[list.selectedIndex].condition=="incomingPetCrit"
							then
								return "주문/기술명을 입력할 경우 해당 주문/기술에 의한 치명피해만 발동됩니다.(공란이면 항상 발동함)"

							elseif db.customEvents[list.selectedIndex].condition=="outgoingBlock"
							or db.customEvents[list.selectedIndex].condition=="incomingBlock"
							or db.customEvents[list.selectedIndex].condition=="outgoingDodge"
							or db.customEvents[list.selectedIndex].condition=="incomingDodge"
							or db.customEvents[list.selectedIndex].condition=="outgoingParry"
							or db.customEvents[list.selectedIndex].condition=="incomingParry"
							or db.customEvents[list.selectedIndex].condition=="outgoingResist"
							or db.customEvents[list.selectedIndex].condition=="incomingResist"
							or db.customEvents[list.selectedIndex].condition=="outgoingImmune"
							or db.customEvents[list.selectedIndex].condition=="incomingImmune"

							or db.customEvents[list.selectedIndex].condition=="outgoingPetBlock"
							or db.customEvents[list.selectedIndex].condition=="incomingPetBlock"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetDodge"
							or db.customEvents[list.selectedIndex].condition=="incomingPetDodge"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetParry"
							or db.customEvents[list.selectedIndex].condition=="incomingPetParry"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetResist"
							or db.customEvents[list.selectedIndex].condition=="incomingPetResist"
							or db.customEvents[list.selectedIndex].condition=="outgoingPetImmune"
							or db.customEvents[list.selectedIndex].condition=="incomingPetImmune"

							or db.customEvents[list.selectedIndex].condition=="outgoingCastStart"
							or db.customEvents[list.selectedIndex].condition=="outgoingCastSuccess"
							or db.customEvents[list.selectedIndex].condition=="outgoingCastFail"
							or db.customEvents[list.selectedIndex].condition=="incomingCastStart"
							or db.customEvents[list.selectedIndex].condition=="incomingCastSuccess"
							or db.customEvents[list.selectedIndex].condition=="incomingCastFail"

							then
								return "주문/기술명을 입력할 경우 해당 주문/기술에 의한 방어행동시에만 발동됩니다.(공란이면 항상 발동함)"

							else
								return "버프/디버프 이름을 입력해주십시오."
							end
						end,
						value = {
							get = function ()
								return db.customEvents[list.selectedIndex].value
							end,
							set = function (value)
								db.customEvents[list.selectedIndex].value = value
								addon.bcf:UpdateCustomEventDB(true)
							end,
						},
					},
					{
						show = function ()
							if db.customEvents[list.selectedIndex].condition=="selfHealthGain"
							or db.customEvents[list.selectedIndex].condition=="selfHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="petHealthGain"
							or db.customEvents[list.selectedIndex].condition=="petHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="targetHealthGain"
							or db.customEvents[list.selectedIndex].condition=="targetHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="selfManaGain"
							or db.customEvents[list.selectedIndex].condition=="selfManaLoss"
							then
								return true
							end
						end,
						type = "slider",
						text = "1차 조건 값(%)",
						tooltip = function ()
							if db.customEvents[list.selectedIndex].condition=="selfHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="selfHealthGain"
							or db.customEvents[list.selectedIndex].condition=="petHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="petHealthGain"
							or db.customEvents[list.selectedIndex].condition=="targetHealthLoss"
							or db.customEvents[list.selectedIndex].condition=="targetHealthGain"
							then
								return "조건이 발동하기 위한 체력%를 입력해주십시오. 지정한 %미만으로 체력이 떨어지거나 %이상으로 올라가면 발동합니다.(단위 %)"
							else
								return "조건이 발동하기 위한 파워(마나/분노/기력)%를 입력해주십시오. 지정한 %미만으로 파워(마나/분노/기력)이 떨어지거나 %이상으로 올라가면 발동합니다.(단위 %)"
							end
						end,
						min = 0,
						max = 100,
						step = 1,
						value = {
							get = function ()
								return tonumber(db.customEvents[list.selectedIndex].value) or 0
							end,
							set = function (value)
								db.customEvents[list.selectedIndex].value = tonumber(value)
								addon.bcf:UpdateCustomEventDB(true)
							end,
						},
					},
					{
						type = "button",
						text = "2차 조건 추가",
						func = function ()
							getSubConditionFrame(nil, nil, function (subCondition)
								if not db.customEvents[list.selectedIndex].subConditions then
									db.customEvents[list.selectedIndex].subConditions = {}
								end
								if subCondition.key and subCondition.value then
									db.customEvents[list.selectedIndex].subConditions[subCondition.key] = subCondition.value
									addon.bcf:UpdateCustomEventDB(true)
									config.refresh() -- 부모스크롤창 리프레쉬
								end
							end)
						end,
						width = 110,
						height = 24,
					},
					{
						type = "group",
						options = function ()
							local t = {}
							for i=1, #subConditions do
								t[subConditions[i].value] = subConditions[i].text
							end
							local opt = {}
							if db.customEvents[list.selectedIndex].subConditions then
								for k, v in pairs(db.customEvents[list.selectedIndex].subConditions) do
									tinsert(opt, {
										type = "subCondition",
										getText = function ()
											if v and type(v)=='table' then
												local vs
												for kk, vv in pairs(v) do
													if not vs then
														vs = tostring(kk)
													else
														vs = vs..","..tostring(kk)
													end
												end
												return ("%s (%s)"):format(t[k], vs or "선택안함")
											else
												return ("%s (%s)"):format(t[k], tostring(v))
											end
										end,
										func = function ()
											getSubConditionFrame(k, v, function (subCondition)
												if not db.customEvents[list.selectedIndex].subConditions then
													db.customEvents[list.selectedIndex].subConditions = {}
												end
												db.customEvents[list.selectedIndex].subConditions[k] = nil
												db.customEvents[list.selectedIndex].subConditions[subCondition.key] = subCondition.value
												addon.bcf:UpdateCustomEventDB(true)
												config.refresh() -- 부모스크롤창 리프레쉬
											end)
										end,
										deleteFunc = function ()
											db.customEvents[list.selectedIndex].subConditions[k] = nil
											--addon.bcf:UpdateCustomEventDB(true)
											config.refresh() -- 부모스크롤창 리프레쉬
										end
									})
								end
							end
							if #opt==0 then
								tinsert(opt, {
									type = "text",
									text = "(등록된 2차조건이 없습니다)",
									size = 13,
									fontobject = GameFontNormal,
									outline = "",
									r = .8,
									g = .8,
									b = .8,
								})
							end
							return opt
						end,
					},
					{
						type = "null",
						height = 8,
					},
					{
						type = "text",
						text = "효과 설정",
						size = 20,
						font = "Fonts\\2002b.TTF",
					},
					{
						type = "group",
						options = {
							{
								type = "slider",
								text = "글자 크기",
								tooltip = "메세지 글자 크기를 설정합니다.",
								min = 10,
								max = 30,
								step = 1,
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].size
									end,
									set = function (value)
										db.customEvents[list.selectedIndex].size = tonumber(value)
										addon.bcf:UpdateCustomEventDB(true)
									end
								},
							},
							{
								type = "color",
								text = "색상",
								tooltip = "메세지의 색상을 설정합니다.",
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].color
									end,
									set = function (value)
										db.customEvents[list.selectedIndex].color = value
										addon.bcf:UpdateCustomEventDB(true)
									end
								},
							},
							{
								type = "dropdown",
								text = "글꼴",
								tooltip = "메시지의 글꼴을 설정합니다.",
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].font
									end,
									set = function (value)
										db.customEvents[list.selectedIndex].font = value
										addon.bcf:UpdateCustomEventDB(true)
									end
								},
								options = fonts,
							},
							{
								type = "dropdown",
								text = "글꼴 외각선",
								tooltip = "출력되는 메세지 글꼴의 외각선을 선택합니다.",
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].outline
									end,
									set = function (value)
										db.customEvents[list.selectedIndex].outline = value
										addon.bcf:UpdateCustomEventDB(true)
									end
								},
								options = outlines,
							},
							{
								type = "dropdown",
								text = "스크롤 영역",
								tooltip = "메세지를 출력할 스크롤 영역을 선택합니다.",
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].scrollArea
									end,
									set = function (value)
										db.customEvents[list.selectedIndex].scrollArea = value
										addon.bcf:UpdateCustomEventDB(true)
									end
								},
								options = function ()
									local sa = {}
									for i=1, #db.scrollAreas do
										tinsert(sa, { text=db.scrollAreas[i].name, value=db.scrollAreas[i].name })
									end
									return sa
								end,
							},
							{
								type = "dropdown",
								text = "애니메이션 효과",
								tooltip = "출력되는 메세지의 움직임 효과를 선택합니다.",
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].scrollType
									end,
									set = function (value)
										db.customEvents[list.selectedIndex].scrollType = value
										addon.bcf:UpdateCustomEventDB(true)
									end
								},
								options = animationTypes,
							},
							{
								type = "dropdown",
								text = "메세지 정렬",
								tooltip = "메세지 정렬 방식을 선택합니다.",
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].align
									end,
									set = function (value)
										db.customEvents[list.selectedIndex].align = value
										addon.bcf:UpdateCustomEventDB(true)
									end
								},
								options = messageAligns,
							},
						},
					},
					{
						type = "null",
						height = 8,
					},
					{
						type = "text",
						text = "직업 설정",
						size = 20,
						font = "Fonts\\2002b.TTF",
					},
					{
						type = "group",
						options = {
							{
								type = "choice",
								col = 3,
								options = {
									{ text = "전사", value = "WARRIOR", r = 0.78, g = 0.61, b = 0.43 },
									{ text = "마법사", value = "MAGE", r = 0.41, g = 0.8, b = 0.94 },
									{ text = "드루이드", value = "DRUID", r = 1.0, g = 0.49, b = 0.04 },
									{ text = "사냥꾼", value = "HUNTER", r = 0.67, g = 0.83, b = 0.45 },
									{ text = "사제", value = "PRIEST", r = 1.0, g = 1.0, b = 1.0 },
									{ text = "주술사", value = "SHAMAN", r = 0.14, g = 0.35, b = 1.0 },
									{ text = "성기사", value = "PALADIN", r = 0.96, g = 0.55, b = 0.73 },
									{ text = "흑마법사", value = "WARLOCK", r = 0.58, g = 0.51, b = 0.79 },
									{ text = "도적", value = "ROGUE", r = 1.0, g = 0.96, b = 0.41 },
									{ text = "모든직업", value = "ALL", r = .8, g = .8, b = .8, exclusion = true, tooltip = "모든 직업 공통 사용자 정의 이벤트라면 \"|cffff7f00모든직업|r\"을 체크하거나 |cffff7f00모두 체크해제|r하면 됩니다." },
								},
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].class or {["ALL"]=true}
									end,
									set = function (value)
										if value["ALL"] then
											db.customEvents[list.selectedIndex].class = nil
										else
											db.customEvents[list.selectedIndex].class = value
										end
										addon.bcf:UpdateCustomEventDB(true)
									end,
								},
							},
						},
					},
					{
						type = "null",
						height = 8,
					},
					{
						type = "text",
						text = "사운드 설정",
						size = 20,
						font = "Fonts\\2002b.TTF",
					},
					{
						type = "group",
						options = {
							{
								type = "radio",
								options = function ()
									local opt = {}
									tinsert(opt, {text = "없음", value = ""})
									for k, v in pairs(db.registedSoundFiles) do
										local filename = k:gsub("Interface\\AddOns\\","")
										filename = filename:gsub("Sound\\Creature\\","")
										filename = filename:gsub("Sound\\Event Sounds\\","")
										filename = filename:gsub("Sound\\Spells\\","")
										filename = filename:gsub("Sound\\Character\\","")
										tinsert(opt,{
											text = filename,
											value = k,
											tooltip = "클릭하시면 소리를 들어보실 수 있습니다.",
											func = function ()
												PlaySoundFile(k)
											end,
											deleteFunc = function ()
												db.registedSoundFiles[k] = nil
												addon.bcf:UpdateCustomEventDB(true)
												config.refresh()
											end,
										})
									end
									return opt
								end,
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].sound
									end,
									set = function (value)
										db.customEvents[list.selectedIndex].sound = value
										addon.bcf:UpdateCustomEventDB(true)
									end,
								},
							},
							{
								type = "editbox",
								allowBlank = true,
								text = "사운드 파일 추가(입력후 엔터필수)",
								wide = true,
								tooltip = "추가할 사운드 파일 경로를 입력해주십시오.|n입력 후 엔터 필수!!|n사용가능한 파일은 wav, mp3입니다.",
								value = {
									get = function ()
										return ""
									end,
									set = function (value)
										if value:find("\.mp3$") or value:find("\.wav$") then
											db.registedSoundFiles[value] = true
											config.refresh()
											addon.bcf:UpdateCustomEventDB(true)
										end
									end,
								},
							},
						},
					},
					{
						type = "null",
						height = 8,
					},
					{
						type = "text",
						text = "추가 설정",
						size = 20,
						font = "Fonts\\2002b.TTF",
					},
					{
						type = "group",
						options = {
							{
								type = "editbox",
								allowBlank = true,
								text = "스크립트:",
								wide = true,
								tooltip = "해당 이벤트가 발동될때 입력한 스크립트가 실행됩니다.|n입력 예시)|n|cffff7f00SendChatMessage(\"도발저항\",\"YELL\");|r",
								value = {
									get = function ()
										return db.customEvents[list.selectedIndex].script
									end,
									set = function (value)
										db.customEvents[list.selectedIndex].script = value
										addon.bcf:UpdateCustomEventDB(true)
									end,
								},
							},
						},
					},
				}
				return opt
			end
			config = drawScrollFrame(eventConfigPanel, nil, getConfigOptions, eventConfigPanel:GetWidth()-20, 226, false, 5)
			tinsert(eventConfigPanel.controls, config)

	tinsert(frame.groups, eventConfig2Panel)
	frame:Hide()
end

function addon:OnLoad()

	tinsert(UISpecialFrames,"BCFOptions")

	self:LoadBCF()

	createMainFrame()

	drawPanel()
	drawTabs()
	drawEnableButton()

	drawTab_Common()
	drawTab_Damage()
	drawTab_Heal()
	drawTab_Aura()
	drawTab_Scroll()
	drawTab_Event()

end

function addon:ConfirmFrame(msg, titleText, acceptFunc, cancelFunc)
	if not confirmFrame then
		confirmFrame = createWindowFrame("bcf_options_confirmFrame", titleText or "확인", 200, 110, true, 5)

		confirmFrame.text = confirmFrame:CreateFontString(nil, "OVERLAY","GameFontNormalSmall")
		confirmFrame.text:SetPoint("TOP", confirmFrame, "TOP", 0, -30)
		confirmFrame.text:SetHeight(47)

		confirmFrame.acceptButton = createButton(confirmFrame, "예")
		confirmFrame.acceptButton:SetPoint("BOTTOM", confirmFrame, "BOTTOM", -40, 10)
		confirmFrame.acceptButton:SetWidth(70)
		confirmFrame.acceptButton:SetHeight(24)

		confirmFrame.cancelButton = createButton(confirmFrame, "아니오")
		confirmFrame.cancelButton:SetPoint("BOTTOM", confirmFrame, "BOTTOM", 40, 10)
		confirmFrame.cancelButton:SetWidth(70)
		confirmFrame.cancelButton:SetHeight(24)
		tinsert(addon.frame.subFrames, confirmFrame) -- 최상위 설정창의 자식창으로 등록
	else
		if titleText then
			confirmFrame.title.text:SetText(titleText)
		end
	end

	confirmFrame.text:SetText(msg)
	if confirmFrame.text:GetStringWidth()>170 then
		if confirmFrame.text:GetStringWidth()>300 then
			confirmFrame:SetWidth(330)
			confirmFrame.text:SetWidth(300)
		else
			confirmFrame:SetWidth(confirmFrame.text:GetStringWidth()+30)
			confirmFrame.text:SetWidth(confirmFrame.text:GetStringWidth())
		end
	else
		confirmFrame.text:SetWidth(170)
	end
	confirmFrame.acceptButton:SetScript("OnClick", function ()
		if acceptFunc and type(acceptFunc)=='function' then
			acceptFunc()
		end
		confirmFrame:Hide()
	end)
	confirmFrame.cancelButton:SetScript("OnClick", function ()
		if cancelFunc and type(cancelFunc)=='function' then
			cancelFunc()
		end
		confirmFrame:Hide()
	end)
	confirmFrame:Show()
end

function addon:LoadBCF()
	local bcf = _G["BlinkCombatFeedback"]
	db = bcf.db
	animationTypes = bcf.animationTypes
	self.bcf = bcf
end

addon:OnLoad()
