local AceGUI = LibStub("AceGUI-3.0")

local function print(a)
	DEFAULT_CHAT_FRAME:AddMessage(a)
end


local function ZOMGConfig(widget, event)
	AceGUI:Release(widget.userdata.parent)
	
	local f = AceGUI:Create("Frame")
	
	f:SetCallback("OnClose",function(widget, event) print("Closing") AceGUI:Release(widget) end )
	f:SetTitle("ZOMG Config!")
	f:SetStatusText("Status Bar")
	f:SetLayout("Fill")
	
	local maingroup = AceGUI:Create("DropdownGroup")
	maingroup:SetLayout("Fill")
	maingroup:SetGroupList({Addons = "Addons !!", Zomg = "Zomg Addons"})
	maingroup:SetGroup("Addons")
	maingroup:SetTitle("")
	
	f:AddChild(maingroup)
	
	local tree = { "A", "B", "C", "D", B = { "B1", "B2", B1 = { "B11", "B12" } }, C = { "C1", "C2", C1 = { "C11", "C12" } } }
	local text = { A = "Option 1", B = "Option 2", C = "Option 3", D = "Option 4", J = "Option 10", K = "Option 11", L = "Option 12", 
					B1 = "Option 2-1", B2 = "Option 2-2", B11 = "Option 2-1-1", B12 = "Option 2-1-2",
					C1 = "Option 3-1", C2 = "Option 3-2", C11 = "Option 3-1-1", C12 = "Option 3-1-2" }
	local t = AceGUI:Create("TreeGroup")
	t:SetLayout("Fill")
	t:SetTree(tree, text)
	maingroup:AddChild(t)
	
	local tab = AceGUI:Create("TabGroup")
	tab:SetTabs({"A","B","C","D"},{A="Yay",B="We",C="Have",D="Tabs"})
	tab:SetLayout("Fill")
	tab:SelectTab(1)
	t:AddChild(tab)
	
	local component = AceGUI:Create("DropdownGroup")
	component:SetLayout("Fill")
	component:SetGroupList({Blah = "Blah", Splat = "Splat"})
	component:SetGroup("Blah")
	component:SetTitle("Choose Componet")
	
	tab:AddChild(component)
	
	local more = AceGUI:Create("DropdownGroup")
	more:SetLayout("Fill")
	more:SetGroupList({ButWait = "But Wait!", More = "Theres More"})
	more:SetGroup("More")
	more:SetTitle("And More!")
	
	component:AddChild(more)
	
	local sf = AceGUI:Create("ScrollFrame")
	sf:SetLayout("Flow")
	more:AddChild(sf)
	local stuff = AceGUI:Create("Heading")
	stuff:SetText("Omg Stuff Here")
	stuff.width = "fill"
	sf:AddChild(stuff)
	
	for i = 1, 10 do
		local edit = AceGUI:Create("EditBox")
		edit:SetText("")
		edit:SetWidth(200)
		edit:SetLabel("Stuff!")
		edit:SetCallback("OnEnterPressed",function(widget,event,text) widget:SetLabel(text) end )
		edit:SetCallback("OnTextChanged",function(widget,event,text) print(text) end )
		sf:AddChild(edit)
	end
	
	f:Show()
end

