s12_fire_cockroach_minigame = {} -- огненные тараканы http://wiki/ProjectS12/miniigry/fire?v=3f4
local self = s12_fire_cockroach_minigame 

self.params = {
	max_life = 5000, -- максимальное время жизни объекта
	min_life = 3000, -- минимальное время жизни объекта
	max_interval = 600, -- максимальный промежуток между появлениями объектов
	min_interval = 300, -- минимальный промежуток между появлениями объектов
	max_objects = 30, -- максимальное количество объектов на сцене
	
	progress_positions = 1000, -- сколько делений у прогрессбара
	progress_init = 500, -- в каком положении прогрессбар в начале
 	progress_update = 3, -- на сколько увеличивается прогрессбар при апдейте
	progress_update_time = 400, -- обновляется раз в милисекунды
	progress_click = 25, -- на сколько уменьшается при верном клике
	
	need_objects = 30, --количество объектов необходимое собрать за установленное время 
	sound_luck = "fire_02", -- звук при тушении пламени
	sound_click = "rub_stone_chemical", -- звук клика
	obj_clip = "minigame_fire", -- название id-шника  с клипом огня
	luck_clip = "minigame_smoke", -- id-шник с клипом затухающего огня
	click_clip = "minigame_extinguisher", -- пена от огнетушителя при обычном клике
	right_click = "minigame_foam", -- эффект для правильного клика
	pos_size = sf.misc.FloatVector(70, 30), -- размеры позиции
	cursor = "scenes_chapter01_scene02_scene03_cursor_extinguisher", -- курсор 
	positions = { -- возможные координаты появления пламени (указывается центр позиции)
		{ X = 410, Y = 610 }, -- 1
		{ X = 155, Y = 576 },--2 
		{ X = 627, Y = 521 },-- 3 
		{ X = 310, Y = 527 },-- 4 
		{ X = 275, Y = 482 },-- 5 
		{ X = 715, Y = 238 },-- 6 
		{ X = 976, Y = 309 },--7 
		{ X = 835, Y = 225 },-- 8 
		{ X = 301, Y = 182 }, -- 9 
		{ X = 842, Y = 364 },-- 10 
		{ X = 199, Y = 390 },-- 11 
		{ X = 300, Y = 394 },--12 
		{ X = 779, Y = 309 },-- 13 
		{ X = 957, Y = 233 },-- 14 
		{ X = 262, Y = 267 },-- 15 
		{ X = 784, Y = 306 },-- 16 
		{ X = 390, Y = 488 },--17 
		{ X = 723, Y = 357 }, -- 18 
		{ X = 134, Y = 431 } -- 19
	}
}

function self.Init(_owner) -- функция, инициализирующая миниигру; в ней стоит инициализировать все переменные, нужные миниигре
	sminigames.SetStandartScriptName(_owner, s12_fire_cockroach_minigame) 
	
	self.pos_amount = #self.params.positions -- количество позиций, в которых может появиться пламя
	
	self.timer = __create_timer("", "qe_level") -- создаем таймер
	
	self.pos_state = {} -- массив отметок, есть ли пламя в этой позиции или нет
	for i = 1, #self.params.positions do
		table.insert(self.pos_state, 0)
	end
	
	self.fire = self.AllFire(_owner) -- создали огонь
	self.progress = self.params.progress_init
	
	self.luck_widgets = {} -- виджеты с эффектов тушения
	self.clicks = {} -- виджеты с пеной

	local img = __cast(_owner.GetWidget("progressbar", true), sf.gui.CImageWidget)
	__assert("Нет виджета для отображения прогресса: image_widget, id = progressbar")
	self.progressbar = {image = img, init_size = {X = img.GetSize().X, Y = img.GetSize().Y}}
	self.offset_bottom = self.progressbar.image.GetOffset().Y + self.progressbar.image.GetSize().Y
	
	-- полосочка наверх прогрессбара
	self.progress_upper = __cast(_owner.GetWidget("progressbar_up", true), sf.gui.CImageWidget)
	self.SetProgress()
	
	self.last_update = self.timer.Get().GetTime()
end

