find_pairs = {}

find_pairs.params = 
{
	-- позиции и угол элементов; angle в градусах
	items = 
	{		
		-- 1
		{pos = sf.misc.FloatVector(50.0, 75.0), angle = 180.0},
		-- 2
		{pos = sf.misc.FloatVector(275.0, 60.0), angle = 0.0},
		-- 3
		{pos = sf.misc.FloatVector(50.0, 250.0), angle = 0.0},
		-- 4
		{pos = sf.misc.FloatVector(135.0, 50.0), angle = 0.0},
		-- 5
		{pos = sf.misc.FloatVector(75.0, 200.0), angle = 90.0},
		-- 6
		{pos = sf.misc.FloatVector(250.0, 240.0), angle = 0.0},
		-- 7
		{pos = sf.misc.FloatVector(355.0, 50.0), angle = 0.0},
		-- 8
		{pos = sf.misc.FloatVector(210.0, 60.0), angle = 90.0},
		-- 9
		{pos = sf.misc.FloatVector(155.0, 175.0), angle = 0.0},
		-- 10
		{pos = sf.misc.FloatVector(425.0, 180.0), angle = 0.0},
		-- 11
		{pos = sf.misc.FloatVector(225.0, 165.0), angle = 0.0},
		-- 12
		{pos = sf.misc.FloatVector(470.0, 45.0), angle = 0.0},
		-- 13
		{pos = sf.misc.FloatVector(170.0, 450.0), angle = 0.0},
		-- 14
		{pos = sf.misc.FloatVector(65.0, 460.0), angle = 0.0},
		-- 15
		{pos = sf.misc.FloatVector(480.0, 450.0), angle = 0.0},
		-- 16
		{pos = sf.misc.FloatVector(475.0, 130.0), angle = 90.0},
		-- 17
		{pos = sf.misc.FloatVector(290.0, 310.0), angle = 0.0},
		-- 18
		{pos = sf.misc.FloatVector(430.0, 340.0), angle = 0.0},
		-- 19
		{pos = sf.misc.FloatVector(195.0, 420.0), angle = 270.0},
		-- 20
		{pos = sf.misc.FloatVector(260.0, 150.0), angle = 180.0},
		-- 21
		{pos = sf.misc.FloatVector(90.0, 365.0), angle = 180.0},
		-- 22
		{pos = sf.misc.FloatVector(365.0, 440.0), angle = 0.0},
		-- 23
		{pos = sf.misc.FloatVector(100.0, 410.0), angle = 270.0},
		-- 24
		{pos = sf.misc.FloatVector(120.0, 115.0), angle = 180.0},
		-- 25
		{pos = sf.misc.FloatVector(245.0, 370.0), angle = 0.0},
		-- 26
		{pos = sf.misc.FloatVector(360.0, 355.0), angle = 0.0},
		-- 27
		{pos = sf.misc.FloatVector(150.0, 320.0), angle = 180.0},
		-- 28
		{pos = sf.misc.FloatVector(490.0, 250.0), angle = 180.0},
		-- 29
		{pos = sf.misc.FloatVector(270.0, 440.0), angle = 270.0},
		-- 30
		{pos = sf.misc.FloatVector(365.0, 250.0), angle = 180.0},
		-- 31
		{pos = sf.misc.FloatVector(500.0, 350.0), angle = 270.0},
		-- 32
		{pos = sf.misc.FloatVector(160.0, 260.0), angle = 180.0},
		-- 33
		{pos = sf.misc.FloatVector(50.0, 345.0), angle = 90.0},
		-- 34
		{pos = sf.misc.FloatVector(375.0, 130.0), angle = 180.0}
	},
	
	-- цвет выделения
	selection_color = sf.graphics.Color(255, 100, 100, 100), -- ARGB
	
	-- параметры подсветки выделения
	select_min_scale = 1.0,
	select_max_scale = 1.2,
	select_period = 1000.0, --мс
	
	-- время исчезновения
	fade_out_time = 1000.0,
	
	sound_select_one = "mini_game_find_pairs_select_01",
	sound_select_pair = "mini_game_find_pairs_select_02"
}

function find_pairs.CheckEnd(_owner)
end
				
function find_pairs.EndGame(_owner)
	_owner.SetGameResult(1)
	_owner.OnEndGame()
end
	