local function GroupA(content)
	content:ReleaseChildren()
	
	local sf = AceGUI:Create("ScrollFrame")
	sf:SetLayout("Flow")
	
	local edit = AceGUI:Create("EditBox")
	edit:SetText("Testing")
	edit:SetWidth(200)
	edit:SetLabel("Group A Option")
	edit:SetCallback("OnEnterPressed",function(widget,event,text) widget:SetLabel(text) end )
	edit:SetCallback("OnTextChanged",function(widget,event,text) print(text) end )
	sf:AddChild(edit)
	
	local slider = AceGUI:Create("Slider")
	slider:SetLabel("Group A Slider")
	slider:SetSliderValues(0,1000,5)
	slider:SetDisabled(false)
	sf:AddChild(slider)
	
	local zomg = AceGUI:Create("Button")
	zomg.userdata.parent = content.userdata.parent
	zomg:SetText("Zomg!")
	zomg:SetCallback("OnClick", ZOMGConfig)
	sf:AddChild(zomg)
	
	local heading1 = AceGUI:Create("Heading")
	heading1:SetText("Heading 1")
	heading1.width = "fill"
	sf:AddChild(heading1)
	
	for i = 1, 5 do
		local radio = AceGUI:Create("CheckBox")
		radio:SetLabel("Test Check "..i)
		radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Check "..i.." Checked" or "Check "..i.." Unchecked") end )
		sf:AddChild(radio)
	end
	
	local heading2 = AceGUI:Create("Heading")
	heading2:SetText("Heading 2")
	heading2.width = "fill"
	sf:AddChild(heading2)
	
	for i = 1, 5 do
		local radio = AceGUI:Create("CheckBox")
		radio:SetLabel("Test Check "..i+5)
		radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Check "..i.." Checked" or "Check "..i.." Unchecked") end )
		sf:AddChild(radio)
	end
	
	local heading1 = AceGUI:Create("Heading")
	heading1:SetText("Heading 1")
	heading1.width = "fill"
	sf:AddChild(heading1)
	
    for i = 1, 5 do
	    local radio = AceGUI:Create("CheckBox")
	    radio:SetLabel("Test Check "..i)
	    radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Check "..i.." Checked" or "Check "..i.." Unchecked") end )
	    sf:AddChild(radio)
	end
	
	local heading2 = AceGUI:Create("Heading")
	heading2:SetText("Heading 2")
	heading2.width = "fill"
	sf:AddChild(heading2)
	
    for i = 1, 5 do
	    local radio = AceGUI:Create("CheckBox")
	    radio:SetLabel("Test Check "..i+5)
	    radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Check "..i.." Checked" or "Check "..i.." Unchecked") end )
	    sf:AddChild(radio)
	end
    
	content:AddChild(sf)
end

local function GroupB(content)
	content:ReleaseChildren()
	local sf = AceGUI:Create("ScrollFrame")
	sf:SetLayout("Flow")
	
 	local check = AceGUI:Create("CheckBox")
	check:SetLabel("Group B Checkbox")
	check:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Checked" or "Unchecked") end )
	
	local dropdown = AceGUI:Create("Dropdown")
	dropdown:SetText("Test")
	dropdown:SetLabel("Group B Dropdown")
	dropdown.list = {"Test","Test2"}
	dropdown:SetCallback("OnValueChanged",function(widget,event,value) print(value) end )
	
	sf:AddChild(check)
	sf:AddChild(dropdown)
	content:AddChild(sf)
end

local function OtherGroup(content)
	content:ReleaseChildren()
	
	local sf = AceGUI:Create("ScrollFrame")
	sf:SetLayout("Flow")
	
 	local check = AceGUI:Create("CheckBox")
	check:SetLabel("Test Check")
	check:SetCallback("OnValueChanged",function(widget,event,value) print(value and "CheckButton Checked" or "CheckButton Unchecked") end )
	
	sf:AddChild(check)
	
	local inline = AceGUI:Create("InlineGroup")
	inline:SetLayout("Flow")
	inline:SetTitle("Inline Group")
	inline.width = "fill"

	local heading1 = AceGUI:Create("Heading")
	heading1:SetText("Heading 1")
	heading1.width = "fill"
	inline:AddChild(heading1)
	
	for i = 1, 10 do
		local radio = AceGUI:Create("CheckBox")
		radio:SetLabel("Test Radio "..i)
		radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Radio "..i.." Checked" or "Radio "..i.." Unchecked") end )
		radio:SetType("radio")
		inline:AddChild(radio)
	end
	
	local heading2 = AceGUI:Create("Heading")
	heading2:SetText("Heading 2")
	heading2.width = "fill"
	inline:AddChild(heading2)
	
	for i = 1, 10 do
		local radio = AceGUI:Create("CheckBox")
		radio:SetLabel("Test Radio "..i)
		radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Radio "..i.." Checked" or "Radio "..i.." Unchecked") end )
		radio:SetType("radio")
		inline:AddChild(radio)
	end
	
	
	sf:AddChild(inline)
	content:AddChild(sf)
end

local function SelectGroup(widget, event, value)
	if value == "A" then
		GroupA(widget)
	elseif value == "B" then
	 GroupB(widget)
	else
		OtherGroup(widget)
	end
end


local function TreeWindow(content)
	content:ReleaseChildren()
	
	local tree = { 
			{ 
				value = "A",
				text = "Alpha"
			},
			{
				value = "B",
				text = "Bravo",
				children = {
					{ 
						value = "C", 
						text = "Charlie",
					},
					{
						value = "D",	
						text = "Delta",
						children = { 
							{ 
								value = "E",
								text = "Echo",
							} 
						} 
					},
				}
			},
			{ 
				value = "F", 
				text = "Foxtrot",
			},
		}
	local t = AceGUI:Create("TreeGroup")
	t:SetLayout("Fill")
	t:SetTree(tree)
	t:SetCallback("OnGroupSelected", SelectGroup )
	content:AddChild(t)
	SelectGroup(t,"OnGroupSelected","A")
	