-- обновление прогрессбара
function self.UpdateProgress(_owner)
	if self.timer.Get().GetTime() - self.last_update >= self.params.progress_update_time then
		self.progress = self.progress + self.params.progress_update
		self.SetProgress()
		self.last_update = self.timer.Get().GetTime()
	end
end

function self.SetProgress()
	if self.progress > 0 then
		local value = self.progress/self.params.progress_positions
		if value > 1 then
			value = 1
			self.progress = self.params.progress_positions
		end
		local value1 = 1 - value

		self.progressbar.image.SetSize(self.progressbar.init_size.X, self.progressbar.init_size.Y*value1)
		-- выделяем прямоугольник для отрисовки
		local rect = sf.misc.FloatRect(0.0, math.ceil(self.progressbar.init_size.Y*value1), self.progressbar.init_size.X, self.progressbar.init_size.Y)
		self.progressbar.image.GetImage().SetRect(rect)
		self.progressbar.image.GetImage().SetSourceRect(rect)
		
		-- вычисляем новое положение полосочки
		local up_y = self.offset_bottom - self.progressbar.init_size.Y + math.ceil(self.progressbar.init_size.Y*value1) 
		local up_x = self.progressbar.image.GetOffset().X
		self.progress_upper.SetOffset(up_x, up_y)
	end
end

-- обновление всей игры
function self.OnUpdate(_owner)
	if  sf.core.g_Application.GetTimeManager().GetTimer(_T("qe_level")).GetK() < 0.01 then
		return
	end

	if not self.lose_widget then
		self.fire:Update() -- обновление пожара
		self.RemoveLuckWidgets(_owner) -- удаление виджетов с дымом, которые уже закончили играть
		self.CheckEnd(_owner) -- проверка окончания игры и обнуление параметров, если время закончилось
		self.UpdateProgress(_owner) -- обновление прогрессбара
	end
end

-- удаляет виджеты тушения и пены, которые уже закончили играть
function self.RemoveLuckWidgets(_owner)
	local i, n = 1, #self.luck_widgets
	local now = self.timer.Get().GetTime()
	while i <= n do
		local clip = self.luck_widgets[i].clip.GetClip()
		if ((now - self.luck_widgets[i].start) < qe.GetClipTime(clip))  then -- клип еще не отыграл свое
			i = i + 1
		else
			self.luck_widgets[i].clip.SetSize(0,0)
			self.luck_widgets[i].clip.GetClip().Stop() -- отключили звук в клипе
			_owner.RemoveWidget(self.luck_widgets[i].clip)
			table.remove(self.luck_widgets, i)
			n = n-1
		end		
	end
	
	local i, n = 1, #self.clicks
	while i <= n do
		local clip = self.clicks[i].clip.GetClip()
		if ((now - self.clicks[i].start) < qe.GetClipTime(clip))  then -- клип еще не отыграл свое
			i = i + 1
		else
			self.clicks[i].clip.SetSize(0,0)
			self.clicks[i].clip.GetClip().Stop() -- отключили звук в клипе
			_owner.RemoveWidget(self.clicks[i].clip)
			table.remove(self.clicks, i)
			n = n-1
		end		
	end
end

function self.DeleteFire(_owner)
	local n = #self.fire.fires 
		-- удаляем все виджеты текущего пламени
	while n > 0  do
		self.fire.fires[n].clip.SetSize(0, 0)
		self.fire.fires[n].clip.GetClip().Stop()
		_owner.RemoveWidget(self.fire.fires[n].clip)
		table.remove(self.fire.fires, n)
		n = n - 1
	end
	for i = 1, #self.params.positions do
		self.pos_state[i] = 0
	end
	n =  #self.luck_widgets
	while n>0 do
		local clip = self.luck_widgets[n].clip
		clip.GetClip().Stop()
		clip.SetSize(0,0)
		clip.GetClip().Stop()
		_owner.RemoveWidget(clip)
		table.remove(self.luck_widgets, n)
		n = n - 1
	end
	
	n =  #self.clicks
	while n>0 do
		local clip = self.clicks[n].clip
		clip.GetClip().Stop()
		clip.SetSize(0,0)
		clip.GetClip().Stop()
		_owner.RemoveWidget(clip)
		table.remove(self.clicks, n)
		n = n - 1
	end
