--[[
Исходные данные: есть 10 ячеек, есть 4 объекта цвета A и 4 объекта цвета B. Объекты располагаются в ячейках начиная с первой, чередуясь по цветам.
Т.е, например так:
1 2 3 4 5 6 7 8 9 10
A B A B A B A B _ _

За один ход, игрок может перемещать 2 объекта (неважно каких цветов). Реализовать так, чтобы при наведении на один объект, выделялся объект следующий
за ним ( если он есть), либо предыдущий, если следующего нет.

Цель игры:  переместить объекты одного цвета в одну сторону, другого - в другую:
1 2 3 4 5 6 7 8 9 10
A A A A _ _ B B B B
]]

split_figures_by_type = {}
local self = split_figures_by_type

self.params = {
	sound_select = "mini_game_mini_game_split_figures_by_type_select_part_01", -- выделение по клику
	sound_selection_on_move = "mini_game_mini_game_split_figures_by_type_select_part_02", -- когда ничего не выделено и меняется маленькое выделение
	sound_put = "mini_game_mini_game_split_figures_by_type_select_put_01", -- звук на перемещение 
	
	image_prefix = "figure0", -- начало id-шников в dsfrontend'е для всех объектов
	big_image_id = "scenes_scene02_01_minigame_minigame02_big0", -- начало id вытащенного объекта
	big_image_shift = 
	{--  сдвиг вытащенного объекта относительно начального положения02
		sf.misc.FloatVector(-30, -20), -- для левого объекта
		sf.misc.FloatVector(-20, -20) -- для правого объекта
	},
	speed = 150, -- скорость перемещения фишек
	clip_select_pair = 
	{ -- выделение пары объектов
		on_mouse_over = 
		{ -- когда наведена мышь на книжку
			id = "light_button02", -- id клипа
			shift_pos = sf.misc.FloatVector(-0.1, -0.05), -- на сколько сдвигать относительно левого верхнего угла левой картинки, в доле от размера картинки
			layer = 0  -- слой
		},
		on_moving =
		{ -- когда нажали на книжки и они поехали
			id = "light_button01", -- id клипа
			shift_pos = sf.misc.FloatVector(-0.1, -0.03), -- на сколько сдвигать относительно левого верхнего угла левой картинки, в доле от размера картинки
			layer = 0  -- слой
		}, 
		empty_select =
		{ -- подсветка пустого места
			id = "bottom01", -- id клипа
			shift_pos = sf.misc.FloatVector(0, 0), -- на сколько сдвигать относительно левого верхнего угла левой картинки, в доле от размера картинки
			layer = 1  -- слой
		}
	},
	positions = {
		{ -- 1
			obj_type = 1,
			end_type = 2
		},
		{ -- 2
			obj_type = 2,
			end_type = 2
		},
		{ -- 3
			obj_type = 1,
			end_type = 2
		},
		{ -- 4
			obj_type = 2,
			end_type = 2
		},
		{ -- 5
			obj_type = 1,
			end_type =0 -- будет пусто
		},
		{ -- 6
			obj_type = 2,
			end_type = 0
		},
		{ -- 7
			obj_type = 1,
			end_type = 1
		},
		{ -- 8
			obj_type = 2,
			end_type = 1
		},
		{ -- 1
			obj_type = 0,
			end_type = 1
		},
		{ -- 10
			obj_type = 0,
			end_type = 1
		}
	}
}

self.Init = function(_owner)
	sminigames.SetStandartScriptName(_owner, split_figures_by_type) 
	
	self.LoadInfo(_owner)
	
	-- выделение 
	local layer = self.params.clip_select_pair.on_mouse_over.layer or 0
	self.select_on_mouse_over = sf.gui.CClipWidget("", layer, 0)
	self.select_on_mouse_over.GetClip().Load(self.params.clip_select_pair.on_mouse_over.id, true)
	_owner.AddWidget(self.select_on_mouse_over)
	self.select_on_mouse_over.AddFlags(sf.gui.CWidget.FlagHidden)
	
	layer = self.params.clip_select_pair.on_moving.layer or 0
	self.select_on_moving = sf.gui.CClipWidget("", layer, 0)
	self.select_on_moving.GetClip().Load(self.params.clip_select_pair.on_moving.id, true)
	_owner.AddWidget(self.select_on_moving)
	self.select_on_moving.AddFlags(sf.gui.CWidget.FlagHidden)
	
	layer = self.params.clip_select_pair.empty_select.layer or 0
	self.select_empty = sf.gui.CClipWidget("", layer, 0)
	self.select_empty.GetClip().Load(self.params.clip_select_pair.empty_select.id, true)
	_owner.AddWidget(self.select_empty)
	self.select_empty.AddFlags(sf.gui.CWidget.FlagHidden)