end

local function TabWindow(content)
	content:ReleaseChildren()
	local tab = AceGUI:Create("TabGroup")
	tab.userdata.parent = content.userdata.parent
	tab:SetTabs({"A","B","C","D"},{A="Alpha",B="Bravo",C="Charlie",D="Deltaaaaaaaaaaaaaa"})
	tab:SetTitle("Tab Group")
	tab:SetLayout("Fill")
	tab:SetCallback("OnGroupSelected",SelectGroup)
	tab:SelectTab(1)
	content:AddChild(tab)
	
end


function TestFrame()
	local f = AceGUI:Create("Frame")
	f:SetCallback("OnClose",function(widget, event) print("Closing") AceGUI:Release(widget) end )
	f:SetTitle("AceGUI Prototype")
	f:SetStatusText("Root Frame Status Bar")
	f:SetLayout("Fill")
	
	local maingroup = AceGUI:Create("DropdownGroup")
	maingroup.userdata.parent = f
	maingroup:SetLayout("Fill")
	maingroup:SetGroupList({Tab = "Tab Frame", Tree = "Tree Frame"})
	maingroup:SetGroup("Tab")
	maingroup:SetTitle("Select Group Type")
	maingroup:SetCallback("OnGroupSelected", function(widget, event, value)
		widget:ReleaseChildren()
		if value == "Tab" then
			TabWindow(widget)
		else
			TreeWindow(widget)
		end
	end )
	
	TabWindow(maingroup)
	f:AddChild(maingroup)
	
	
	f:Show()
end

-----------------------
-- DragTarget Widget --
-----------------------
-- Designed to replace type='input' in AceConfigDialog-3.0
do
	local Type = "DragTarget"
	local Version = 1
	local function Acquire(self)

	end
	
	local function Release(self)
		self.frame:ClearAllPoints()
		self.frame:Hide()
	end
	

	local function SetLabel(self, text)
		self.label:SetText(text)
	end

	local function PickupItem(link)
		local name = GetItemInfo(link)
		for bag = 0, 4 do
			for slot = 1, GetContainerNumSlots(bag) do
				local slotlink = GetContainerItemLink(bag, slot)
				if slotlink then
					local slotname = GetItemInfo(slotlink)
					if slotname == name then
						PickupContainerItem(bag, slot)
						return
					end
				end
			end
		end
	end

	local function DragLinkOnDragStart(this)
		local self = this.obj
		if (self.objType == "item") then
			PickupItem(self.value)
		elseif (self.objType == "spell") then
			PickupSpell(self.value)
		elseif (self.objType == "macro") then
			PickupMacro(strsub(self.value,7))
		end
		self:SetText("")
		self:Fire("OnEnterPressed", self.value)
	end
	

	local function DragLinkGetTexture(self)
		if (self.objType == "item") then
				local texture = select(10,GetItemInfo(self.value))
				if (texture) then
					return texture
				end
		elseif (self.objType == "spell") then
			local texture = GetSpellTexture(self.value)
			if (texture) then
				return texture
			end
		elseif (self.objType == "macro") then
			local name, texture = GetMacroInfo(strsub(self.value,7))
			return texture
		end
		return "Interface\\Icons\\INV_Misc_QuestionMark"
	end
	
	local function GetValueFromParams(objType, Info1, Info2)
		if objType == "item" then
			--for items use the link
			return Info2
		elseif objType == "spell" then
			local name, rank = GetSpellName(Info1, Info2)
			if rank ~= "" then name = name.."("..rank..")" end
			return name
		elseif objType == "macro" then
			return "macro:"..GetMacroInfo(Info1)
		end
	end
	
	local function DragLinkOnReceiveDrag(this)
		local self = this.obj

		local objType, Info1, Info2 = GetCursorInfo()

		if (objType == "item" or objType == "spell" or objType == "macro") then
			self.objType = objType
			self.value = GetValueFromParams(objType, Info1, Info2)
			self:Fire("OnEnterPressed", self.value)
			self.linkIcon:SetTexture(DragLinkGetTexture(self))

			ClearCursor()
		end
	end
	
	local function SetText(self, text)
		if not text then text = "" end
		if text:find("item:%d+") then
			self.objType = "item"
			self.value = text
		elseif strsub(text,1,6) == "macro:" then
			self.objType = "macro"
			self.value = text
		elseif text ~= "" then
			self.objType = "spell"
			self.value = text
		else
			self.objType = nil
			self.value = ""
		end
		self.linkIcon:SetTexture(DragLinkGetTexture(self))
		self.text:SetText(self.value or "")
	end
	
	local function SetDisabled(self, disabled)
	
	end
	
	local function Constructor()
		local frame = CreateFrame("Button",nil,UIParent)
		local self = {}
		self.type = Type
		

		self.Release = Release
		self.Acquire = Acquire
		self.SetLabel = SetLabel
		self.SetText = SetText
		self.SetDisabled = SetDisabled
		self.UpdateValue = UpdateValue
		
		self.frame = frame
		frame.obj = self

		frame:SetScript("OnDragStart", DragLinkOnDragStart)
		frame:SetScript("OnReceiveDrag", DragLinkOnReceiveDrag)
		frame:SetScript("OnClick", DragLinkOnReceiveDrag)
		frame:SetScript("OnEnter", DragLinkOnEnter)
		frame:SetScript("OnLeave", DragLinkOnLeave)
	
		frame:EnableMouse()
		frame:RegisterForDrag("LeftButton")
		frame:RegisterForClicks("LeftButtonUp", "RightButtonUp")
	
		local linkIcon = frame:CreateTexture(nil, "OVERLAY")
		linkIcon:SetWidth(self.iconWidth or 36)
		linkIcon:SetHeight(self.iconHeight or 36)
		linkIcon:SetPoint("LEFT",frame,"LEFT",0,0)
		linkIcon:SetTexture(DragLinkGetTexture(self))
		linkIcon:SetTexCoord(0,1,0,1)
		linkIcon:Show()
		self.linkIcon = linkIcon
		
		local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
		label:SetPoint("TOPLEFT",linkIcon,"TOPRIGHT",3,-3)
		label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
		label:SetHeight(10)
		label:SetJustifyH("LEFT")
		self.label = label
		
		local text = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
		text:SetPoint("BOTTOMLEFT",linkIcon,"BOTTOMRIGHT",3,3)
		text:SetPoint("RIGHT",frame,"RIGHT",0,0)
		text:SetHeight(10)
		text:SetTextColor(1,1,1,1)
		text:SetJustifyH("LEFT")
		self.text = text
	
		text:SetJustifyH("LEFT")
		text:SetTextColor(1,1,1)
	
		frame:SetHeight(36)
		frame:SetWidth(200)

		AceGUI:RegisterAsWidget(self)
		return self
	end
	
	AceGUI:RegisterWidgetType(Type,Constructor,Version)
	
