Rapture = LibStub("AceAddon-3.0"):NewAddon("Ingela's Rapture", "AceConsole-3.0", "AceEvent-3.0")
RaptureGUI = LibStub("AceGUI-3.0")
local rapmedia = LibStub("LibSharedMedia-3.0")
local rapcandy = LibStub("LibCandyBar-3.0")
local db

local defaults = {
	profile = {
		scale = 1.0,
		xpos = 0,
		ypos = 0,
		colorr = 0, 
		colorg = 0.5, 
		colorb = 1, 
		colora = 1,        
		bgcolorr = 0, 
		bgcolorg = 0.5, 
		bgcolorb = 1, 
		bgcolora = 0.5,
		width = 200,
		height = 19,
		texture = "Blizzard",
		font = "Friz Quadrata TT",
		fontscale = 12,
		outline = 4,
		alignment = "LEFT",
		valignment = "CENTER",
		labelinput = "Rapture Cooldown",
		soundenable = true,
		frametime = 6,
		fadetime = 0.5,
		framelabelinput = "Rapture ready!",
		framefont = "Friz Quadrata TT",
		framexpos = 0,
		frameypox = 0,
		framefontscale = 24,
		framecolorr = 1,
		framecolorg = 1,
		framecolorb = 1,
		frameenable = true,
		fill = false,
		icon = true,
	},
}

