local L = AceLibrary("AceLocale-2.2"):new("Incubator")
local BB = AceLibrary("Babble-Boss-2.2")
local BZ = AceLibrary("Babble-Zone-2.2")
local PC = AceLibrary("PaintChips-2.0")
local SM = AceLibrary("SharedMedia-1.0")
local dewdrop = AceLibrary("Dewdrop-2.0")
local AllowTimers = true
local InCombat = false
local INCUBATOR_OOC_THRESHOLD = 5
local RunningTimers = { }
local CurrentCombat = { }
local Killcount = { }
local LastOOC = 0
local anchor = "Incubator Anchor"
local BarCount = 0
local Lastexp = 0
local NeedTimers = 0

local IncubatorTable = {
	-- Localized name = Respawn time in seconds, minimum count to start a timer, is grouped with other mobs, localized short name
	[L["Spectral Charger"]] 		= {1500, -1,	true,		L["Spectral Charger_Short"]},		
	[L["Spectral Stallion"]]		= {1500, -1,	true,		L["Spectral Stallion_Short"]},	
	[L["Spectral Stable Hand"]]	= {1500, -1,	true,		L["Spectral Stable Hand_Short"]},	

	[L["Phantom Attendant"]] 		= {3600, -1,	false,		L["Phantom Attendant_Short"]},--*****
	[L["Phantom Guest"]] 				= {3600,  8,	false,		L["Phantom Guest_Short"]},
	[L["Phantom Valet"]] 				= {3600, -1,	false,		L["Phantom Valet_Short"]},--*****
	[L["Skeletal Waiter"]] 			= {3600, -1,	false,		L["Skeletal Waiter_Short"]},--*****

	[L["Wanton Hostess"]] 			= {3600, -1,	true,		L["Wanton Hostess_Short"]},
	[L["Concubine"]] 						= {3600, -1,	true,		L["Concubine_Short"]},
	[L["Night Mistress"]] 			= {3600, -1,	true,		L["Night Mistress_Short"]},
	[L["Phantom Guardsman"]] 		= {3600,  2,	false,		L["Phantom Guardsman_Short"]},
	[L["Spectral Sentry"]] 			= {3600,  2,	false,		L["Spectral Sentry_Short"]},

	[L["Skeletal Usher"]] 			= {3600, -1,	true,		L["Skeletal Usher_Short"]},
	[L["Phantom Stagehand"]]		= {3600, -1,	false, 	L["Phantom Stagehand_Short"]},	--*****
	[L["Spectral Performer"]]		= {3600,  2,	false,		L["Spectral Performer_Short"]},

	[BB["Romulo"]]							=	{1, 99, true, 				BB["Romulo"]},			-- Enable killcount tracking of R&J
	[BB["Julianne"]]						=	{1, 99, true,				BB["Julianne"]},		-- Killcount requirement of 99 should prevent bars from starting

	[L["Arcane Anomaly"]]				= {3600, -1,	true,		L["Arcane Anomaly_Short"]},
	[L["Syphoner"]]							= {3600,  5,	true,		L["Syphoner_Short"]},

	[L["Mana Feeder"]]					= {7200,  3,	true,		L["Mana Feeder_Short"]},
	[L["Chaotic Sentience"]]		= {7200, -1,	true,		L["Chaotic Sentience_Short"]},
	[L["Mana Warp"]]						=	{7200,  2,	true,		L["Mana Warp_Short"]},
	[L["Magical Horror"]]				=	{7200, -1,	true,		L["Magical Horror_Short"]},
	[L["Arcane Watchman"]]			= {3600,  2,	false,		L["Arcane Watchman_Short"]},
	[L["Arcane Protector"]]			=	{7200, -1,	false,		L["Arcane Protector_Short"]},--*****

	[L["Homunculus"]]						= {7200, 	2,	true,		L["Homunculus_Short"]},
	[L["Shadow Pillager"]]			= {7200, -1,	true,		L["Shadow Pillager_Short"]},

	[L["Spell Shade"]]					= {7200, -1,	true,		L["Spell Shade_Short"]},
	[L["Sorcerous Shade"]]			= {7200, -1,	true,		L["Sorcerous Shade_Short"]},
	[L["Ethereal Thief"]]				=	{7200, -1, false,		L["Ethereal Thief_Short"]},				--*****
	[L["Ethereal Spellfilcher"]]={7200, -1, false,		L["Ethereal Spellfilcher_Short"]},--*****

	[L["Fleshbeast"]]						=	{7200, 	2, false,		L["Fleshbeast_Short"]},
	[L["Greater Fleshbeast"]]		=	{7200, -1, true,			L["Greater Fleshbeast_Short"]},			--*****

	[L["Lair Brute"]]						= {3600, -1,	true,		L["Lair Brute_Short"]},
	[L["Gronn-Priest"]]					=	{3600, -1,	true,		L["Gronn-Priest_Short"]},

	[L["Hellfire Warder"]]			=	{7200, -1, true,			L["Hellfire Warder_Short"]},

	[L["Underbog Colossus"]]		=	{7200, -1, true,			L["Underbog Colossus_Short"]},			--*****
	[L["Coilfang Hate-Screamer"]]={7200, -1, true,		L["Coilfang Hate-Screamer_Short"]},	
	[L["Coilfang Beast-Tamer"]]	=	{7200, -1, true,			L["Coilfang Beast-Tamer_Short"]},		
	[L["Serpentshrine Sporebat"]]={7200, -1, true,		L["Serpentshrine Sporebat_Short"]},	

	[L["Coilfang Fathom-Witch"]]={7200, -1, true,			L["Coilfang Fathom-Witch_Short"]},	
	[L["Coilfang Priestess"]]		=	{7200, -1, true,			L["Coilfang Priestess_Short"]},			
	[L["Coilfang Serpentguard"]]={7200, -1, true,			L["Coilfang Serpentguard_Short"]}, 	
	[L["Coilfang Shatterer"]]			=	{7200, -1, true,		L["Coilfang Shatterer_Short"]}, 		

	[L["Greyheart Nether-Mage"]]={7200, -1, true,			L["Greyheart Nether-Mage_Short"]},
	[L["Greyheart Skulker"]]		=	{7200, -1, true,			L["Greyheart Skulker_Short"]},
	[L["Greyheart Tidecaller"]]	=	{7200, -1, true,			L["Greyheart Tidecaller_Short"]},
	[L["Greyheart Technician"]]	=	{7200, -1, true,			L["Greyheart Technician_Short"]},

	[L["Tidewalker Depth-Seer"]]={7200, -1, true,			L["Tidewalker Depth-Seer_Short"]},
	[L["Tidewalker Harpooner"]]={7200, -1, true,			L["Tidewalker Harpooner_Short"]},
	[L["Tidewalker Hydromancer"]]={7200, -1, true,		L["Tidewalker Hydromancer_Short"]},
	[L["Tidewalker Shaman"]]		=	{7200, -1, true,			L["Tidewalker Shaman_Short"]},
	[L["Tidewalker Warrior"]]		=	{7200, -1, true,			L["Tidewalker Warrior_Short"]},

	[L["Bloodwarder Legionnaire"]]={7200, -1, true,		L["Bloodwarder Legionnaire_Short"]},
	[L["Bloodwarder Marshal"]]		={7200, -1, true,		L["Bloodwarder Marshal_Short"]},
	[L["Bloodwarder Squire"]]		={7200, -1, true,			L["Bloodwarder Squire_Short"]},
	[L["Bloodwarder Vindicator"]]={7200, -1, true,		L["Bloodwarder Vindicator_Short"]},

	[L["Apprentice Star Scryer"]]=	{7200, -1, true,		L["Apprentice Star Scryer_Short"]},
	[L["Star Scryer"]]						=	{7200, -1, true,		L["Star Scryer_Short"]},
	[L["Novice Astromancer"]]		=	{7200, -1, true,			L["Novice Astromancer_Short"]},
	[L["Astromancer"]]						=	{7200, -1, true,		L["Astromancer_Short"]},
	[L["Nether Scryer"]]					=	{7200, -1, true,		L["Nether Scryer_Short"]},

	[L["Tempest Falconer"]]			=	{7200, -1, true,			L["Tempest Falconer_Short"]},
	[L["Phoenix-Hawk"]]					=	{7200, -1, true,			L["Phoenix-Hawk_Short"]},
	[L["Phoenix-Hawk Hatchling"]]=	{7200, -1, true,		L["Phoenix-Hawk Hatchling_Short"]},

	[L["Crystalcore Devastator"]]=	{7200, -1, true,		L["Crystalcore Devastator_Short"]},
	[L["Crystalcore Mechanic"]]	=	{7200, -1, true,			L["Crystalcore Mechanic_Short"]},
	[L["Crystalcore Sentinel"]]	=	{7200, -1, true,			L["Crystalcore Sentinel_Short"]},
	[L["Tempest-Smith"]]					=	{7200, -1, true,		L["Tempest-Smith_Short"]},

	[L["Crimson Hand Battle Mage"]] = {7200, -1, true, L["Crimson Hand Battle Mage_Short"]},
	[L["Crimson Hand Blood Knight"]] = {7200, -1, true, L["Crimson Hand Blood Knight_Short"]},
	[L["Crimson Hand Centurion"]] = {7200, -1, true, 		L["Crimson Hand Centurion_Short"]},
	[L["Crimson Hand Inquisitor"]] = {7200, -1, true, 	L["Crimson Hand Inquisitor_Short"]},
	
	[L["Aqueous Lord"]] = {7200, -1, true, L["Aqueous Lord_Short"]},
	
	[L["Coilskar General"]]	=	{7200, -1, true, L["Coilskar General_Short"]},
	[L["Coilskar Harpooner"]]	=	{7200, -1, true, L["Coilskar Harpooner_Short"]},
	[L["Coilskar Sea-Caller"]]	=	{7200, -1, true, L["Coilskar Sea-Caller_Short"]},
	[L["Coilskar Soothsayer"]]	=	{7200, -1, true, L["Coilskar Soothsayer_Short"]},
	[L["Coilskar Wrangler"]]	=	{7200, -1, true, L["Coilskar Wrangler_Short"]},
	[L["Leviathan"]] = {7200, -1, true, L["Leviathan_Short"]},
	[L["Dragon Turtle"]]			=	{7200, -1, true, L["Dragon Turtle_Short"]},

	[L["Illidari Nightlord"]] = {7200, -1, true,			L["Illidari Nightlord_Short"]},
	[L["Illidari Boneslicer"]] = {7200, -1, true, 		L["Illidari Boneslicer_Short"]},
	[L["Illidari Heartseeker"]] = {7200, -1, true, 		L["Illidari Heartseeker_Short"]},
	[L["Illidari Defiler"]] = {7200, -1, true, 				L["Illidari Defiler_Short"]},

	[L["Bonechewer Behemoth"]] = {7200, -1, true, 		L["Bonechewer Behemoth_Short"]},
	[L["Bonechewer Combatant"]] = {7200, -1, true, 		L["Bonechewer Combatant_Short"]},
	[L["Bonechewer Brawler"]] = {7200, -1, true, 			L["Bonechewer Brawler_Short"]},
	[L["Bonechewer Spectator"]] = {7200, -1, true, 		L["Bonechewer Spectator_Short"]},
	[L["Bonechewer Blood Fury"]] = {7200, -1, true,		L["Bonechewer Blood Fury_Short"]},
	[L["Mutant War Hound"]] = {7200, -1, true, 				L["Mutant War Hound_Short"]},

	[L["Temple Concubine"]] = {7200, 4, true,		L["Temple Concubine_Short"]},
	[L["Charming Courtesan"]] = {7200, 4, true,		L["Charming Courtesan_Short"]},
	[L["Spellbound Attendant"]] = {7200, -1, true, 		L["Spellbound Attendant_Short"]},
	[L["Enslaved Servant"]] = {7200, -1, true, 		L["Enslaved Servant_Short"]},
	[L["Sister of Pain"]] = {7200, -1, true, 		L["Sister of Pain_Short"]},
	[L["Sister of Pleasure"]] = {7200, -1, true,		L["Sister of Pleasure_Short"]},
	[L["Priestess of Dementia"]] = {7200, -1, true, 	L["Priestess of Dementia_Short"]},
	[L["Priestess of Delight"]] = {7200, -1, true, 		L["Priestess of Delight_Short"]},

	[L["Shadowmoon Champion"]] = {7200, -1, true, L["Shadowmoon Champion_Short"]},
	[L["Shadowmoon Houndmaster"]] = {7200, -1, true, L["Shadowmoon Houndmaster_Short"]},
	[L["Shadowmoon Riding Hound"]] = {7200, 2, true, L["Shadowmoon Riding Hound_Short"]},
	[L["Shadowmoon Grunt"]] = {7200, -1, true, L["Shadowmoon Grunt_Short"]},
	[L["Shadowmoon War Hound"]] = {7200, 2, true, L["Shadowmoon War Hound_Short"]},
	[L["Shadowmoon Reaver"]] = {7200, -1, true, L["Shadowmoon Reaver_Short"]},
	[L["Shadowmoon Blood Mage"]] = {7200, -1, true, L["Shadowmoon Blood Mage_Short"]},
	[L["Shadowmoon Deathshaper"]] = {7200, -1, true, L["Shadowmoon Deathshaper_Short"]},
	[L["Shadowmoon Soldier"]] = {7200, -1, true, L["Shadowmoon Soldier_Short"]},
	[L["Shadowmoon Weapon Master"]] = {7200, -1, true, L["Shadowmoon Weapon Master_Short"]},
	[L["Shadowmoon Fallen"]] = {7200, -1, true, L["Shadowmoon Fallen_Short"]},
	[L["Wrathbone Flayer"]] = {7200, -1, true, L["Wrathbone Flayer_Short"]},
	[L["Hand of Gorefiend"]] = {7200, -1, true, L["Hand of Gorefiend_Short"]},

--	[L["Elder Mottled Boar"]]		=	{600, -1, true,			L["Debug Respawn"]},
	[L["Promenade Sentinel"]] = {7200, -1, true, 		L["Promenade Sentinel_Short"]},
	[L["Illidari Blood Lord"]] = {7200, 2, true, 		L["Illidari Blood Lord_Short"]},
}