end

local name = "ConfigTest" 
local groups = {} 
local testgroups = {
	type = "group",
	name = "Test Group Delete/Hide/Diabled",
	childGroups = "select",
	args = {
	
	}
}

local function Delete(info) 
  testgroups.args[info.arg] = nil 
end 

local function Disable(info) 
  testgroups.args[info.arg].disabled = true 
end 

local function Hide(info)
  testgroups.args[info.arg].hidden = true
end

local function Replace(info)
	testgroups.args[info.arg] = {
		type = "execute",
		name = "Replaced"..info.arg
	}
end

groups.description = {
	type = 'description',
	name = 'This is a test Description Icon + Width and height from a function, no coords',
	image = function() return "Interface\\Icons\\Temp.blp", 100, 100 end,
	--imageCoords = { 0, 0.5, 0, 0.5 },
	order = 1,
}
--[[
groups.description2 = {
	type = 'description',
	name = 'This is a test Description Image + width and height directly set',
	image = "Interface\\Icons\\Temp.blp",
	imageCoords = { 0, 0.5, 0, 0.5 },
	imageWidth = 100,
	imageHeight = 100,
	order = 2,
}

groups.description3 = {
	type = 'description',
	name = '',
	image = function() return "Interface\\Icons\\Temp.blp", 100, 100 end,
	--imageCoords = { 0, 0.5, 0, 0.5 },
	order = 3,
}
--]]
groups.confirm = {
	type = 'execute',
	name = 'Test Confirm',
	order = 15,
	func = function() print("Confirmed") end,
	confirm = true,
	confirmText = "Confirm Prompt",
}

local dragvalue = nil

groups.customDrag = {
	type = 'input',
	name = 'Test Custom Control',
	get = function() return dragvalue end,
	set = function(info, value) dragvalue = value end,
	dialogControl = "DragTarget",
	order = 16,
}