function find_pairs.ClickInWidget(_item, _pos)
	local is_enabled = (sf.misc.BitwiseAnd(_item.widget.GetFlags(), sf.gui.CBaseWidget.FlagDisabled) == 0)
	return (is_enabled and _item.widget.GetPoly().IsContains(_pos.X, _pos.Y))
end
	
function find_pairs.ClickInFilled(_item, _pos)
	local angle = math.pi * _item.info.angle / 180.0
	local size = _item.widget.GetSize()
    local offset = _item.info.pos - size / 2.0
	local p = _pos * sf.misc.MatrixRotation(-angle, _item.info.pos.X, _item.info.pos.Y) - offset

    return sminigames.IsVisiblePoint(_item.widget.GetImage(), p.X, p.Y)
end
				
function find_pairs.OnMouseDown(_owner, _pos, _button, _state, _broadcast)
	for _, item in pairs(find_pairs.items) do		
		if find_pairs.ClickInWidget(item, _pos) and find_pairs.ClickInFilled(item, _pos) then
			find_pairs.SelectItem(item)
			return true
		end
	end
	return false
end

function find_pairs.OnMouseMove(_owner, _pos, _state, _broadcast)
	return false
end

function find_pairs.OnMouseUp(_owner, _pos, _button, _state, _broadcast)	
	return false
end


function find_pairs.OnUpdate(_owner)
	local i = 1
	while i <= #find_pairs.effects do
		local effect = find_pairs.effects[i]
		assert(effect)
		if not effect.is_dead then
			effect:Update(find_pairs.timer.Get().GetTime())
		end
		if effect.is_dead then
			table.remove(find_pairs.effects, i)			
		else
			i = i+1
		end
	end
	if #find_pairs.effects == 0 and find_pairs.resolved == true then
		find_pairs.EndGame(_owner)
		find_pairs.resolved = false
	end
end

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

function find_pairs.Init(_owner)
	sminigames.SetStandartScriptName(_owner, find_pairs)
	
	find_pairs.items = {}

	-- загружаем изображения
	local w = _owner.GetWidgets()
	while not w.IsEnd() do
		local widget = w.Get()		
		if not widget.GetId().empty() then
			local image_item = __cast(widget, sf.gui.CImageWidget)
			if image_item then 
				table.insert(find_pairs.items, {widget = image_item})
			end
		end
		w.Next()
	end
	
	-- расставляем изображения по местам и делаем доступными для клика
	local count = math.min(#find_pairs.items, #find_pairs.params.items)
	for i = 1, count do
		local item = find_pairs.items[i]
		local item_info = find_pairs.params.items[count - i + 1]
		
		local size = item.widget.GetSize()
		local offset = item.widget.GetOffset()		
		
		local matrix = sf.misc.MatrixTranslation(-offset.X - size.X / 2.0, -offset.Y - size.Y / 2.0)
		matrix = matrix * sf.misc.MatrixRotation(math.pi * item_info.angle / 180.0, 0.0, 0.0)
		matrix = matrix * sf.misc.MatrixTranslation(item_info.pos.X, item_info.pos.Y)
		
		item.info = item_info
		
		item.widget.SetRotation(matrix)
		
		item.widget.RemFlags(sf.gui.CBaseWidget.FlagDisabled)
	end
	
	find_pairs.timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().AttachTimer(_T(""), nil))
	
	find_pairs.effects = {}
	
	find_pairs.resolved = false
end

function find_pairs.FadeOutEffect(_item, _start_time, _target_time)
	return 
	{
		_item = _item,
		_start_time = _start_time,
		_target_time = _target_time,
		
		is_dead = false, 
				
		Update = function(_self, _time)
			local alpha = 0
			if _self._start_time <= _time and _time <= _self._target_time then
				local k = (_time - _self._start_time) / (_self._target_time - _self._start_time)
				alpha = 255.0 * (1.0 - k)
			else
				_item.select_effect.is_dead = true
				_item.select_effect = nil
				_self.is_dead = true
			end
			local color = sf.graphics.Color(_self._item.widget.GetColor())
			color.Alpha = alpha
			_self._item.widget.SetColor(color)
		end
	}
end