local IncubatorHeroicTable = {
	[L["Durnholde Lookout"]]		=	{600,		-1,	true,		L["Durnholde Lookout_Short"]},
	[L["Durnholde Tracking Hound"]]	=	{600,	-1, true, 	L["Durnholde Tracking Hound_Short"]},
}

local IncubatorBossShutoff = {
	-- Table of which spawn timers a boss kill should shut off. This prevents the mob from being tracked for the remainder of the current session.
	--See Incubator:Bossdeath
	--Localized Boss Name = "remove" or "reset", mob1, mob2, mob3, etc
	[BB["Attumen the Huntsman"]]	=	{"remove",	L["Spectral Charger"], L["Spectral Stallion"], L["Spectral Stable Hand"]},
	[BB["Moroes"]]								=	{"remove",	L["Phantom Attendant"], L["Phantom Guest"], L["Phantom Valet"], L["Skeletal Waiter"]},
	[BB["Maiden of Virtue"]]			=	{"remove",	L["Wanton Hostess"], L["Concubine"], L["Night Mistress"], L["Phantom Guardsman"], L["Spectral Sentry"]},
	[BB["Romulo"]]								=	{"remove",	L["Skeletal Usher"], L["Phantom Stagehand"], L["Spectral Performer"]},
	[BB["Julianne"]]							=	{"remove",	L["Skeletal Usher"], L["Phantom Stagehand"], L["Spectral Performer"]},
	[BB["The Big Bad Wolf"]]			=	{"remove",	L["Skeletal Usher"], L["Phantom Stagehand"], L["Spectral Performer"]},
	[BB["The Crone"]]							=	{"remove",	L["Skeletal Usher"], L["Phantom Stagehand"], L["Spectral Performer"]},
	[BB["The Curator"]]						=	{"remove",	L["Arcane Anomaly"], L["Syphoner"], L["Arcane Watchman"]},
	[BB["Shade of Aran"]]					=	{"remove",	L["Mana Feeder"], L["Arcane Watchman"], L["Arcane Protector"], L["Chaotic Sentience"], L["Mana Warp"], L["Magical Horror"], L["Spell Shade"]},
	[BB["Terestian Illhoof"]]			= {"remove",	L["Homunculus"], L["Shadow Pillager"]},
	[BB["Netherspite"]]						=	{"remove",	L["Spell Shade"], L["Sorcerous Shade"], L["Ethereal Thief"], L["Ethereal Spellfilcher"]},
	[BB["Prince Malchezaar"]]			= {"remove",	L["Fleshbeast"], L["Greater Fleshbeast"]},
	[BB["High King Maulgar"]]			= {"reset",		L["Lair Brute"], L["Gronn-Priest"]},
	[BB["Gruul the Dragonkiller"]]={"remove",	L["Lair Brute"], L["Gronn-Priest"]},
	[BB["Magtheridon"]]						=	{"remove",	L["Hellfire Warder"]},
	[BB["Hydross the Unstable"]]	=	{"reset",		L["Coilfang Hate-Screamer"], L["Coilfang Beast-Tamer"], L["Serpentshrine Sporebat"], L["Underbog Colossus"]},
	[BB["Morogrim Tidewalker"]]		=	{"remove",	L["Tidewalker Depth-Seer"], L["Tidewalker Harpooner"], L["Tidewalker Hydromancer"], L["Tidewalker Shaman"], L["Tidewalker Warrior"]},
	[BB["The Lurker Below"]]			=	{"reset",		L["Coilfang Shatterer"], L["Coilfang Priestess"]},
	[BB["Fathom-Lord Karathress"]]={"reset",		L["Underbog Colossus"]},
	[BB["Leotheras the Blind"]]		=	{"reset",		L["Greyheart Tidecaller"], L["Greyheart Nether-Mage"], L["Greyheart Skulker"]},
	[BB["Void Reaver"]]						=	{"reset",		L["Tempest-Smith"], L["Crystalcore Devastator"], L["Crystalcore Sentinel"], L["Crystalcore Mechanic"]},
	[BB["High Astromancer Solarian"]]={"reset",L["Apprentice Star Scryer"], L["Bloodwarder Squire"], L["Nether Scryer"], L["Crystalcore Sentinel"], L["Bloodwarder Legionnaire"]},
	[BB["Al'ar"]] = {"reset",		L["Bloodwarder Vindicator"], L["Bloodwarder Squire"], L["Tempest Falconer"], L["Phoenix-Hawk"], L["Phoenix-Hawk Hatchling"], L["Bloodwarder Marshal"]},
	[BB["Kael'thas Sunstrider"]] = {"reset", L["Crimson Hand Blood Knight"], L["Crimson Hand Centurion"], L["Crimson Hand Inquisitor"], L["Bloodwarder Marshal"], L["Crimson Hand Battle Mage"]},
	[BB["High Warlord Naj'entus"]] = {"reset", L["Aqueous Lord"], L["Coilskar General"], L["Coilskar Harpooner"], L["Coilskar Sea-Caller"], L["Coilskar Soothsayer"], L["Coilskar Wrangler"], L["Dragon Turtle"]},
	[BB["Shade of Akama"]] = {"remove", L["Illidari Nightlord"], L["Illidari Boneslicer"], L["Illidari Heartseeker"], L["Illidari Defiler"]},
	[BB["Mother Shahraz"]] = {"reset", L["Temple Concubine"], L["Charming Courtesan"], L["Spellbound Attendant"], L["Enslaved Servant"], L["Sister of Pain"], L["Sister of Pleasure"], L["Priestess of Dementia"], L["Priestess of Delight"]},
	[BB["Teron Gorefiend"]] = {"remove", L["Shadowmoon Champion"], L["Shadowmoon Houndmaster"], L["Shadowmoon Riding Hound"], L["Shadowmoon Grunt"], L["Shadowmoon War Hound"], L["Shadowmoon Reaver"], L["Shadowmoon Blood Mage"], L["Shadowmoon Deathshaper"], L["Shadowmoon Soldier"], L["Shadowmoon Weapon Master"], L["Shadowmoon Fallen"], L["Wrathbone Flayer"], L["Hand of Gorefiend"]},
	[BB["Gurtogg Bloodboil"]] = {"remove", L["Bonechewer Behemoth"], L["Bonechewer Combatant"], L["Bonechewer Brawler"], L["Bonechewer Spectator"], L["Bonechewer Blood Fury"], L["Mutant War Hound"]},
	[BB["Gathios the Shatterer"]] = {"reset", L["Promenade Sentinel"], L["Illidari Blood Lord"]},
}