local options = {
type = "group",
childGroups = "tab",
	args = {
		info = {
			order = 1,
			name = "Info",
			desc = "Shows info about the addon",
			type = 'execute',
			func = function()
			Rapture:Print("This addon shows a neat bar too see how long cooldown is left on your rapture ability. Made by Ingela @ Twilight's Hammer(EU)")
			end,
		},
		test = {
			order = 2,
			name = "Run Bar",
			desc = "Test rapture cooldown bar",
			type = 'execute',
			func = function()
			Rapture:Runbar()
			Rapture:barset()
			end,
		},
		bar = {
		type = "group",
		name = "Bar Options",
			args = {
				barposdesc = {
					order = 1,
					type = "description",
					name = "Bar positioning\n",
					cmdHidden = true
				},
				xpos = {
					order = 3,
					name = "X",
					desc = "Change horizontal position",
					type = 'range',
					min = -500,
					max = 500,
					step = 1,
					get = function(info) return db.xpos end,
					set = function(info, x) 
					db.xpos = x
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				ypos = {
					order = 6,
					name = "Y",
					desc = "Change veritcal position",
					type = 'range',
					min = -500,
					max = 500,
					step = 1,
					get = function(info) return db.ypos end,
					set = function(info, y) 
					db.ypos = y
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				nudgeright = {
					order = 4,
					name = "Right",
					desc = "Nudge right once",
					type = 'execute',
					get = function(info) return db.xpos end,
					func = function() 
					db.xpos = db.xpos + 1
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				nudgeleft = {
					order = 2,
					name = "Left",
					desc = "Nudge left once",
					type = 'execute',
					get = function(info) return db.xpos end,
					func = function() 
					db.xpos = db.xpos - 1
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				nudgeup = {
					order = 5,
					name = "Up",
					desc = "Nudge up once",
					type = 'execute',
					get = function(info) return db.ypos end,
					func = function() 
					db.ypos = db.ypos + 1
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				nudgedown = {
					order = 7,
					name = "Down",
					desc = "Nudge down once",
					type = 'execute',
					get = function(info) return db.ypos end,
					func = function() 
					db.ypos = db.ypos - 1
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				scaledesc = {
					order = 9,
					type = "description",
					name = "\n\nBar settings\n",
					cmdHidden = true
				},
				scale = {
					order = 10,
					name = "Scale",
					desc = "Set scale",
					type = 'range',
					min = 0.5,
					max = 2,
					step = 0.1,
					get = function(info) return db.scale end,
					set = function(info, s) 
					db.scale = s
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				width = {
					order = 11,
					name = "Width",
					desc = "Set width",
					type = 'range',
					min = 10,
					max = 600,
					step = 1,
					get = function(info) return db.width end,
					set = function(info, w) 
					db.width = w
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				height = {
					order = 12,
					name = "Height",
					desc = "Set height",
					type = 'range',
					min = 1,
					max = 60,
					step = 1,
					get = function(info) return db.height end,
					set = function(info, h) 
					db.height = h
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				textstuff = {
					order = 15,
					type = "description",
					name = "\n\nText settings\n",
					cmdHidden = true
				},
				texture = {
					order = 14,
					type = "select",
					name = "Texture",
					desc = "Set the statusbar texture.",
					values = rapmedia:HashTable("statusbar"),
					dialogControl = "LSM30_Statusbar",
					get = function(info) return db.texture end,
					set = function(info, text) 
					db.texture = text
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				font = {
					order = 16,
					type = "select",
					name = "Font",
					desc = "Set the font.",
					values = rapmedia:HashTable("font"),
					dialogControl = "LSM30_Font",
					get = function(info) return db.font end,
					set = function(info, f) 
					db.font = f
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				fontscale = {
					order = 17,
					name = "Font Scale",
					desc = "Set the font scale",
					type = 'range',
					min = 1,
					max = 50,
					step = 1,
					get = function(info) return db.fontscale end,
					set = function(info, fontsc) 
					db.fontscale = fontsc
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				outline = {
					order = 18,
					name = "Outline",
					desc = "Outline",
					type = 'select',
					values = {["OUTLINE"]="Outline", ["THICKOUTLINE"]="Thickoutline", ["MONOCHROME"]="Monochrome", ["NONE"]="None"},
					get = function(info) return db.outline end,
					set = function(info, line)
					db.outline = line
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				alignment = {
					order = 19,
					name = "Text alignment",
					desc = "Text alignment",
					type = 'select',
					values = {["LEFT"]="Left", ["CENTER"]="Center", ["Right"]="Right"},
					get = function(info) return db.alignment end,
					set = function(info, line)
					db.alignment = line
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				labelinput = {
					order = 20,
					name = "Label text",
					desc = "Label text",
					type = 'input',
					get = function(info) return db.labelinput end,
					set = function(info, line)
					db.labelinput = line
						if db.labelinput == "" then
							Rapture:Print("Label text can not be empty. Reverting back to default text")
							db.labelinput = "Rapture Cooldown"
							Rapture:Runbar()
							Rapture:barset()
						else
							Rapture:Runbar()
							Rapture:barset()
						end
					end,
				},
				fill = {
					order = 21,
					name = "Enable fill",
					desc = "Enable fill",
					type = 'toggle',
					get = function(info) return db.fill end,
					set = function(info, x) 
					db.fill = x
						if RaptureBAR then
							RaptureBAR:Stop()
						end
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
				icon = {
					order = 22,
					name = "Enable icon",
					desc = "Enable icon",
					type = 'toggle',
					get = function(info) return db.icon end,
					set = function(info, x) 
					db.icon = x
					Rapture:Runbar()
					Rapture:barset()
					end,
				},
			},
		},
		colors = {
		type = "group",
		name = "Bar Colors",
			args = {
				barcolordesc = {
						order = 1,
						type = "header",
						name = "Bar color\n",
						cmdHidden = true
				},
				barcolor = {
						order = 2,
						name = "Bar color",
						desc = "Set color",
						type = 'color',
						hasAlpha = true,
						get = function(info) return db.colorr, db.colorg, db.colorb, db.colora end,
						set = function(info, r, g, b, a)
						db.colorr, db.colorg, db.colorb, db.colora = r, g, b, a
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
				barcolorrgbadesc = {
						order = 3,
						type = "description",
						name = "\n\nRGBA changer\n",
						cmdHidden = true
				},
				barR = {
						order = 4,
						name = "Red",
						desc = "Set red color",
						type = 'range',
						min = 0,
						max = 1,
						step = 0.01,
						get = function(info) return db.colorr end,
						set = function(info, r)
						db.colorr = r
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
				barG = {
						order = 5,
						name = "Green",
						desc = "Set green color",
						type = 'range',
						min = 0,
						max = 1,
						step = 0.01,
						get = function(info) return db.colorg end,
						set = function(info, g)
						db.colorg = g
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
				barB = {
						order = 6,
						name = "Blue",
						desc = "Set blue color",
						type = 'range',
						min = 0,
						max = 1,
						step = 0.01,
						get = function(info) return db.colorb end,
						set = function(info, b)
						db.colorb = b
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
				barA = {
						order = 7,
						name = "Alpha",
						desc = "Set the alpha",
						type = 'range',
						min = 0,
						max = 1,
						step = 0.01,
						get = function(info) return db.colora end,
						set = function(info, a)
						db.colora = a
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
				bgcolordesc = {
						order = 9,
						type = "header",
						name = "Bar background color\n",
						cmdHidden = true
				},
				bgcolor = {
						order = 10,
						name = "Bar background color",
						desc = "Set color",
						type = 'color',
						hasAlpha = true,
						get = function(info) return db.bgcolorr, db.bgcolorg, db.bgcolorb, db.bgcolora end,
						set = function(info, bgr, bgg, bgb, bga)
						db.bgcolorr, db.bgcolorg, db.bgcolorb, db.bgcolora = bgr, bgg, bgb, bga
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
				bgcolorrgbadesc = {
						order = 11,
						type = "description",
						name = "\n\nRGBA changer\n",
						cmdHidden = true
				},
				bgR = {
						order = 12,
						name = "Red",
						desc = "Set red color",
						type = 'range',
						min = 0,
						max = 1,
						step = 0.01,
						get = function(info) return db.bgcolorr end,
						set = function(info, bgr)
						db.bgcolorr = bgr
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
				bgG = {
						order = 13,
						name = "Green",
						desc = "Set green color",
						type = 'range',
						min = 0,
						max = 1,
						step = 0.01,
						get = function(info) return db.bgcolorg end,
						set = function(info, bgg)
						db.bgcolorg = bgg
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
				bgB = {
						order = 14,
						name = "Blue",
						desc = "Set blue color",
						type = 'range',
						min = 0,
						max = 1,
						step = 0.01,
						get = function(info) return db.bgcolorb end,
						set = function(info, bgb)
						db.bgcolorb = bgb
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
				bgA = {
						order = 15,
						name = "Alpha",
						desc = "Set the alpha",
						type = 'range',
						min = 0,
						max = 1,
						step = 0.01,
						get = function(info) return db.bgcolora end,
						set = function(info, bga)
						db.bgcolora = bga  
						Rapture:Runbar()
						Rapture:barset()
						end,
				},
			},
		},
		message = {
		type = "group",
		name = "Message Frame",
			args = {
				frametime = {
					order = 1,
					name = "Up time",
					desc = "How long the frame will be shown",
					type = 'range',
					min = 1,
					max = 12,
					step = 1,
					get = function(info) return db.frametime end,
					set = function(info, x) 
					db.frametime = x
					Rapture:frame()
					end,
				},
				fadetime = {
					order = 2,
					name = "Fade time",
					desc = "How long it takes to hide the frame",
					type = 'range',
					min = 0.1,
					max = 1,
					step = 0.1,
					get = function(info) return db.fadetime end,
					set = function(info, x) 
					db.fadetime = x
					Rapture:frame()
					end,
				},
				framefont = {
					order = 3,
					type = "select",
					name = "Font",
					desc = "Set the font",
					values = rapmedia:HashTable("font"),
					dialogControl = "LSM30_Font",
					get = function(info) return db.framefont end,
					set = function(info, f) 
					db.framefont = f
					Rapture:frame()
					end,
				},
				framefontscale = {
					order = 4,
					name = "Font Scale",
					desc = "Set the font scale",
					type = 'range',
					min = 1,
					max = 24,
					step = 1,
					get = function(info) return db.framefontscale end,
					set = function(info, fontsc) 
					db.framefontscale = fontsc
					Rapture:frame()
					end,
				},
				frameoutline = {
					order = 5,
					name = "Outline",
					desc = "Outline",
					type = 'select',
					values = {["OUTLINE"]="Outline", ["THICKOUTLINE"]="Thickoutline", ["MONOCHROME"]="Monochrome", ["NONE"]="None"},
					get = function(info) return db.frameoutline end,
					set = function(info, line)
					db.frameoutline = line
					Rapture:frame()
					end,
				},
				framelabelinput = {
					order = 6,
					name = "Frame text",
					desc = "Frame text",
					type = 'input',
					get = function(info) return db.framelabelinput end,
					set = function(info, line)
					db.framelabelinput = line
					Rapture:frame()
					end,
				},
				framepos = {
					order = 7,
					type = "description",
					name = "\n\nFrame Position\n",
					cmdHidden = true
				},
				framexpos = {
					order = 9,
					name = "X",
					desc = "Change horizontal position",
					type = 'range',
					min = -500,
					max = 500,
					step = 1,
					get = function(info) return db.framexpos end,
					set = function(info, x) 
					db.framexpos = x
					Rapture:frame()
					end,
				},
				frameypos = {
					order = 12,
					name = "Y",
					desc = "Change veritcal position",
					type = 'range',
					min = -500,
					max = 500,
					step = 1,
					get = function(info) return db.frameypos end,
					set = function(info, y) 
					db.frameypos = y
					Rapture:frame()
					end,
				},
				framenudgeright = {
					order = 10,
					name = "Right",
					desc = "Nudge right once",
					type = 'execute',
					get = function(info) return db.framexpos end,
					func = function() 
					db.framexpos = db.framexpos + 1
					Rapture:frame()
					end,
				},
				framenudgeleft = {
					order = 8,
					name = "Left",
					desc = "Nudge left once",
					type = 'execute',
					get = function(info) return db.framexpos end,
					func = function() 
					db.framexpos = db.framexpos - 1
					Rapture:frame()
					end,
				},
				framenudgeup = {
					order = 11,
					name = "Up",
					desc = "Nudge up once",
					type = 'execute',
					get = function(info) return db.frameypos end,
					func = function() 
					db.frameypos = db.frameypos + 1
					Rapture:frame()
					end,
				},
				framenudgedown = {
				order = 13,
				name = "Down",
				desc = "Nudge down once",
				type = 'execute',
				get = function(info) return db.frameypos end,
				func = function() 
				db.frameypos = db.frameypos - 1
				Rapture:frame()
				end,
			},
			},
		},
		framecolors = {
		type = "group",
		name = "Message Frame Colors",
			args = {
				framebarcolordesc = {
					order = 1,
					type = "header",
					name = "Text color\n",
					cmdHidden = true
				},
				framecolor = {
					order = 2,
					name = "Frame color",
					desc = "Set color",
					type = 'color',
					get = function(info) return db.framecolorr, db.framecolorg, db.framecolorb end,
					set = function(info, r, g, b, a)
					db.framecolorr, db.framecolorg, db.framecolorb = r, g, b
					Rapture:frame()
					end,
				},
				framecolorrgbadesc = {
					order = 3,
					type = "description",
					name = "\n\nRGB changer\n",
					cmdHidden = true
				},
				frameR = {
					order = 4,
					name = "Red",
					desc = "Set red color",
					type = 'range',
					min = 0,
					max = 1,
					step = 0.01,
					get = function(info) return db.framecolorr end,
					set = function(info, r)
					db.framecolorr = r
					Rapture:frame()
					end,
				},
				frameG = {
					order = 5,
					name = "Green",
					desc = "Set green color",
					type = 'range',
					min = 0,
					max = 1,
					step = 0.01,
					get = function(info) return db.framecolorg end,
					set = function(info, g)
					db.framecolorg = g
					Rapture:frame()
					end,
				},
				frameB = {
				order = 6,
				name = "Blue",
				desc = "Set blue color",
				type = 'range',
				min = 0,
				max = 1,
				step = 0.01,
				get = function(info) return db.framecolorb end,
				set = function(info, b)
				db.framecolorb = b
				Rapture:frame()
				end,
			},
			},
		},
		extras = {
		type = "group",
		name = "Extras",
			args = {
				sound = {
					order = 1,
					name = "Enable sound",
					desc = "Enable sound",
					type = 'toggle',
					get = function(info) return db.soundenable end,
					set = function(info, x) 
					db.soundenable = x
					Rapture:Runbar()
					end,
				},
				enableframe = {
					order = 3,
					name = "Enable message frame",
					desc = "Enable message frame",
					type = 'toggle',
					get = function(info) return db.frameenable end,
					set = function(info, x) 
					db.frameenable = x
					Rapture:frame()
					end,
				},
			},
		},
	},
}

function Rapture:OnInitialize()
	self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Ingela's Rapture", "Ingela's Rapture")
	LibStub("AceConfig-3.0"):RegisterOptionsTable("Ingela's Rapture", options, {"rapture", "rap", "Rapture", "Rap"})
	LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("Ingela's Rapture", options)
	self.db = LibStub("AceDB-3.0"):New("RaptureDB", defaults)
	db = self.db.profile
	options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
	self:RegisterChatCommand("rap", "ChatCommand")
	self:RegisterChatCommand("Rapture", "ChatCommand")
	self.db.RegisterCallback(self, "OnProfileChanged", "RefreshConfig")
	self.db.RegisterCallback(self, "OnProfileCopied", "RefreshConfig")
	self.db.RegisterCallback(self, "OnProfileReset", "RefreshConfig")
	
	local function barstopped( callback, bar )
		local candylabel = bar.candyBarLabel:GetText()
		if candylabel == db.labelinput then
			if db.soundenable == true then
				PlaySoundFile("interface\\addons\\ingelasrapture\\media\\ready.ogg", "Master")
			end
			if RaptureBAR and RaptureBAR == bar then
				RaptureBAR = nil
			end
			Rapture:frame()
		end
	end
	
	rapcandy.RegisterCallback(self, "LibCandyBar_Stop", barstopped)
	rapframe = CreateFrame("MessageFrame","Rapframe",UIParent)
end

function Rapture:OnEnable()
	self:Print("Rapture Loaded")
	self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	if not rapmedia:Fetch("statusbar", db.texture, true) then db.texture = "Blizzard" end
	if not rapmedia:Fetch("font", db.font, true) then db.font = "Friz Quadrata TT" end
end

function Rapture:RefreshConfig()
	db = self.db.profile
end

function Rapture:frame()
	rapframe:SetWidth(300)
	rapframe:SetHeight(25)
	rapframe:SetTimeVisible(db.frametime)
	rapframe:SetFadeDuration(db.fadetime)
	rapframe:SetFont(rapmedia:Fetch("font", db.framefont), db.framefontscale, db.frameoutline~="NONE" and db.frameoutline or nil)
	rapframe:SetPoint("CENTER", UIParent, "CENTER", db.framexpos, db.frameypos)
	rapframe:AddMessage(db.framelabelinput, db.framecolorr, db.framecolorg, db.framecolorb)
	rapframe:Show()
	if db.frameenable == false then
		rapframe:Hide()
	end
end

function Rapture:barset()
	RaptureBAR:Set("none", none)
	RaptureBAR:SetTexture(rapmedia:Fetch("statusbar", db.texture))
	RaptureBAR:SetWidth(db.width)
	RaptureBAR:SetHeight(db.height)
	RaptureBAR:SetScale(db.scale)
	RaptureBAR:SetPoint("CENTER", UIParent, "CENTER", db.xpos, db.ypos)
	RaptureBAR:SetColor(db.colorr, db.colorg, db.colorb, db.colora)
	RaptureBAR.candyBarLabel:SetFont(rapmedia:Fetch("font", db.font), db.fontscale, db.outline~="NONE" and db.outline or nil)
	RaptureBAR.candyBarDuration:SetFont(rapmedia:Fetch("font", db.font), db.fontscale, db.outline~="NONE" and db.outline or nil)
	RaptureBAR.candyBarBackground:SetVertexColor(db.bgcolorr, db.bgcolorg, db.bgcolorb, db.bgcolora)
	RaptureBAR.candyBarLabel:SetJustifyH(db.alignment)
	RaptureBAR:SetLabel(db.labelinput)
	local _, _, icon = GetSpellInfo(47755)
	if db.icon == true then
		RaptureBAR:SetIcon(icon)
	elseif db.icon == false then
		RaptureBAR:SetIcon(nil)
	end
end

function Rapture:Runbar()
	if rapframe then
		rapframe:SetTimeVisible(0.1)
	end
	if not RaptureBAR then
		RaptureBAR = rapcandy:New(rapmedia:Fetch("statusbar", db.texture), db.width, db.height)
		RaptureBAR:SetFill(db.fill)
	end
	Rapture:barset()
	RaptureBAR:SetDuration(12)
	RaptureBAR:Start()
end

function Rapture:SPELL_ENERGIZE(timestamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceFlags2, destGUID, destName, destFlags, dstFlags2, spellId, spellName, spellSchool, auraType, amount)
	local player_name = UnitName("player")
	if destName == player_name and sourceName == player_name and spellId == 47755 then
		Rapture:Runbar()
	end
end

function Rapture:COMBAT_LOG_EVENT_UNFILTERED(_, timestamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceFlags2, destGUID, destName, destFlags, dstFlags2, amount, spellID, ...)
	local func = self[event]
	if (func) then
		func(self, timestamp, event, hideCaster, sourceGUID, sourceName, sourceFlags, sourceFlags2, destGUID, destName, destFlags, dstFlags2, amount, spellID, ...)
	end
end

function Rapture:ChatCommand(input)
	if not input or input:trim() == "" then
		InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
	else
		LibStub("AceConfigCmd-3.0").HandleCommand(Rapture, "rap", "Rapture", input)
	end
end