-- ----------------------------------------------------------------------------
fireFlies = {}
fireFlies.flies = {}
fireFlies.activeFlies = {}
fireFlies.activeLayouts = {}
fireFlies.currentActiveCount = 0
fireFlies.wantedActiveCount = 3
fireFlies.seen = {}
-- ----------------------------------------------------------------------------
function fireFlies:dumpFlies()

	local text = "--- active fireflies ----------------------\n"
	for object, b in pairs(self.activeFlies) do
		text = text .. object:name() .. " (" .. object:getLayout():name() .. ") (" .. object:getState() .. ")"
		if (object:isVisible()) then
			text = text .. " (visible)"
		else
			text = text .. " (hidden)"
		end
		text = text .. "\n"
	end
	
	if (isDebug()) then
		print(text)
	else
		messageBox(text)
	end

end
-- ----------------------------------------------------------------------------
function fireFlies:reset()

	self.flies = {}
	self.activeFlies = {}
	self.activeLayouts = {}
	self.currentActiveCount = 0
	self.seen = {}

end
-- ----------------------------------------------------------------------------
function fireFlies:activateFly(object)

	assert(object)
	assert(object:isFirefly())

	if (self.flies[object]) then
		if (not self.activeFlies[object]) then
			-- activate it
			object:ss(kActive)
			-- add it to active flies
			self.activeFlies[object] = true
			-- add it to active layouts
			self.activeLayouts[object:getLayout()] = true
			-- increase the used count of the fly
			self.flies[object].used = self.flies[object].used + 1
			-- increase the active count
			self.currentActiveCount = self.currentActiveCount + 1
			-- info
			print("(firefly) actived fly " .. object:name() .. " in " .. object:getLayout():name())
		end
	end

end
-- ----------------------------------------------------------------------------
function fireFlies:deactivateFly(object)

	assert(object)
	assert(object:isFirefly())
	
	if (self.flies[object]) then	
		if (self.activeFlies[object]) then
			-- decrease the active count
			self.currentActiveCount = self.currentActiveCount - 1		
			-- increase the found count
			self.flies[object].found = self.flies[object].found + 1
			-- remove it from the active flies
			self.activeFlies[object] = nil
			-- remove it from the active layouts
			self.activeLayouts[object:getLayout()] = nil
			-- deactivate it
			object:ss(kUsed)
		end
	end

end
-- ----------------------------------------------------------------------------
function fireFlies:onLayoutShow(layout)

	assert(layout)
	assert(layout.type == kLayout)
	
	if (layout:shouldPlaceFireflies()) then
		if (self.seen[layout]) then
			-- already saw this layout and imported its flies
		else
			-- first time we see this one, let's import its flies
			if (layout.mFireflies) then
				for object, props in pairs(layout.mFireflies) do
					-- store object
					self.flies[object] = { found = 0, used = 0 }
				end
			end
			self.seen[layout] = true
			-- info
			print("(firefly) added layout: " .. layout:name())
		end
		
		self:update()
	end

end
-- ----------------------------------------------------------------------------
function fireFlies:onLayoutHide(layout)

	assert(layout)
	assert(layout.type == kLayout)	

end
-- ----------------------------------------------------------------------------
function fireFlies:onClickFirefly(layout, object, props, x, y)

	assert(layout)
	assert(layout.type == kLayout)	
	assert(object)
	assert(object.type == kObject)
	assert(self.flies[object])
	assert(self.flies[object].found)
	assert(self.flies[object].used)
	
	self:deactivateFly(object)
	self:update(layout)

end
-- ----------------------------------------------------------------------------
function fireFlies:update(excludeLayout)

	if (isLoading()) then
		return
	end

	local currentLayout = layoutStack[#layoutStack]

	-- let's see if we want to make a fly active
	while (self.currentActiveCount < self.wantedActiveCount) do
		-- find flies that are options
		local possibilities = {}
		local minUsed = math.huge
		for object, props in pairs(self.flies) do
			-- cannot be active yet
			if (not self.activeFlies[object]) then
				-- cannot have active layout yet
				if (not self.activeLayouts[object:getLayout()]) then
					-- cannot be in the exclude layout
					if (excludeLayout ~= currentLayout) or (excludeLayout == nil) then
						-- cannot be done
						if (not object:isDone()) then
							-- choose lowest used count only
							if (props.used < minUsed) then
								possibilities = {}
								minUsed = props.used
							end
							if (props.used <= minUsed) then
								table.insert(possibilities, object)
							end
						end
					end
				end
			end
		end
		
		if (#possibilities > 0) then
		
			local index  = math.random(#possibilities)
			assert(index > 0)
			assert(index <= #possibilities)
			local object = possibilities[index]
			assert(object)
			
			self:activateFly(object)
			
		else
			-- stop prematurely
			-- wantedActiveCount not reached!
			break		
		end
	end
	
	if (canFindHint()) then
		for object, b in pairs(self.activeFlies) do
			object:ss(kActive)
		end
	else
		for object, b in pairs(self.activeFlies) do
			object:ss(kInactive)
		end	
	end	

end
-- ----------------------------------------------------------------------------