local IncubatorZoneList = {
	BZ["Karazhan"],
	BZ["Black Temple"],
	BZ["Gruul's Lair"],
	BZ["Magtheridon's Lair"],
	BZ["Old Hillsbrad Foothills"],
	BZ["Serpentshrine Cavern"],
	BZ["Tempest Keep"],
--	BZ["Durotar"],
}

local options = {
	type = 'group',
	args = {
		list = {
			type = 'execute',
			name = L["List running timers"],
			desc = L["Output all active timers to chat"],
			func = function()
				Incubator:ConsoleRunning()
			end,
		},
		clearall = {
			type = 'execute',
			name = L["Clear all running timers"],
			desc = L["Clears all running timers and bars"],
			func = function()
				Incubator:ClearAll()
			end,
		},
		maxshowtime = {
			type = 'range',
			name = L["Maximum time in minutes"],
			desc = L["Set the maximum time for a respawn bar to show"],
			get = function()
				return Incubator.db.profile.maxshowtime
			end,
			set = function(v)
				Incubator.db.profile.maxshowtime = v
			end,
			min = 0,
			max = 120,
			step = 1,
		},
		barcount = {
			type = 'range',
			name = L["Bar count"],
			desc = L["Maximum number of bars to show at one time"],
			get = function()
				return Incubator.db.profile.barcount
			end,
			set = function(v)
				Incubator.db.profile.barcount = v
			end,
			min = 0,
			max = 25,
			step = 1,
		},
		timebetween = {
			type = 'range',
			name = L["Time between bars"],
			desc = L["Only show bars that are further apart then this in minutes"],
			get = function()
				return Incubator.db.profile.timebetween
			end,
			set = function(v)
				Incubator.db.profile.timebetween = v
			end,
			min = 0,
			max = 30,
			step = 1,
		},
		developer = {
			type = 'toggle',
			name = L["Developer"],
			desc = L["Outputs debug information to chat"],
			get = function()
				return Incubator.db.profile.developer
			end,
			set = function(v)
				Incubator.db.profile.developer = v
			end,
			map = { [false] = L["Disabled"], [true] = L["Enabled"] },
		},
		baroptions = {
			type = 'group',
			desc = 'bar options',
			name = L["Bar Options"],
			args = {
				enablemouse = {
					type = 'toggle',
					name = L["Enable Mouse"],
					desc = L["Enable mouse interaction on bars"],
					get = function()
						return Incubator.db.profile.baroptions.enablemouse
					end,
					set = function(v)
						Incubator.db.profile.baroptions.enablemouse = v
					end,
					map = { [false] = L["Disabled"], [true] = L["Enabled"] },
				},
				locked = {
					type = 'toggle',
					name = L["Locked"],
					desc = L["Lock the bars, preventing dragging"],
					get = function()
						return Incubator.db.profile.baroptions.locked
					end,
					set = function(v)
						Incubator.db.profile.baroptions.locked = v
						Incubator:ToggleLock()
					end,
					map = { [false] = L["Disabled"], [true] = L["Enabled"] },
				},
				growup = {
					type = 'toggle',
					name = L["Grow up"],
					desc = L["Grow bars upward from the anchor"],
					get = function()
						return Incubator.db.profile.baroptions.growup
					end,
					set = function(v)
						Incubator.db.profile.baroptions.growup = v
						Incubator:SetCandyBarGroupGrowth(anchor, v)
					end,
					map = { [false] = L["False"], [true] = L["True"] },
				},
				texture = {
						type = "text",
						name = L["Texture"],
						desc = L["Incubator bar texture"],
						get = function() 
							return Incubator.db.profile.baroptions.texture 
						end,
						set = function(v)
							Incubator.db.profile.baroptions.texture = v
						end,
						validate = SM:List("statusbar"),
				},
				barwidth = {
					type = 'range',
					name = L["Bar width"],
					desc = L["Width of Incubator bars"],
					get = function()
						return Incubator.db.profile.baroptions.width
					end,
					set = function(v)
						Incubator.db.profile.baroptions.width = v
					end,
					min = 24,
					max = 512,
					step = 8,
				},
				barheight = {
					type = 'range',
					name = L["Bar height"],
					desc = L["Width of Incubator bars"],
					get = function()
						return Incubator.db.profile.baroptions.height
					end,
					set = function(v)
						Incubator.db.profile.baroptions.height = v
					end,
					min = 6,
					max = 64,
					step = 2,
				},
				barscale = {
					type = 'range',
					name = L["Bar scale"],
					desc = L["Scale of Incubator bars"],
					get = function()
						return Incubator.db.profile.baroptions.scale
					end,
					set = function(v)
						Incubator.db.profile.baroptions.scale = v
					end,
					min = 0.5,
					max = 1.5,
					step = 0.1,
				},
			},
		},
	},
}