end

function self.LoadInfo(_owner)
	self.pos_amount = #self.params.positions -- количество позиций
	
	self.timer = __create_timer() -- создаем таймер
		
	self.turns = 0 -- еще не сделано ни одного хода
	--  создадим массив виджетов с рисунками передвигаемых объектов
	self.init_objects = {}
	self.objects = {}
	for i = 1, self.pos_amount do
		local img = __cast(_owner.GetWidget(self.params.image_prefix..i , true), sf.gui.CImageWidget)
		__assert(img, "Добавьте картинки в dsfrontend! нет картинки с id="..self.params.image_prefix..i)
		local o = {image = img, obj_type = self.params.positions[i].obj_type}
		table.insert(self.objects, o)
		table.insert(self.init_objects, {image = img, obj_type = self.params.positions[i].obj_type, X = img.GetOffset().X, Y = img.GetOffset().Y })
	end
	self.selected = {}
	
	self.sel_widgets = {} -- вытащенные виджеты
	self.is_moving = -1 -- ничего не движется
	self.mov_shift = 0 -- на сколько надо будет сдвинуть виджеты по горизонтали (отр - влево, положит - вправо)
	self.last_start = 0 -- начало последнего движения
	self.start_pos = {} -- откуда начал двигаться
	self.free_ind = 0 -- индекс свободного поля, в который кликнули
end

function self.CheckEnd(_owner)
	local flag = true
	for i = 1, self.pos_amount do
		if self.objects[i].obj_type ~= self.params.positions[i].end_type then
			flag = false
			break
		end
	end
	
	if flag then
		_owner.SetGameResult(1)
		_owner.OnEndGame()
	end
end

-- проверяет, в какой объект кликнули
function self.IsObject(_owner, _pos)
	for i = 1, #self.objects do
		local width, height = self.objects[i].image.GetSize().X, self.objects[i].image.GetSize().Y
		-- центр картинки
		local pos_x = self.objects[i].image.GetOffset().X + width/2
		local pos_y = self.objects[i].image.GetOffset().Y + height/2
		
		if math.abs(_pos.X - pos_x) < width/2 and math.abs(_pos.Y - pos_y) < height/2 then
			-- попали в виджет
			return i
		end
	end
	return nil
end

-- выделяем 
function self.OnMouseMove(_owner, _pos, _keyboard_state, _broadcast)
	if self.is_moving > 0 or #self.selected >0 then return false end -- при движении не обрабатываем 
	
	local obj = self.IsObject(_owner, _pos)
	if not obj then 
		self.select_on_mouse_over.AddFlags(sf.gui.CWidget.FlagHidden)
		self.select_on_mouse_over.SetOffset(0, 0)
		return false 
	end
	
	if self.select_on_mouse_over then
		if self.objects[obj].obj_type > 0 then
			-- не пустое место
			
			local sel_ind = self.GetSelectionIndexes(obj)
			if #sel_ind > 0 then
				local off_x = self.objects[sel_ind[1]].image.GetOffset().X + 
					self.objects[sel_ind[1]].image.GetSize().X*self.params.clip_select_pair.on_mouse_over.shift_pos.X
				local off_y = self.objects[sel_ind[1]].image.GetOffset().Y + 
					self.objects[sel_ind[1]].image.GetSize().Y*self.params.clip_select_pair.on_mouse_over.shift_pos.Y
				local old_off = 
							{
								X = self.select_on_mouse_over.GetOffset().X, 
								Y = self.select_on_mouse_over.GetOffset().Y
							}
				self.select_on_mouse_over.SetOffset(off_x, off_y)
				self.select_on_mouse_over.RemFlags(sf.gui.CWidget.FlagHidden)
				if old_off.X ~= off_x or old_off.Y ~= off_y then
					if self.params.sound_selection_on_move then
						sound(self.params.sound_selection_on_move)
					end
				end
			end
		end
	end
	return true
end

function self.Deselect(_owner) -- убрать выделение
	if #self.selected > 0 then
		-- убрали невидимость у выделеных виджетов
		self.objects[self.selected[1]].image.SetLayer(self.selected[1]+1)
		self.objects[self.selected[2]].image.SetLayer(self.selected[2]+1)
		
		_owner.RemoveWidget(self.sel_widgets[1])
		_owner.RemoveWidget(self.sel_widgets[2])
		self.sel_widgets = {}
		self.select_on_moving.AddFlags(sf.gui.CWidget.FlagHidden)
	end