end

function self.CheckEnd(_owner)
	if self.progress <= 0 then
		self.win = true
		self.DeleteFire(_owner)
		_owner.SetGameResult(1)
		_owner.OnEndGame()
	end
end

-- меняем курсор
function self.OnMouseMove(_owner, _pos, _keyboard_state, _broadcast)
	if self.win then
		return true
	end
	local cursor = sf.gui.CImageWidget(self.params.cursor, "cursor", 1, 0)
	if self.params.cursor ~= "" then
		sf.gui.g_Cursor.Instance().SetCustomCursor(cursor.GetImage().GetTexture())
	end
	return true
end 
-- обработка клика
function self.OnMouseDown(_owner, _pos, _button, _keyboard_state, _broadcast)
	if _broadcast then return false end
	if self.params.sound_click then
		sound(self.params.sound_click)
	end
	-- игра идет своим ходом, все нормально
	local i, n = 1, #self.fire.fires
	
		local widget = sf.gui.CClipWidget("", 0, 0)
		widget.GetClip().Load(self.params.click_clip, true)	
		widget.SetOffset(_pos.X - widget.GetClip().GetViewSize().X/2, _pos.Y - widget.GetClip().GetViewSize().Y/3)
		_owner.AddWidget(widget)
		widget.GetClip().Play()
	while i <= n do -- анализируем, не попали ли мы в один из объектов
		local fire_pos_X, fire_pos_Y  = self.fire.fires[i].clip.GetOffset().X, self.fire.fires[i].clip.GetOffset().Y
		local size = self.fire.fires[i].clip.GetClip().GetSize()
		
		-- вычисляем положение центра клипа
		fire_pos_X = fire_pos_X + size.X/2
		fire_pos_Y = fire_pos_Y + size.Y/2
		if math.abs(_pos.X - fire_pos_X) <= size.X/2 and math.abs(_pos.Y - fire_pos_Y) <= size.Y/2 then
			self.fire.fires[i].active = -1 -- потушили

			-- уменьшаем прогрессбар
			self.progress = self.progress - self.params.progress_click
			self.SetProgress()
		--	return true
		end
		i = i + 1
	end

	
	local obj = {clip = widget, start = self.timer.Get().GetTime()}
	table.insert(self.clicks, obj)
	return true
end

-- _pos - середина нижней части позиции, в которой появилось пламя
-- _time_start - время начала жизни
function self.SingleFire(_pos, _time_start, _num)
	local widget = sf.gui.CClipWidget("", 0, 0)
	widget.GetClip().Load(self.params.obj_clip, true)
	widget.SetOffset(_pos.X, _pos.Y)
	local time_of_life = random(self.params.min_life, self.params.max_life)
	local size = widget.GetClip().GetViewSize()
	widget.SetSize(0, 0) -- изначально пламя у нас не видно
	
	return {
		clip = widget, -- сам объект
		active = 1,  -- сейчас горит = 1, погас сам = 0, потушили = -1
		time_start = _time_start, -- начало жизни
		life_time = time_of_life, -- сколько вообще было время жизни
		max_size = size, -- максимальные размеры
		pos = _pos, -- координаты середины нижней части позиции, в которой появилось пламя
		num = _num, -- номер позиции, которую занял объект
		
		Update = function(_self, _time)
			if not ((_time - _self.time_start < _self.life_time) and _self.active) then
				_self.active = 0 -- погас сам	
				return
			end 
						
			-- время жисти еще не кончилось => надо менять размеры клипа 
			-- вычислим необходимые размеры
			local t = _time - _self.time_start 
			if t > _self.life_time/2 then -- до середины жизни пламя растет, а после - гаснет
				t = _self.time_start + _self.life_time - _time
			end
			t = t*2/_self.life_time -- вычисляем процент
			if t<0 then 
				t = 0
			elseif t>1 then 
				t = 1
			end
				
			local new_w, new_h = _self.max_size.X*t, _self.max_size.Y*t -- новые ширина и высота клипа
			_self.clip.SetSize(new_w, new_h) -- изменили размер
			-- новые координаты клипа
			local new_x, new_y = _self.pos.X - new_w/2, _self.pos.Y - new_h
			_self.clip.SetOffset(new_x, new_y)
		end
	}