Incubator = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0", "CandyBar-2.0")
Incubator:RegisterChatCommand(L["Slash-Commands"], options)
Incubator:RegisterDB("IncubatorDB", "IncubatorDBPC")
Incubator:RegisterDefaults("profile", {
	maxshowtime = 60,
	barcount = 10,
	timebetween = 0,
	developer = false,
	
	x = 0,
	y = 0,
	relpoint = "CENTER",
	point = "CENTER",
	["baroptions"] = {
		["enablemouse"] = true,
		["locked"] = false,
		["growup"] = false,
		["colors"] = { "blue", "green", "red", },
		["width"] = 128,
		["height"] = 16,
		["scale"] = 1.0,
		["texture"] = "BantoBar",
	},
} )

function Incubator:CreateAnchor()
	self.anchor = CreateFrame("Frame",anchor..tostring(math.floor(GetTime())),UIParent)
	self.anchor:ClearAllPoints();
	self.anchor:SetBackdrop( {
		bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
		edgeFile="Interface\\Tooltips\\UI-Tooltip-Border",
		tile = true, tileSize = 16, edgeSize = 16, insets = {
			left = 5, right = 5, top = 5, bottom = 5 },
	} );
	self.anchor:SetWidth(128)
	self.anchor:SetHeight(30)
	self.anchor:SetBackdropColor(0.1,0.1,0.3)
	self.anchor:EnableMouse(Incubator.db.profile.baroptions.enablemouse)
	self.anchor:SetPoint(Incubator.db.profile.point, "UIParent", Incubator.db.profile.relpoint, Incubator.db.profile.x, Incubator.db.profile.y)
	local msg = self.anchor:CreateFontString(nil,"overlay","GameFontNormal")
	msg:ClearAllPoints()
	msg:SetPoint("CENTER", self.anchor, "CENTER")
	msg:SetText(anchor)
	self.anchor:SetMovable(true)
	self.anchor:SetScript("OnDragStart", function() self.anchor:StartMoving(); GameTooltip:Hide() end)
	self.anchor:SetScript("OnDragStop", function() self.anchor:StopMovingOrSizing(); self:SavePosition() end)
	self.anchor:SetScript("OnMouseUp", function() self:OnAnchorClick() end)
	self.anchor:SetScript("OnEnter", function() self:ShowAnchorTooltip() end)
	self.anchor:SetScript("OnLeave", function() GameTooltip:Hide() end)
	self.anchor:RegisterForDrag("LeftButton")
	if self.db.profile.baroptions.locked then
		self.anchor:Hide()
	else
		self.anchor:Show()
	end
	self:RegisterCandyBarGroup(anchor)
	self:SetCandyBarGroupPoint(anchor, "TOP", self.anchor:GetName(), "BOTTOM", 0, 0)
	self:SetCandyBarGroupGrowth(anchor, self.db.profile.baroptions.growup)