for i = 1, 5 do 
  testgroups.args["group"..i] = { 
    order = i, 
    type = "group", 
    name = "Group"..i, 
    args = { 
      delete = { 
        name = "Delete", 
        desc = "Delete this group", 
        type = "execute", 
        arg = "group"..i, 
        func = Delete, 
      }, 
		disable = { 
        name = "Disable", 
        desc = "Disable this group", 
        type = "execute", 
        arg = "group"..i, 
        func = Disable, 
      }, 
		hide = { 
        name = "Hide", 
        desc = "Hide this group", 
        type = "execute", 
        arg = "group"..i, 
        func = Hide, 
      }, 
		replace = { 
        name = "Replace", 
        desc = "Replace this group", 
        type = "execute", 
        arg = "group"..i, 
        func = Replace, 
      }, 
    } 
  } 
end 

local m = { }

groups.multi = {
	type = 'multiselect',
	name = 'multi',
	desc = 'Test Multiselect',
	tristate = true,
	width = "half",
	set = function(info, key, value) m[key] = value print(key, value) end,
	get = function(info, key) return m[key] end,
	order = 100,
	values = {
		a = "Alpha",
		b = "Bravo",
		c = "Charlie",
		d = "Delta",
		e = "Echo",
		f = "Foxtrot",
	}
}

local sel = 'a'

groups.select = {
	type = 'select',
	name = 'select',
	desc = 'Test Select',
	set = function(info, key, value) sel = key print(sel) end,
	get = function(info, key) return sel end,
	order = 101,
	values = {
		a = "Alpha",
		b = "Bravo",
		c = "Charlie",
		d = "Delta",
		e = "Echo",
		f = "Foxtrot",
	}
}

local toggleval

groups.toggle = {
	type = 'toggle',
	name = 'toggle',
	desc = 'Test Toggle',
	set = function(info, value) toggleval = value print(toggleval) end,
	get = function(info) return toggleval end,
	tristate = true,
	order = 102
}

local R,G,B,A = 1.0,1.0,1.0,1.0

groups.color = {
	type = 'color',
	name = 'color',
	desc = 'Test Color',
	set = function(info, r,g,b,a) R,G,B,A = r,g,b,a print(R,G,B,A) end,
	get = function(info) return R,G,B,A end,
	hasAlpha = false,
	order = 103
}

groups.colora = {
	type = 'color',
	name = 'colora',
	desc = 'Test Color with Alpha',
	set = function(info, r,g,b,a) R,G,B,A = r,g,b,a print(R,G,B,A) end,
	get = function(info) return R,G,B,A end,
	hasAlpha = true,
	order = 104
}

local keyval
groups.key = {
	type = 'keybinding',
	name = 'key',
	desc = 'Test Keybind',
	set = function(info, value) keyval = value print(keyval) end,
	get = function(info) return keyval end,
	order = 105,
}

local mval
groups.multiline = {
	type = 'input',
	name = "Multiline",
	desc = "Test Multiline",
	set = function(info, value) mval = value print(mval) end,
	get = function(info) return mval end,
	multiline = true,
}

local options = { 
  type = "group", 
  name = name, 
  childGroups = "tab", 
  args = {
	  	test = {
	  	type = "group",
	  	name = "Test Controls",
	  	args = groups,
	  	disabled = false
  	}
  } 
} 

local types = {'input', 'toggle', 'select', 'multiselect', 'range', 'keybinding', 'execute', 'color'}
local function GetTestOpts(disabled)
	local values = { input = "Test", select = 'a', multiselect = true, range = 1}
	local group = {
		type = "group",
		--inline = true,
		name = "Options",
		set = function(info, value) values[info[#info]] = value end,
		get = function(info, value) return values[info[#info]] end,
		args = {}
	}
	
	if disabled then
		group.name = "Disabled Options"
	end

	for i, type in ipairs(types) do
		local opt = {}
		opt.name = type
		opt.type = type
		opt.desc = "Test "..type
		opt.order = i
		opt.disabled = disabled
		if type == "select" or type =="multiselect" then
			opt.values = {
				a = "Alpha",
				b = "Bravo",
				c = "Charlie",
				d = "Delta",
				e = "Echo",
				f = "Foxtrot",
			}
		end
		
		if type == "range" then
			opt.min = 0
			opt.max = 1000
			opt.step = 1
			opt.bigStep = 10
		end
		
		if type == "execute" then
			opt.func = function(info) print("Execute") end
		end
		
		group.args[type] = opt
	end
	return group
end

options.plugins = {}
options.plugins.normal = { normal = GetTestOpts() }
options.plugins.disabled = { disabled = GetTestOpts(true) }
options.plugins.test = { testgroups = testgroups }

LibStub("AceConfig-3.0"):RegisterOptionsTable(name, options, "ct") 
--LibStub("AceConfigDialog-3.0"):Open("ConfigTest" )