function find_pairs.SelectEffect(_item, _start_time, _min_scale, _max_scale, _period)
	return 
	{
		_item = _item,
		_start_time = _start_time,
		_min_scale = _min_scale, 
		_max_scale = _max_scale, 
		_period = _period,
		
		is_dead = false, 
				
		Update = function(_self, _time)		
			local t = math.mod(_time - _self._start_time + _period, _period)
			local a = math.pi * (t / _period)
			local k = math.sin(a)
			local scale = _self._min_scale + (_self._max_scale - _self._min_scale) * k
			
			local size = _self._item.widget.GetSize()
			local offset = _self._item.widget.GetOffset()		
			
			local matrix = sf.misc.MatrixTranslation(-offset.X - size.X / 2.0, -offset.Y - size.Y / 2.0)
			matrix = matrix * sf.misc.MatrixScale(scale, scale)
			matrix = matrix * sf.misc.MatrixRotation(math.pi * _self._item.info.angle / 180.0, 0.0, 0.0)
			matrix = matrix * sf.misc.MatrixTranslation(_self._item.info.pos.X, _self._item.info.pos.Y)
			
			_self._item.widget.SetRotation(matrix)
		end
	}
end

function find_pairs.SelectItem(_item)
	find_pairs.AddSelectEffect(_item)
	if find_pairs.selected_item then		
		local id1 = find_pairs.selected_item.widget.GetId().c_str()
		local id2 = _item.widget.GetId().c_str()
		
		if id1 == id2 then			
			-- нашли пару
			find_pairs.RemoveItem(find_pairs.selected_item)
			find_pairs.RemoveItem(_item)
			find_pairs.AddFadeOutEffect(find_pairs.selected_item)
			find_pairs.AddFadeOutEffect(_item)

			if #find_pairs.items == 0 then
				find_pairs.resolved = true
			end
			
			find_pairs.selected_item = nil
			
			if find_pairs.params.sound_select_pair then
				sf.core.g_Application.GetAudioManager().Play(find_pairs.params.sound_select_pair, -2, -2, -2, -2, -2)
			end			
		else
			-- сбросить выделения
			find_pairs.selected_item.select_effect.is_dead = true
			find_pairs.selected_item.select_effect = nil
			
			local size = find_pairs.selected_item.widget.GetSize()
			local offset = find_pairs.selected_item.widget.GetOffset()		
			
			local matrix = sf.misc.MatrixTranslation(-offset.X - size.X / 2.0, -offset.Y - size.Y / 2.0)
			matrix = matrix * sf.misc.MatrixScale(1.0, 1.0)
			matrix = matrix * sf.misc.MatrixRotation(math.pi * find_pairs.selected_item.info.angle / 180.0, 0.0, 0.0)
			matrix = matrix * sf.misc.MatrixTranslation(find_pairs.selected_item.info.pos.X, find_pairs.selected_item.info.pos.Y)
			find_pairs.selected_item.widget.SetRotation(matrix)
			find_pairs.selected_item.widget.RemFlags(sf.gui.CBaseWidget.FlagDisabled)

			find_pairs.selected_item = _item
			if find_pairs.params.sound_select_one then
				sf.core.g_Application.GetAudioManager().Play(find_pairs.params.sound_select_one, -2, -2, -2, -2, -2)
			end
		end
		
	else		
		if #find_pairs.items == 1 then
			find_pairs.resolved = true
		else
			find_pairs.selected_item = _item
		end
		if find_pairs.params.sound_select_one then
			sf.core.g_Application.GetAudioManager().Play(find_pairs.params.sound_select_one, -2, -2, -2, -2, -2)
		end
	end
end

function find_pairs.RemoveItem(_item)
	for i = 1, #find_pairs.items do
		local item = find_pairs.items[i]
		assert(item)
		if item == _item then
			table.remove(find_pairs.items, i)
			break
		end
	end
end

function find_pairs.AddFadeOutEffect(_item)	
	local effect = find_pairs.FadeOutEffect(_item, find_pairs.timer.Get().GetTime(), find_pairs.timer.Get().GetTime() + find_pairs.params.fade_out_time)
	table.insert(find_pairs.effects, effect)
end

function find_pairs.AddSelectEffect(_item)	
	_item.widget.AddFlags(sf.gui.CBaseWidget.FlagDisabled)
	local effect = find_pairs.SelectEffect(_item, find_pairs.timer.Get().GetTime(), find_pairs.params.select_min_scale, find_pairs.params.select_max_scale, find_pairs.params.select_period)
	table.insert(find_pairs.effects, effect)
	_item.select_effect = effect
end