end

	
function Incubator:LockAnchor()
	self.db.profile.baroptions.locked = true
	self.anchor:Hide()
end

function Incubator:UnlockAnchor()
	self.db.profile.baroptions.locked = false
	self.anchor:Show()
end

function Incubator:ToggleLock()
	if self.db.profile.baroptions.locked then
		self.anchor:Hide()
	else
		self.anchor:Show()
	end
end

function Incubator:ShowAnchorTooltip()
	GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT")
	GameTooltip:AddLine(L["Incubator Anchor"])
	GameTooltip:AddLine(L["Drag this to reposition Incubator bars"])
	GameTooltip:AddLine(L["Alt+Left Click will display or hide a test bar"])
	GameTooltip:AddLine(L["Shift+Left Click will lock and hide the anchor"])
	GameTooltip:Show()
end

function Incubator:OnAnchorClick()
	if IsAltKeyDown() then
		if self:IsCandyBarRegistered("Incubator Testbar") then
			self:StopCandyBar("Incubator Testbar")
			return;
		end
		self:RegisterCandyBar("Incubator Testbar", 300, "Test bar", nil, unpack(self.db.profile.baroptions.colors) )
		self:RegisterCandyBarWithGroup("Incubator Testbar", anchor)
		self:SetCandyBarTexture("Incubator Testbar", SM:Fetch("statusbar", self.db.profile.baroptions.texture))
		self:SetCandyBarWidth("Incubator Testbar", self.db.profile.baroptions.width)
		self:SetCandyBarHeight("Incubator Testbar", self.db.profile.baroptions.height)
		self:SetCandyBarScale("Incubator Testbar", self.db.profile.baroptions.scale)
		self:StartCandyBar("Incubator Testbar", true)
	end
	if IsShiftKeyDown() then
		if self:IsCandyBarRegistered("Incubator Testbar") then
			self:StopCandyBar("Incubator Testbar")
			return;
		end
		self:LockAnchor()
	end
