catch_falling_objects = {}

catch_falling_objects.params = 
{
	conveyor =
	{
		-- минимальная пауза между появлением объектов
		min_sleep = 800,
		-- максимальная пауза между появлением объектов
		max_sleep = 1200,
		-- объекты
		objects = 
		{
			{
				is_good = true,
				image = "scene12_02_mini_minigame01_berry",
				chance = 0.3,
				speed = 300,
				score = 20
			},
			{
				is_good = true,
				image = "scene12_02_mini_minigame01_herb",
				chance = 0.25,
				speed = 300,
				score = 20
			},
			{
				is_good = true,
				image = "scene12_02_mini_minigame01_mushroom",
				chance = 0.25,
				speed = 300,
				score = 20
			},
			{
				is_good = false,
				image = "scene12_02_mini_minigame01_leaf",
				chance = 0.1,
				speed = 300,
				score = -40
			},
			{
				is_good = false,
				image = "scene12_02_mini_minigame01_cone",
				chance = 0.1,
				speed = 300,
				score = -40
			}
		}
	},
	-- координата Y "ловильщика"
	catcher_y = 441,
	-- необходимое количество очков
	target_scores = 300,
	-- звук на ловлю "хорошего" предмета
	sound_good_catch = "mini_game_catch_falling_objects_01",
	-- звук на ловлю "плохого" предмета
	sound_bad_catch = "mini_game_catch_falling_objects_error_01"
}
		
function catch_falling_objects.CheckEnd(_owner)
	if catch_falling_objects.scores >= catch_falling_objects.params.target_scores then
		_owner.SetGameResult(1)
		_owner.OnEndGame()
	end
end
	
function catch_falling_objects.OnMouseMove(_owner, _pos, _state, _broadcast)

	sf.gui.g_Cursor.Instance().SetCursor(sf.gui.CCursor.CursorNone)

	local size_area = _owner.GetSize()
	local size = sf.misc.FloatVector(catch_falling_objects.catcher.GetSize())
	local offset = sf.misc.FloatVector(catch_falling_objects.catcher.GetOffset())
	offset.X = _pos.X - size.X/2.0
	if offset.X < 0.0 then offset.X = 0.0 end
	if offset.X > size_area.X-size.X then offset.X = size_area.X-size.X end
	catch_falling_objects.catcher.SetOffset(offset.X, offset.Y)
	
	return true
end

function catch_falling_objects.OnUpdate(_owner)
	catch_falling_objects.conveyor:Update()
	catch_falling_objects.UpdateScores(_owner)
	catch_falling_objects.CheckEnd(_owner)
end

function catch_falling_objects.OnPreferredSize(_owner)
	return sminigames.OnPreferredSize(_owner)
end

function catch_falling_objects.Init(_owner)
	sminigames.SetStandartScriptName(_owner, catch_falling_objects)		
	
	_owner.AddFlags(sf.gui.CBaseWidget.FlagClipDraw)
	
	catch_falling_objects.conveyor = catch_falling_objects.CConveyor(_owner)
	
	catch_falling_objects.catcher = __cast(_owner.GetWidget(_T("catcher")), sf.gui.CImageWidget)
	assert(catch_falling_objects.catcher)
	
	catch_falling_objects.progress = nil
	
	catch_falling_objects.scores = 0.0
end

function catch_falling_objects.UpdateScores(_owner)
	if not catch_falling_objects.progress then
		local parent = _owner.GetParentWidget()
		catch_falling_objects.progress = __cast(parent.GetWidget(_T("progress")), sf.gui.CImageWidget)
		assert(catch_falling_objects.progress)
	end
	if catch_falling_objects.scores < 0.0 then 
		catch_falling_objects.scores = 0.0 
	end
	if catch_falling_objects.scores > catch_falling_objects.params.target_scores then 
		catch_falling_objects.scores = catch_falling_objects.params.target_scores 
	end
	if catch_falling_objects.scores == 0.0 then
		catch_falling_objects.progress.AddFlags(sf.gui.CBaseWidget.FlagHidden)
	else
		catch_falling_objects.progress.RemFlags(sf.gui.CBaseWidget.FlagHidden)
		local value = catch_falling_objects.scores / catch_falling_objects.params.target_scores
		local image = catch_falling_objects.progress.GetImage()
		local size = catch_falling_objects.progress.GetSize()
		local rect = sf.misc.FloatRect(0.0, 0.0, size.X * value, size.Y)
		image.SetRect(rect)
		image.SetSourceRect(rect)
	end