end

function self.AllFire(_owner)
	return {
		fires = {}, -- список языков пламени
		next_fire_time = 0, -- время появления следующего огня
		_owner = _owner, 
		
		Update = function(_self)
			local now = self.timer.Get().GetTime() -- нынешнее времечко
			
			local i, n = 1, #_self.fires
			
			while i<=n do -- обновляем все объекты
				local fire = _self.fires[i]
				fire:Update(now) -- обновляем i-ый объект
				
				if fire.active == 1 then -- не надо удалять клип
					i = i + 1
				else --  надо удалять клип
					self.pos_state[fire.num] = 0 -- позиция свободна
					if fire.active < 0 then -- если огонь потушили, а не закончилось его время
						if self.params.sound_luck then	
							sound(self.params.sound_luck)
						end
						------- дым от потухшего огонька
						local widget = sf.gui.CClipWidget("", 0, 0)
						widget.GetClip().Load(self.params.luck_clip, true)
						widget.SetOffset(fire.pos.X - widget.GetClip().GetViewSize().X/2, fire.pos.Y - widget.GetClip().GetViewSize().Y)
						local widget_ptr = sf.gui.CClipWidgetPtrT(widget) --для тушения
						_self._owner.AddWidget(widget_ptr)
						widget.GetClip().Play()
						local obj = {clip = widget, start = now}
						table.insert(self.luck_widgets, obj) -- добавили в список виджетов эффектов тушения
						---- пена для правильного клика
						local widget1 = sf.gui.CClipWidget("", 0, 0)
						widget1.GetClip().Load(self.params.right_click, true)
						widget1.SetOffset(fire.pos.X - widget.GetClip().GetViewSize().X/1.1, fire.pos.Y - widget.GetClip().GetViewSize().Y/6)
						local obj1 = {clip = widget1, start = now}
						_self._owner.AddWidget(widget1)
						table.insert(self.luck_widgets, obj1) -- добавили в спи
					end 
					
					local widget_ptr1 = sf.gui.CClipWidgetPtrT(fire.clip) --удаляем виджет огня
					fire.clip.SetSize(0,0)
					fire.clip.GetClip().Stop() -- отключили звук в клипе
					_self._owner.RemoveWidget(fire.clip)
					table.remove(_self.fires, i)
					n = n - 1
				end
			end
		
			local now = self.timer.Get().GetTime() -- нынешнее времечко
			if (now >= _self.next_fire_time) and #_self.fires < self.params.max_objects then
				-- надо генерить новый объект
				local free = 0 -- считаем количество свободных позиций
				for k = 1, #self.params.positions do
					if self.pos_state[k] == 0 then
						free = free + 1
					end
				end
				local free_num = random(1, free)
				local i = 0
				-- ищем свободную позицию free_num
				for k = 1, #self.params.positions do
					if self.pos_state[k] == 0 then
						i = i + 1
						if i == free_num then
							self.pos_state[k] = 1
							_self:_AddNewFire(now, k)
							break
						end
					end
				end
			end
		end,
		
		-- добавление языка пламени в момент времени _time в позицию _num
		_AddNewFire = function(_self, _time, _num)
			local pos_x, pos_y = self.params.positions[_num].X, self.params.positions[_num].Y
			local pos = {X = pos_x, Y = pos_y}
			
			local object = self.SingleFire(pos, _time, _num) -- создали новый объект
			
			local widget_ptr = sf.gui.CClipWidgetPtrT(object.clip) --???
			_self._owner.AddWidget(widget_ptr)
			
			local interval = random(self.params.min_interval, self.params.max_interval)
			
			_self.next_fire_time = _self.next_fire_time + interval -- следующее появление огня
			
			table.insert(_self.fires, object)
		end		
	}
end