end

function Incubator:SavePosition()
	self.db.profile.point, _, self.db.profile.relpoint, self.db.profile.x, self.db.profile.y = self.anchor:GetPoint()
end

function Incubator:OnEnable()
	self:RegisterEvent("CHAT_MSG_COMBAT_HOSTILE_DEATH")
	self:RegisterEvent("PLAYER_REGEN_DISABLED")
	self:RegisterEvent("PLAYER_REGEN_ENABLED")
	self:RegisterEvent("PLAYER_ENTERING_WORLD")
	
	self:ScheduleRepeatingEvent("IncubatorPeriodicHandler", self.PeriodicHandler, 1, self )
	
	SM:Register("statusbar", "Blizzard", "Interface\\TargetingFrame\\UI-StatusBar")
	SM:Register("statusbar", "BantoBar", "Interface\\AddOns\\Incubator\\textures\\bantobar.tga")
	SM:Register("statusbar", "Charcoal", "Interface\\AddOns\\Incubator\\textures\\charcoal.tga")
	SM:Register("statusbar", "Otravi", "Interface\\AddOns\\Incubator\\textures\\otravi.tga")
	SM:Register("statusbar", "Perl", "Interface\\AddOns\\Incubator\\textures\\perl.tga")
	SM:Register("statusbar", "Smooth", "Interface\\AddOns\\Incubator\\textures\\smooth.tga")
	SM:Register("statusbar", "Smudge", "Interface\\AddOns\\Incubator\\textures\\smudge.tga")
	SM:Register("statusbar", "Striped", "Interface\\AddOns\\Incubator\\textures\\striped.tga")
	
	self:CreateAnchor()
end

function Incubator:PLAYER_ENTERING_WORLD()
	-- reset existing timers, etc
end

function Incubator:CHAT_MSG_COMBAT_HOSTILE_DEATH(msg)
	-- increment a death counter and start timers if needed
	if self:InTrackedZone() then
		for key, table in pairs(IncubatorTable) do
			if msg == string.format(UNITDIESOTHER, key) then
			-- The thing that died is on our list of stuff that can be tracked.
				if IncubatorTable[key][2] == -1 and IncubatorTable[key][3] == false then -- The thing that died is tracked as a solo mob
					self:StartTimer(IncubatorTable[key][4], IncubatorTable[key][1] + GetTime())
				else
					NeedTimers = 1
					CurrentCombat[key] = 1
					if Killcount[key] == nil then
						Killcount[key] = 1
					else
						Killcount[key] = Killcount[key] + 1
					end
					if self.db.profile.developer == true then
						self:Print(key, "found on list to be tracked.", Killcount[key], "this combat.")
					end
				end
			end
		end
		
		for key, value in pairs(IncubatorBossShutoff) do
			if msg == string.format(UNITDIESOTHER, key) then
			-- A boss died, so kill all the timers associated with that boss.
				self:BossDeath(key)
			end
		end
	end
