categorize_stuff = {}

categorize_stuff.params = 
{
	inaccuracy = 30.0,
	
	item_size = 40.0,
	
	categories =
	{		
		{
			area = sf.misc.FloatRect(0.0, 0.0, 230.0, 210.0),
			items = 
			{
				sf.misc.FloatVector(28.0, 209.0),
				sf.misc.FloatVector(211.0, 90.0),
				sf.misc.FloatVector(95.0, 191.0),
				sf.misc.FloatVector(209.0, 154.0),
				sf.misc.FloatVector(46.0, 162.0),
				sf.misc.FloatVector(144.0, 168.0)
			},
			sound_take = "mini_game_categorize_stuff_chicken_01"
		},
		{
			area = sf.misc.FloatRect(259.0, 0.0, 230.0, 210.0),
			items = 
			{
				sf.misc.FloatVector(296.0, 75.0),
				sf.misc.FloatVector(485.0, 186.0),
				sf.misc.FloatVector(433.0, 58.0),
				sf.misc.FloatVector(295.0, 163.0),
				sf.misc.FloatVector(359.0, 185.0),
				sf.misc.FloatVector(418.0, 163.0)
			},
			sound_take = "mini_game_categorize_stuff_duckling_01"
		}
	},
	
	moving_effect = 
	{
		speed = 0.5
	},
	
	sound_right_put = "mini_game_categorize_stuff_put_01",
	sound_error_put = "mini_game_categorize_stuff_error_01"
}

-- находит вещь по позиции
function categorize_stuff.FindItemByPos(_owner, _pos)
	for _, item in pairs(categorize_stuff.items) do
		if item.widget.GetPoly().IsContains(_pos.X, _pos.Y) then
			local image = item.widget.GetImage()
			local pos = _pos - item.widget.GetOffset()
			if sminigames.IsVisiblePoint(image, pos.X, pos.Y) then
				return item
			end
		end
	end
end

-- находит область по позиции
function categorize_stuff.FindCategoryByPos(_pos)
	for i, category in pairs(categorize_stuff.params.categories) do
		if category.area.IsContains(_pos.X, _pos.Y) then
			return i
		end
	end
end

-- удаляет item из общего списка
function categorize_stuff.RemoveItem(_item)
	for i, item in pairs(categorize_stuff.items) do
		if item == _item then
			table.remove(categorize_stuff.items, i)
			break
		end
	end
end

function categorize_stuff.CheckEnd(_owner)
	if #categorize_stuff.items == 0 then
		if categorize_stuff.widgets then
			for _, w in pairs(categorize_stuff.widgets) do
				sminigames.ImageDropBuffer(w.GetImage())
			end		
			categorize_stuff.widgets = nil
		end
		_owner.SetGameResult(1)
		_owner.OnEndGame()
	end
end

function categorize_stuff.OnUpdate(_owner)	
	
	local i, size = 1, #categorize_stuff.effects
	while i <= size  do		
		local e = categorize_stuff.effects[i]		
		e:Update(categorize_stuff.timer.Get().GetTime())
		if e.is_dead == true then
			table.remove(categorize_stuff.effects, i)
			size = size - 1
		else
			i = i + 1
		end		
	end
	
	if #categorize_stuff.effects == 0 then
		categorize_stuff.CheckEnd(_owner)
	end
end

function categorize_stuff.CMovingEffect(_widget, _from, _to, _time_create, _sound_end)
	
	return
	{
		widget = _widget,
		from = sf.misc.FloatVector(_from),
		to = sf.misc.FloatVector(_to),
		dist = sf.misc.CalculateFloatVectorModule(_to - _from),
		time_create = _time_create,	
		sound_end = _sound_end,
		is_dead = false,
		
		Update = function(_self, _time)			
			local speed = categorize_stuff.params.moving_effect.speed
			local k = (_time - _self.time_create) * speed / _self.dist
			
			if _self.widget then
				if k >= 1.0 then
					sound(_self.sound_end)
					_self.widget.SetOffset(_self.to.X, _self.to.Y)
					_self.is_dead = true	
				else
					local pos = _self.from + (_self.to - _self.from) * k
					_self.widget.SetOffset(pos.X, pos.Y)
				end
			end
		end
	}	
end

function categorize_stuff.add_moving_effect(_widget, _to, _sound_end)
	local effect = categorize_stuff.CMovingEffect(_widget, _widget.GetOffset(), _to, categorize_stuff.timer.Get().GetTime(), _sound_end)
	table.insert(categorize_stuff.effects, effect)
