--[[
Провести по каждой линии узора, не повторяя дважды ни одну из них
]]

draw_in_single_line = {}
local self = draw_in_single_line

self.params = {
	sound_on_pos = "rope_tie", -- звук на привязывание к следующей точке
	cursor = "", -- курсор игры
	color_selected = sf.graphics.Color(255, 245, 155, 255), -- цвет, накладываемый на выделенную позицию
	pos_size = sf.misc.FloatVector(30, 30), -- размер позиции
	delay = 500, -- задержка при победе или поражении
	positions = { -- узлы 
		sf.misc.FloatVector(502, 48),
		sf.misc.FloatVector(322, 130),
		sf.misc.FloatVector(679, 106),
		sf.misc.FloatVector(440, 177),
		sf.misc.FloatVector(565, 173),
		sf.misc.FloatVector(278, 260),
		sf.misc.FloatVector(732, 232),
		sf.misc.FloatVector(412, 297),
		sf.misc.FloatVector(613, 282),
		sf.misc.FloatVector(352, 436),
		sf.misc.FloatVector(668, 419)
	},
	lines = { -- ребра
		{1, 2}, -- начало и конец ребра
		{1, 3},
		{1, 4},
		{1, 5},
		{2, 4},
		{2, 6},
		{2, 8},
		{3, 5},
		{3, 7},
		{3, 9},
		{4, 5},
		{4, 6},
		{4, 9},
		{5, 7},
		{5, 8},
		{6, 8},
		{6, 10},
		{7, 9},
		{7, 11},
		{8, 9},
		{8, 10},
		{8, 11},
		{9, 10},
		{9, 11},
		{10, 11}
	},
	line_tile = "scenes_chapter06_scene03_miniscene_rope", -- картинка с кусочком веревки, который тайлится
	pos_image = "scenes_chapter06_scene03_miniscene_knot" -- картинка с узлом 
}
function self.Init(_owner)
	sminigames.SetStandartScriptName(_owner, draw_in_single_line)

	self.pos_images = {}
	for i, pos in ipairs(self.params.positions) do -- выставляем картинки с позициями
		local img = sf.gui.CImageWidget(self.params.pos_image, "pos", 3, 0)
		local sz = img.GetSize()
		img.SetOffset(pos.X - sz.X/2, pos.Y - sz.Y/2)
		table.insert(self.pos_images, img)
		_owner.AddWidget(img)
	end
		
	self.StartGame(_owner) -- инициализация всех переменных
end 
-- снимает выделение с позиций
function self.DeselectAll()
	for i, img in ipairs(self.pos_images) do
--		img.SetColor(sf.graphics.Color(255, 255, 255))
	end
end

-- выделяет позицию _ind
function self.SelectPos(_ind)
	if self.params.color_selected then
		if self.params.sound_on_pos then
			sound(self.params.sound_on_pos)
		end
		self.DeselectAll()
		self.pos_images[_ind].RemFlags(sf.gui.CWidget.FlagHidden)
	end
end

-- инициализирует начало игры. Вызывается при первом запуске и после захода в тупик 
function self.StartGame(_owner)
	self.lines = {} -- хранит информацию о том, что по линии уже прошли
	for i = 1, #self.params.lines do
		table.insert(self.lines, 0) -- еще не пройдены
	end
	
	self.timer = __create_timer("", "qe_level")
	self.widgets = {} -- здесь хранятся виджеты 
	self.cur_line = nil -- на какой линии мы щас находимся
	self.last_pos = nil -- через какую вершину в последний раз прошли
	self.accessible_lines = {} -- какие линии доступны из этой вершины
	self.cur_widget = nil -- тайлящийся виджет, который бегает за курсором
	
	for i, img in ipairs(self.pos_images) do
		img.AddFlags(sf.gui.CWidget.FlagHidden)
	end
end 

-- проверяет заход в тупик или победу
function self.CheckEnd(_owner)
	for i, line in ipairs(self.lines) do
		if line == 0 then -- если путей из вершины нет от того, что зашли в тупик - начать сначала
			self.lose = true
			self.start = self.timer.Get().GetTime()
			return
		end
	end
	-- иначе победа :)
	self.start = self.timer.Get().GetTime()
	self.win = true
	
end
-- проверяет задержку после победы и поражения
function self.OnUpdate(_owner)
	if  sf.core.g_Application.GetTimeManager().GetTimer(_T("qe_level")).GetK() < 0.01 then
		return
	end

	if self.lose then -- проиграли, инициализируем игру заново
		if self.timer.Get().GetTime() - self.start > self.params.delay then	
			self.lose = nil
			self.RemoveWidgets(_owner)
			self.DeselectAll()
			self.StartGame(_owner)
		end
	end
	if self.win then -- выиграли, завершаем игру
		if self.timer.Get().GetTime() - self.start > self.params.delay then	
			self.win = nil
			_owner.SetGameResult(1)
			_owner.OnEndGame()
		end
	end
	return true
end

-- удаляет все созданные виджеты
function self.RemoveWidgets(_owner)
	for i, widget in ipairs(self.widgets) do
		_owner.RemoveWidget(widget)
	end
	self.widgets = {}
	_owner.RemoveWidget(self.cur_widget)
	self.cur_widget = nil
end