end

-- что выделится, если навели или кликнули на _index
function self.GetSelectionIndexes(_index)
	local n = #self.objects
	local res = {}
	if _index == n or self.objects[_index + 1].obj_type == 0 then
		-- нет объекта справа - надо выделить этот и левый
		if not (_index == 1 or self.objects[_index - 1].obj_type == 0) then
			-- слева есть объекты
			table.insert(res, _index - 1)
			table.insert(res, _index)
		end
	else
		-- справа есть объект
		table.insert(res, _index)
		table.insert(res, _index + 1)
	end
	return res
end

function self.SelectObjects(_owner, _index)
	
	local sel_ind = self.GetSelectionIndexes(_index)
	if #sel_ind == 0 then
		return
	end
	self.Deselect(_owner) -- убрать подсветку с выделенных прежде
	self.selected = {}
	for i = 1, #sel_ind do
		table.insert(self.selected, sel_ind[i])
	end	
	
	if self.params.sound_select then
		sound(self.params.sound_select)
	end
	
	-- прячем выделенные
	self.objects[self.selected[1]].image.SetLayer(0)
	self.objects[self.selected[2]].image.SetLayer(0)
	
	local widget = sf.gui.CImageWidget(self.params.big_image_id..self.objects[self.selected[1]].obj_type, "widget01", 11, 0)
	local offset_x = self.objects[self.selected[1]].image.GetOffset().X + self.params.big_image_shift[1].X
	local offset_y = self.objects[self.selected[1]].image.GetOffset().Y + self.params.big_image_shift[1].Y
	widget.SetOffset(offset_x, offset_y)
	_owner.AddWidget(widget)
	table.insert(self.sel_widgets, widget)
	widget = sf.gui.CImageWidget(self.params.big_image_id..self.objects[self.selected[2]].obj_type, "widget02", 11, 0)
	local offset_x = self.objects[self.selected[2]].image.GetOffset().X + self.params.big_image_shift[2].X
	local offset_y = self.objects[self.selected[2]].image.GetOffset().Y + self.params.big_image_shift[2].Y
	widget.SetOffset(offset_x, offset_y)
	_owner.AddWidget(widget)
	table.insert(self.sel_widgets, widget)
	
	self.select_on_mouse_over.AddFlags(sf.gui.CWidget.FlagHidden)
	
	local off_x = self.sel_widgets[1].GetOffset().X + 
		self.sel_widgets[1].GetSize().X*self.params.clip_select_pair.on_moving.shift_pos.X
	local off_y = self.sel_widgets[1].GetOffset().Y + 
		self.sel_widgets[1].GetSize().Y*self.params.clip_select_pair.on_moving.shift_pos.Y
	self.select_on_moving.SetOffset(off_x, off_y)
	self.select_on_moving.RemFlags(sf.gui.CWidget.FlagHidden)
	
	self.select_empty.RemFlags(sf.gui.CWidget.FlagHidden)
	self.free_ind = self.FindFreeInd()
	local off_x = self.objects[self.free_ind].image.GetOffset().X + 
		self.objects[self.free_ind].image.GetSize().X*self.params.clip_select_pair.empty_select.shift_pos.X
	local off_y = self.objects[self.free_ind].image.GetOffset().Y + 
		self.objects[self.free_ind].image.GetSize().Y*self.params.clip_select_pair.empty_select.shift_pos.Y
	self.select_empty.SetOffset(off_x, off_y)
end

function self.FindFreeInd()
	for i, obj in ipairs(self.objects) do
		if obj.obj_type == 0 then
			return i
		end
	end
end

function self.OnMouseDown(_owner, _pos, _button, _state, _broadcast)
	-- ищем, куда попали
	if self.is_moving > 0 then return false end -- при движении не обрабатываем клики
	
	local click = self.IsObject(_owner, _pos)
	if not click then
		return false-- никуда не попали
	else
		-- попали.
		if self.objects[click].obj_type > 0 then
			-- кликнули не на пустое место - надо выделить два объекта
			self.SelectObjects(_owner, click)
		else
			-- попали в пустое место. надо проверить, были ли выделены объекты, и если были - поменять их расположение и снять выделение
			if #self.selected == 0 then
				return false
			else
				local n = #self.objects
				self.free_ind = click
				if click == n or self.objects[click + 1].obj_type > 0 then
					self.free_ind = click - 1 -- click - индекс левой свободной ячейки
				end
				self.is_moving = 1 -- начали двигаться
				-- вычисляем сдвиг
				self.mov_shift = self.params.big_image_shift[1].X + self.objects[self.free_ind].image.GetOffset().X 
								- self.sel_widgets[1].GetOffset().X
				self.last_start = self.timer.Get().GetTime()
				local strt_x =  self.objects[self.selected[1]].image.GetOffset().X + self.params.big_image_shift[1].X
				local strt_y = self.objects[self.selected[1]].image.GetOffset().Y + self.params.big_image_shift[1].Y
				table.insert(self.start_pos, {X = strt_x, Y = strt_y})
				strt_x =  self.objects[self.selected[2]].image.GetOffset().X + self.params.big_image_shift[2].X
				strt_y = self.objects[self.selected[2]].image.GetOffset().Y + self.params.big_image_shift[2].Y
				table.insert(self.start_pos,  {X = strt_x, Y = strt_y})
			end
		end
		return true
	end