end


function categorize_stuff._DropItem(_owner, _pos)
	assert(categorize_stuff.move_item)
	
	local item = categorize_stuff.move_item	
	
	local cat = categorize_stuff.FindCategoryByPos(_pos)
	if cat and item.cat == cat then	
		--  поставить животное куда надо		
		local free_cell = categorize_stuff.next_free_cell[cat]		
		local target_cell = categorize_stuff.params.categories[cat].items[free_cell]		
		free_cell = free_cell + 1
		categorize_stuff.next_free_cell[cat] = free_cell					
		local pos = target_cell - item.widget.GetSize() / 2.0
		--item.widget.SetOffset(pos.X, pos.Y)
		categorize_stuff.add_moving_effect(item.widget, pos, categorize_stuff.params.sound_right_put)
		
		categorize_stuff.RemoveItem(item)
	else
		--  вернуть животное на место
		categorize_stuff.add_moving_effect(item.widget, categorize_stuff.last_widget_pos, categorize_stuff.params.sound_error_put)
	end
	
	categorize_stuff.move_item = nil
	categorize_stuff.last_widget_pos = nil
	categorize_stuff.last_mdown_pos = nil
	
	categorize_stuff.CheckEnd(_owner)
	
	return true 
end
		
function categorize_stuff.OnMouseDown(_owner, _pos, _button, _state, _broadcast)
	if categorize_stuff.move_item then
		-- если перетаскивали вещь
		return categorize_stuff._DropItem(_owner, _pos)
	else
		local item = categorize_stuff.FindItemByPos(_owner, _pos)
		if item then
			sound(categorize_stuff.params.categories[item.cat].sound_take)
			
			categorize_stuff.move_item = item

			assert(categorize_stuff.top_item)
			item.widget.LayInFront(categorize_stuff.top_item.widget)
			categorize_stuff.top_item = categorize_stuff.move_item
			
			categorize_stuff.last_widget_pos = sf.misc.FloatVector(categorize_stuff.move_item.widget.GetOffset())
			categorize_stuff.last_mdown_pos = sf.misc.IntVector(_pos)

			categorize_stuff.OnMouseMove(_owner, _pos, _state, _broadcast)
			
			return true
		end
	end
	return false
end

function categorize_stuff.OnMouseMove(_owner, _pos, _state, _broadcast)
	if categorize_stuff.move_item then	
		local widget = categorize_stuff.move_item.widget
			widget.SetOffset(
				categorize_stuff.last_widget_pos.X + (_pos.X - categorize_stuff.last_mdown_pos.X),
				categorize_stuff.last_widget_pos.Y + (_pos.Y - categorize_stuff.last_mdown_pos.Y) )
		return true
	end
	return false
end

local inacc = 5
function categorize_stuff.OnMouseUp(_owner, _pos, _button, _state, _broadcast)
	if categorize_stuff.move_item then
		local delta = _pos - categorize_stuff.last_mdown_pos
		if delta.ModSqr() > inacc*inacc then
			return categorize_stuff._DropItem(_owner, _pos)
		end
		return true
	end
	return false
end

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

function categorize_stuff.Init(_owner)
	categorize_stuff.categories = {}
	categorize_stuff.items = {}
	categorize_stuff.next_free_cell = {}
	categorize_stuff.move_item = nil
	categorize_stuff.top_item = nil
	categorize_stuff.dragging = false
	categorize_stuff.last_mdown_pos = nil
	
	sminigames.SetStandartScriptName(_owner, categorize_stuff)
	
	categorize_stuff.widgets = {}
	
	-- находим изображения, которые нужно разместить по ячейкам
	local w = _owner.GetWidgets()
	while not w.IsEnd() do
		local widget = __cast(w.Get(), sf.gui.CImageWidget)
		if widget then		
			local cat = string.match(widget.GetId().c_str(), "(%d+)_(%d+)")
			if cat and categorize_stuff.params.categories[tonumber(cat)] then
				local item = {cat = tonumber(cat), widget = widget}
				if not categorize_stuff.top_item then 
					categorize_stuff.top_item = item
				end
				table.insert(categorize_stuff.items, item)
				table.insert(categorize_stuff.widgets, widget)
			end
		end
		w.Next()
	end	
	
	for i, cat in pairs(categorize_stuff.params.categories) do
		categorize_stuff.next_free_cell[i] = 1
	end
	
	categorize_stuff.timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().AttachTimer(_T(""), nil))
	
	categorize_stuff.effects = {}

end