end


function Incubator:PLAYER_REGEN_DISABLED()
	InCombat = true
	LastOOC = 0
	self:StopOOCHandler()
end

function Incubator:StopOOCHandler()
	self:CancelScheduledEvent("IncubatorOOCHandler")
end

function Incubator:StartOOCHandler()
	if not self:IsEventScheduled("IncubatorOOCHandler") then
		self:ScheduleRepeatingEvent("IncubatorOOCHandler", self.OOCHandler, 1, self )
	end
end

function Incubator:InTrackedZone()
	local currentzone = GetRealZoneText()
	for n, zone in pairs(IncubatorZoneList) do
		if zone == currentzone then
			return true
		end
	end
	return false
end

function Incubator:BossDeath(BossName)
	if BossName == BB["Romulo"] or BossName == BB["Julianne"] then
		if Killcount["Julianne"] ~= 2 or Killcount["Romulo"] ~= 2 then
			return
		end
	end
	for tindex, mobname in pairs(IncubatorBossShutoff[BossName]) do
		if mobname ~= "reset" and mobname ~= "remove" then
			for timername, timerlist in pairs (RunningTimers) do
				if string.find(timername, IncubatorTable[mobname][4]) == 1 then
					if RunningTimers[timername][3] == false then-- candybar was started on this one
						self:StopCandyBar("Incubator-"..timername)
						BarCount = BarCount - 1
					end
					RunningTimers[timername][1] = nil
					RunningTimers[timername][2] = nil
					RunningTimers[timername][3] = nil
					RunningTimers[timername] = nil
				end
			end
			if IncubatorBossShutoff[BossName][1] == "remove" then
				IncubatorTable[mobname] = nil -- Prevent new bars from being started on this mob
			end
		end
	end
	
	if BossName == BB["The Curator"] then
		IncubatorTable[L["Arcane Watchman"]] = {7200, 2, false, L["Arcane Watchman_Short"]}
	end
	
	if BossName == BB["Shade of Aran"] then
		IncubatorTable[L["Spell Shade"]] = {7200, -1, true, L["Spell Shade_Short"]}
	end
end

function Incubator:PLAYER_REGEN_ENABLED()
		LastOOC = GetTime()
		if self.db.profile.developer == true then
			self:Print("Starting OOC checking")
		end
		if self:InTrackedZone() and NeedTimers == 1 then
			self:StartOOCHandler()
		end
end

function Incubator:StartTimer(name, duration)
	local counter = 1
	local expiration = duration + LastOOC
	local title = name .. tostring(counter)

	while RunningTimers[title] ~= nil do
		counter = counter + 1
		title = name .. tostring(counter)
	end
	
	
	RunningTimers[title] = { expiration, true, true }
	if self.db.profile.developer == true then
		self:Print("Starting timer named", title, (SecondsToTime(duration)))
	end
end

function Incubator:TimerHandler()
	-- handles all the timers that need to be started and clearing out the current combat list
	if self.db.profile.developer == true then
		self:Print("Processing Timers")
	end
	local StartedNonHomogeneous = false -- Flag to indicate that we already started a timer on a pack
	InCombat = false
	for key, value in pairs(CurrentCombat) do
		if Killcount[key] ~= nil and IncubatorTable[key] ~= nil then
			if value == 1 then
				if Killcount[key] >= IncubatorTable[key][2] then
					if IncubatorTable[key][3] == true and StartedNonHomogeneous == false then
						StartedNonHomogeneous = true
						-- Start a timer on this particular mob. We only want to start the timer on this one instead of 2+ mobs with the same timer.
						self:StartTimer(IncubatorTable[key][4], IncubatorTable[key][1])
					end
					if IncubatorTable[key][3] == false then
					-- Start a timer on that mob, enough of them died. These are solo so we don't care about other deaths.
						self:StartTimer(IncubatorTable[key][4], IncubatorTable[key][1])
					end
					Killcount[key] = nil
				else
					if self.db.profile.developer == true then
						self:Print("Discarding info on", key, "(Got", Killcount[key], "needed", IncubatorTable[key][2], ")")
					end
					Killcount[key] = nil
				end
			end
		end
		CurrentCombat[key] = nil
	end
	NeedTImers = 0
end