end 

-- переносит выбранные фигуры на пустое место и снимает выделение
function self.SwitchFigures(_owner, _free_index)
	-- снимаем выделение
	self.Deselect(_owner)
	if self.params.sound_put then
		sound(self.params.sound_put)
	end
	-- меняем картинки местами
	local img_offset1_x, img_offset1_y = self.objects[_free_index].image.GetOffset().X, self.objects[_free_index].image.GetOffset().Y
	local img_offset2_x, img_offset2_y  = self.objects[self.selected[1]].image.GetOffset().X, self.objects[self.selected[1]].image.GetOffset().Y
	local img_offset3_x, img_offset3_y = self.objects[_free_index + 1].image.GetOffset().X, self.objects[_free_index + 1].image.GetOffset().Y
	local img_offset4_x, img_offset4_y = self.objects[self.selected[2] ].image.GetOffset().X, self.objects[self.selected[2] ].image.GetOffset().Y
	
	self.objects[_free_index].image.SetOffset(img_offset2_x, img_offset2_y)
	self.objects[self.selected[1] ].image.SetOffset(img_offset1_x, img_offset1_y)
	
	self.objects[_free_index + 1].image.SetOffset(img_offset4_x, img_offset4_y)
	self.objects[self.selected[2] ].image.SetOffset(img_offset3_x, img_offset3_y)
	
	--меняем местами позиции в массиве
	local tmp
	tmp = self.objects[_free_index].image
	self.objects[_free_index].image = self.objects[self.selected[1] ].image
	self.objects[self.selected[1] ].image = tmp
	tmp = self.objects[_free_index].obj_type
	self.objects[_free_index].obj_type = self.objects[self.selected[1] ].obj_type
	self.objects[self.selected[1] ].obj_type = tmp
	self.objects[self.selected[1]].image.SetLayer(1)
	self.objects[_free_index].image.SetLayer(_free_index + 1)
	
	tmp = self.objects[_free_index + 1].image
	self.objects[_free_index + 1].image = self.objects[self.selected[2] ].image
	self.objects[self.selected[2] ].image = tmp
	tmp = self.objects[_free_index + 1].obj_type
	self.objects[_free_index + 1 ].obj_type = self.objects[self.selected[2] ].obj_type
	self.objects[self.selected[2] ].obj_type = tmp
	self.objects[self.selected[2]].image.SetLayer(1)
	self.objects[_free_index + 1].image.SetLayer(_free_index + 2)

	self.selected = {} 
end 

function self.OnUpdate(_owner)
	if self.is_moving < 0 then return end 
	
	local need_time = math.abs(self.mov_shift) / self.params.speed * 1000 
	local cur = (self.timer.Get().GetTime() - self.last_start) / need_time
	if cur > 1 then
		cur = 1
	end
	
	local new_x = self.start_pos[1].X + self.mov_shift * cur -- для первого виджета
	local shift = new_x - self.sel_widgets[1].GetOffset().X
	self.sel_widgets[1].SetOffset(new_x, self.sel_widgets[1].GetOffset().Y)
	new_x = self.start_pos[2].X + self.mov_shift * cur -- для второго виджета
	self.sel_widgets[2].SetOffset(new_x, self.sel_widgets[2].GetOffset().Y)
	
	new_x = self.select_on_moving.GetOffset().X + shift
	self.select_on_moving.SetOffset(new_x, self.select_on_moving.GetOffset().Y)
	
	if cur == 1 then
		-- конец движения
		self.is_moving = -1
		self.start_pos = {}
		self.SwitchFigures(_owner, self.free_ind)
		self.select_empty.AddFlags(sf.gui.CWidget.FlagHidden)
		self.CheckEnd(_owner)
	end
end 