function self.OnMouseDown(_owner, _pos, _button, _keyboard_state, _broadcast)
	local pos_ind = self.IsPos(_pos) -- проверяем, попали ли мы в позицию
	if pos_ind and pos_ind ~= self.last_pos then -- если мы куда-то переместили курсор после последнего нажатия кнопки
		if self.last_pos then  -- это не первая выделенная позиция
			local is_correct = self.IsAccessiblePoint(pos_ind) -- проверяем, соединена ли эта позиция с текущей и проходили ли мы по ней
			if is_correct then -- если можем туда перейти, надо создать веревочку между этими узлами
				self.SelectPos(pos_ind)
				if self.cur_widget then
					_owner.RemoveWidget(self.cur_widget)
				end
				--создаем виджет для таблицы статичных виджетов и растягиваем его между двумя позициями
				local img = self.InitNewLine(_owner, pos_ind)
				local off1 = self.params.positions[self.last_pos]
				local off2 =  self.params.positions[pos_ind]
				
				self.DrawLine(img, off1, off2)
				table.insert(self.widgets, img)
				
				-- запоминаем. что уже прошли по этому ребру и создаем новый тайлящийся виджет
				self.last_pos = pos_ind	
				self.lines[self.accessible_lines[is_correct].num] = 1 -- по ней уже прошли
				self.accessible_lines = self.GetAccessibleLines(pos_ind)
				if #self.accessible_lines == 0 then -- либо зашли в тупик, либо победили
					self.CheckEnd(_owner)
				end
				self.cur_widget = self.InitNewLine(_owner, pos_ind) -- виджет, который растягивается
				self.cur_widget.SetSize(1, self.size.Y)
			end
		else -- создание первой точки пути
			self.SelectPos(pos_ind)
			self.last_pos = pos_ind
			self.accessible_lines = self.GetAccessibleLines(pos_ind)
			if #self.accessible_lines == 0 then -- либо зашли в тупик, либо победили
				self.CheckEnd(_owner)
			end
			self.cur_widget = self.InitNewLine(_owner, pos_ind) -- виджет, который растягивается
			self.cur_widget.SetSize(1, self.size.Y)
		end		
		
	end
	
	return true
end 
-- проверяет, попали ли в позицию
function self.IsPos(_pos)
	for i, pos in ipairs(self.params.positions) do
		if math.abs(_pos.X - pos.X) <= self.params.pos_size.X and math.abs(_pos.Y - pos.Y) <= self.params.pos_size.Y then 
			return i
		end
	end
	return nil
end 

-- для позиции _ind ищет линии, по которым может пойти игрок
function self.GetAccessibleLines(_ind)
	local res = {}
	for i, line in ipairs(self.params.lines) do
		if (line[1] == _ind or line[2] == _ind) and (self.lines[i] == 0) then 
			-- эта линия проходит через вершину _ind , и по ней еще не проводили линию
			table.insert(res, {num = i, line_info = line})
		end
	end
	return res
end 
-- проверяет, ткнули ли мы в вершину, с которой есть связь
function self.IsAccessiblePoint(_ind)
	for i, line in ipairs(self.accessible_lines) do
		if line.line_info[1] == _ind or line.line_info[2] == _ind then
			return i
		end
	end
	return nil
end 
-- параметры = координаты , растягивает виджет между двумя позициями
function self.DrawLine(_widget, _start, _end)
	if _start.X > _end.X then -- _start должен быть левее
		local tmp = _start
		_start = _end
		_end = tmp
	end 
	local tang = nil
	if math.abs(_start.X - _end.X) > 0 then -- вычисляем тангенс угла наклона виджета, если тангенс существует
		tang = (_start.Y - _end.Y)/(_start.X - _end.X) 
	end
	local angle = 0
	if not tang then
		angle = math.pi/2 -- в этом угле тангенс не существует => либо pi/2, либо -pi/2
		if (_start.Y > _end.Y) then
			angle = -1 * angle 
		end
	else
		angle = math.atan(tang) -- вычислям арктангенс, если тангенс нормальный
	end
	
	self.RotateWidget(_widget, angle) -- поворачиваем виджет под нужным углом
	-- растягиваем по длине и перемещаем
	local length = math.sqrt((_start.X - _end.X)*(_start.X - _end.X) + (_start.Y - _end.Y)*(_start.Y - _end.Y))
	local size = _widget.GetSize()
	_widget.SetSize(length, size.Y)
	_widget.SetOffset(_start.X, _start.Y)
end 
-- создает новый виджет с линией и устанавливает ему флаг, что он тайлится
function self.InitNewLine(_owner, _pos)
	local img = sf.gui.CImageWidget(self.params.line_tile, "line", 2, 0)
	local off1 = self.params.positions[_pos]
	self.size = img.GetSize()
	img.SetOffset(off1.X, off1.Y)
	img.GetImage().SetFlags( __or( img.GetImage().GetFlags(), sf.graphics.CImage.FlagBoxImage)) -- картинка должна тайлиться
	_owner.AddWidget(img)
	return img 
end

-- поворачивает виджет _widget на угол _angle 
function self.RotateWidget(_widget, _angle)
	if _angle < 0 then
		_angle = _angle + (math.pi * 2) * (((math.abs(_angle) - (math.abs(_angle) % (math.pi * 2))) / math.pi * 2) + 1)
	end
	if	_angle > math.pi * 2 then
		_angle = _angle % (math.pi * 2)
	end
	_widget.SetRotation(sf.misc.MatrixRotation(_angle, 0, 0))
end 

-- при движении мыши перерисовываем виджет с веревкой
function self.OnMouseMove(_owner, _pos, _keyboard_state, _broadcast)
	if self.win then
		return true
	end

	if self.params.cursor then
		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
	end

	if self.cur_widget then
		local off1 = self.params.positions[self.last_pos]
				
		self.DrawLine(self.cur_widget, off1, _pos)
	end
	return true
end 