function Incubator:PeriodicHandler()
	local threshold = self.db.profile.barcount
	if threshold == 0 then
		threshold = 999
	end
	local showthreshold = self.db.profile.maxshowtime
	if showthreshold == 0 then
		showthreshold = 999
	end
	for key, value in pairs(RunningTimers) do
		--[[ RunningTimers format is 
			RunningTimers[Timername]
				[1] = expiration time
				[2] = Warning needs to be given
				[3] = Bar needs to be started
		]]--
		if GetTime() + 600 > RunningTimers[key][1] and RunningTimers[key][2] and self.db.profile.developer then
			local remaining = floor(RunningTimers[key][1] - GetTime())
			self:Print(key, "respawns in", remaining)
			RunningTimers[key][2] = false
		end
		
		if GetTime() + (60 * showthreshold) > RunningTimers[key][1] and RunningTimers[key][3] and BarCount < threshold and (RunningTimers[key][1] - Lastexp) > (self.db.profile.timebetween * 60) then
			self:RegisterCandyBar("Incubator-"..key, floor(RunningTimers[key][1] - GetTime()), key, nil, unpack(self.db.profile.baroptions.colors))
			self:RegisterCandyBarWithGroup("Incubator-"..key, anchor)
			self:SetCandyBarTexture("Incubator-"..key, SM:Fetch("statusbar", Incubator.db.profile.baroptions.texture))
			self:SetCandyBarWidth("Incubator-"..key, Incubator.db.profile.baroptions.width)
			self:SetCandyBarHeight("Incubator-"..key, Incubator.db.profile.baroptions.height)
			self:SetCandyBarScale("Incubator-"..key, Incubator.db.profile.baroptions.scale)
			self:SetCandyBarOnClick("Incubator-"..key, function()
				self:OnBarClick(key)
			end)
			self:StartCandyBar("Incubator-"..key, true)
			RunningTimers[key][3] = false
			if self.db.profile.developer then
				self:Print(key, "is being flagged as starting a timer")
			end
			BarCount = BarCount + 1
			Lastexp = RunningTimers[key][1]
		end
		
		if GetTime() > RunningTimers[key][1] then
			if RunningTimers[key][1] == Lastexp then
				Lastexp = 0
			end
		RunningTimers[key][1] = nil
		RunningTimers[key][2] = nil
		RunningTimers[key][3] = nil
		RunningTimers[key] = nil
		BarCount = BarCount - 1
		end
	end
end

function Incubator:ConsoleRunning()
	for key, value in pairs(RunningTimers) do
		self:Print(key, (SecondsToTime(floor(RunningTimers[key][1] - GetTime()))))
	end
end

function Incubator:OnBarClick(name)
	if self.db.profile.developer then
		self:Print("Caught mouseclick on", name)
	end
	if IsControlKeyDown() then
		if UnitInRaid("player") == nil then
			SendChatMessage(name .. ": " .. SecondsToTime(floor(RunningTimers[name][1] - GetTime())), "PARTY")
		else
			SendChatMessage(name .. ": " .. SecondsToTime(floor(RunningTimers[name][1] - GetTime())), "RAID")
		end
	end
	if IsShiftKeyDown() then
		self:Print("Clearing timer", name)
		if RunningTimers[name][1] == Lastexp then
			Lastexp = 0
		end
		RunningTimers[name][1] = nil
		RunningTimers[name][2] = nil
		RunningTimers[name][3] = nil
		RunningTimers[name] = nil
		BarCount = BarCount - 1

		self:StopCandyBar("Incubator-"..name)

	end
end

function Incubator:InCombat()
	if UnitAffectingCombat("player") == nil then
		if UnitInRaid("player") == nil then
			local n = GetNumPartyMembers()
			if n == 0 then
				return false
			else
				for i = 1, n do
					if UnitAffectingCombat("party" .. i) == 1 then
						return true
					end
				end
				return false
			end
		else
			local n = GetNumRaidMembers()
			for i = 1, n do
				if UnitAffectingCombat("raid" .. i) == 1 then
					return true
				end
			end
			return false
		end
	else
		return true
	end
end

function Incubator:IsRaidAlive()
	local count = 0
	if UnitInRaid("player") == nil then
		local n = GetNumPartyMembers()
		if UnitIsDeadOrGhost("player") == true then
			count = count + 1
		end
		if n ~= 0 then
			for i = 1, n do
				if UnitIsDeadOrGhost("party" .. i) == true or UnitIsConnected("party" .. i) ~= 1 then
					count = count + 1
				end
			end
		end
		if count == n + 1 then
			return false -- everyone is dead!
		else
			return true
		end
	else
		local n = GetNumRaidMembers()
		for i = 1, n do
			if UnitIsDeadOrGhost("raid" .. i) == true or UnitIsConnected("raid" .. i) ~= 1 then
				count = count + 1
			end
		end
		if count == n then
			return false
		else
			return true
		end
	end
end

function Incubator:OOCHandler()
	if not self:InTrackedZone() then -- Releasing is a no-go, as many functions do not return properly
		self:StopOOCHandler()
		self:EmptyCombatList()
	end
	if not self:IsRaidAlive() then -- Boo wiping! Try harder!
		self:Print("Wipe detected, stopping processing")
		self:StopOOCHandler()
		self:EmptyCombatList()
	end
	if not Incubator:InCombat() and Incubator:IsRaidAlive() then
		if self.db.profile.developer then
			self:Print("The party/raid appears to be OOC")
		end
		LastOOC = GetTime()
		self:StopOOCHandler()
		self:TimerHandler()
	end
end

function Incubator:EmptyCombatList()
	if self.db.profile.developer then
		self:Print("Emptying Combat List")
	end
	for key, value in pairs(CurrentCombat) do
		CurrentCombat[key] = nil
	end
	for key, value in pairs(Killcount) do
		Killcount[key] = nil
	end
	NeedTimers = 0
end

function Incubator:ClearAll()
	for timername, timerlist in pairs (RunningTimers) do
				if RunningTimers[timername][3] == false then-- candybar was started on this one
					self:StopCandyBar("Incubator-"..timername)
					BarCount = BarCount - 1
				end
				RunningTimers[timername][1] = nil
				RunningTimers[timername][2] = nil
				RunningTimers[timername][3] = nil
				RunningTimers[timername] = nil
		end
end