end

function catch_falling_objects.ObjectReachCatcherY(_object)
	local object_offset = _object.widget.GetOffset()
	local object_size = _object.widget.GetSize()
	local catcher_offset = catch_falling_objects.catcher.GetOffset()
	local catcher_size = catch_falling_objects.catcher.GetSize()
	if object_offset.X >= catcher_offset.X and object_offset.X+object_size.X <= catcher_offset.X+catcher_size.X then
		return true
	end
	return false
end

function catch_falling_objects.CObject(_info, _pos)
	local widget = sf.gui.CImageWidget(_T(_info.image), _T(""), 10, 0)
	widget.SetOffset(_pos.X, _pos.Y)
	
	return 
	{
		is_good = _info.is_good,
		speed = _info.speed,
		score = _info.score,
		widget = widget,		
		active = true,
		
		_last_time = nil,
		
		Update = function(_self, _time)
			if _self._last_time then
				local delta_time = (_time - _self._last_time) / 1000.0
				local delta_dist = delta_time * _self.speed
				local offset = sf.misc.FloatVector(_self.widget.GetOffset())
				offset.Y = offset.Y + delta_dist
				_self.widget.SetOffset(offset.X, offset.Y)
			end
			_self._last_time = _time
		end
	}
end

function catch_falling_objects.CConveyor(_owner)
	
	local sum_chance = 0.0
	for _,info in pairs(catch_falling_objects.params.conveyor.objects) do
		sum_chance = sum_chance + info.chance
	end	
	
	return 
	{
		_objects = {},
		_timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().AttachTimer(_T(""), nil)),
		_owner = _owner,
		_good_images = good_images,
		_bad_images = bad_images,
		_time_next_object = 0.0,
		_sum_chance = sum_chance,
			
		Update = function(_self)
			local t = _self._timer.Get().GetTime()
			
			local i,c = 1, #_self._objects
			while i<=c do
				local o = _self._objects[i]
				o:Update(t)
				local offset = o.widget.GetOffset()
				local size = o.widget.GetSize()
				local size_area = _self._owner.GetSize()
				local catched = false
				if o.active and offset.Y+size.Y >= catch_falling_objects.params.catcher_y then
					o.active = false
					catched = catch_falling_objects.ObjectReachCatcherY(o)
					if catched then
						catch_falling_objects.scores = catch_falling_objects.scores + o.score
						local sound = catch_falling_objects.params.sound_good_catch
						if not o.is_good then sound = catch_falling_objects.params.sound_bad_catch end
						sf.core.g_Application.GetAudioManager().Play(sound, -2, -2, -2, -2, -2)					
					end
				end
				if catched or offset.Y > size_area.Y then
					o.widget.AddFlags(sf.gui.CBaseWidget.FlagDead)
					table.remove(_self._objects, i)
					c = c-1
				else					
					i = i+1
				end
			end
			
			local t = _self._timer.Get().GetTime()
			if t >= _self._time_next_object then
				_self:_CreateObject()
				local min_sleep = catch_falling_objects.params.conveyor.min_sleep
				local max_sleep = catch_falling_objects.params.conveyor.max_sleep
				_self._time_next_object = t + math.random(min_sleep, max_sleep)
			end
		end,
		
		_CreateObject = function(_self)
			local chance = math.random() * _self._sum_chance
			local object_info = nil
			local sum_chance = 0.0
			for _,info in pairs(catch_falling_objects.params.conveyor.objects) do
				sum_chance = sum_chance + info.chance
				if chance <= sum_chance then
					object_info = info
					break
				end
			end	
			
			assert(object_info)
				
			local image = sf.graphics.CImage(object_info.image)
			local size_area = _self._owner.GetSize()
			local image_rect = image.GetRect()			
			local pos = sf.misc.FloatVector(math.random(0.0, size_area.X - image_rect.Width), -image_rect.Height)

			local object = catch_falling_objects.CObject(object_info, pos, speed)
			
			local widget_ptr = sf.gui.CImageWidgetPtrT(object.widget)
			_self._owner.AddWidget(widget_ptr)
			
			table.insert(_self._objects, object)
		end
	}
end
