--[[игра "Скарабей"
Есть жук, у него на каждой лапке есть три шарнира, вокруг которых можно вращать их. Необходимо выставить их в нужное положение

сохраняемые параметры:
sminigames.save.angles - углы поворота ног, двумерная таблица
]]

scroll_joints = {}
local self = scroll_joints

self.params = {
	leg_id = "leg0", -- начало идентификатора для частей ног.
	step_angle = math.pi / 4, -- шаг поворота сегмента
	win_delay = 1000, -- задержка на победу
	sound_scroll = "spanner_to_pipe", 
	legs = { -- описание всех ножек
		{ -- leg01
			{ -- leg01_01
				pos = sf.misc.FloatVector(345, 183), -- позиция ноги
				rotation_center = sf.misc.FloatVector(42, 9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  3*math.pi/2, -- какой угол в начале
				end_angle =  2*math.pi -- конечный угол поворота лапки
			}, 
			{ -- leg01_02
				pos = sf.misc.FloatVector(340, 222),--sf.misc.FloatVector(340, 159), -- позиция ноги
				rotation_center = sf.misc.FloatVector(10, 9),--sf.misc.FloatVector(8, 67), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  2*math.pi, -- какой угол в начале
				end_angle =  5*math.pi/4 -- конечный угол поворота лапки
			}, 
			{ -- leg01_03
				pos = sf.misc.FloatVector(382, 224), -- позиция ноги
				rotation_center = sf.misc.FloatVector(9, 48), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  math.pi/4, -- какой угол в начале
				end_angle =  2*math.pi -- конечный угол поворота лапки
			}
		},
		{ -- leg02
			{ -- leg02_01
				pos = sf.misc.FloatVector(356, 262), -- позиция ноги
				rotation_center = sf.misc.FloatVector(42, 9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  math.pi/4, -- какой угол в начале
				end_angle =  2*math.pi -- конечный угол поворота лапки
			}, 
			{ -- leg02_02
				pos = sf.misc.FloatVector(315, 299), -- позиция ноги
				rotation_center = sf.misc.FloatVector(42, 9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  3*math.pi/4, -- какой угол в начале
				end_angle =  2*math.pi - math.pi/4 -- конечный угол поворота лапки
			}, 
			{ -- leg02_03
				pos = sf.misc.FloatVector(280, 297), -- позиция ноги
				rotation_center = sf.misc.FloatVector(39, 47), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  3*math.pi/4, -- какой угол в начале
				end_angle =  2*math.pi - 6*math.pi/4 -- конечный угол поворота лапки
			}
		},
		{ -- leg03
			{ -- leg03_01
				pos = sf.misc.FloatVector(365, 422), -- позиция ноги
				rotation_center = sf.misc.FloatVector(42, 9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  2*math.pi, -- какой угол в начале
				end_angle =  math.pi/2 -- конечный угол поворота лапки
			}, 
			{ -- leg03_02
				pos = sf.misc.FloatVector(332, 459), -- позиция ноги
				rotation_center = sf.misc.FloatVector(42, 9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  math.pi/2, -- какой угол в начале
				end_angle =  2*math.pi - math.pi/4 -- конечный угол поворота лапки
			}, 
			{ -- leg03_03
				pos = sf.misc.FloatVector(294, 468), -- позиция ноги
				rotation_center = sf.misc.FloatVector(38, 38), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  math.pi, -- какой угол в начале
				end_angle =  math.pi -- конечный угол поворота лапки
			}
		},
		{ -- leg04
			{ -- leg04_01
				pos = sf.misc.FloatVector(594, 425), -- позиция ноги
				rotation_center = sf.misc.FloatVector(9, 9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  3*math.pi/4, -- какой угол в начале
				end_angle =  3*math.pi/2 -- конечный угол поворота лапки
			}, 
			{ -- leg04_02
				pos = sf.misc.FloatVector(631, 464), -- позиция ноги
				rotation_center = sf.misc.FloatVector(9,9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  2*math.pi/4, -- какой угол в начале
				end_angle =  math.pi/4 -- конечный угол поворота лапки
			}, 
			{ -- leg04_03
				pos = sf.misc.FloatVector(645, 505), -- позиция ноги
				rotation_center = sf.misc.FloatVector(36, 11), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  2*math.pi, -- какой угол в начале
				end_angle =  2*math.pi -- конечный угол поворота лапки
			}
		},
		{ -- leg05
			{ -- leg05_01
				pos = sf.misc.FloatVector(603, 269), -- позиция ноги
				rotation_center = sf.misc.FloatVector(9, 9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  2*math.pi, -- какой угол в начале
				end_angle =  2*math.pi-- конечный угол поворота лапки
			}, 
			{ -- leg05_02
				pos = sf.misc.FloatVector(645, 310), -- позиция ноги
				rotation_center = sf.misc.FloatVector(9,10), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  math.pi - math.pi/4, -- какой угол в начале
				end_angle =  2*math.pi + math.pi/4 -- конечный угол поворота лапки
			}, 
			{ -- leg05_03
				pos = sf.misc.FloatVector(685, 310), -- позиция ноги
				rotation_center = sf.misc.FloatVector(9, 48), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  math.pi/4  + math.pi/4, -- какой угол в начале
				end_angle =  2*math.pi - 2*math.pi/4 -- конечный угол поворота лапки
			}
		},
		{ -- leg06
			{ -- leg06_01
				pos = sf.misc.FloatVector(614, 190), -- позиция ноги
				rotation_center = sf.misc.FloatVector(9, 9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  6*math.pi/4, -- какой угол в начале
				end_angle =  2*math.pi -- конечный угол поворота лапки
			}, 
			{ -- leg06_02
				pos = sf.misc.FloatVector(620, 230), -- позиция ноги
				rotation_center = sf.misc.FloatVector(42, 9), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  4*math.pi/4, -- какой угол в начале
				end_angle = 3*math.pi/4  -- конечный угол поворота лапки
			}, 
			{ -- leg06_03
				pos = sf.misc.FloatVector(583, 226), -- позиция ноги
				rotation_center = sf.misc.FloatVector(39, 47), -- вокруг какой точки вращаем картинку (смещение относительно левого верхнего угла картинки с сегментом)
				start_angle =  3*math.pi/4, -- какой угол в начале
				end_angle =  2*math.pi -- конечный угол поворота лапки
			}
		}
	}
}

function self.Init(_owner) 
	sminigames.SetStandartScriptName(_owner, scroll_joints) 
	
	self.LoadInfo(_owner)
end 

function self.LoadInfo(_owner)
	self.legs = {}
		for i = 1, #self.params.legs do
			local obj = {}
			for j = 1, #self.params.legs[i] do
				local img = __cast(_owner.GetWidget(self.params.leg_id..i.."_"..j), sf.gui.CImageWidget)
				__assert(img, "нет image_widget с id="..self.params.leg_id..i.."_"..j)
			
				img.SetOffset(self.params.legs[i][j].pos.X, self.params.legs[i][j].pos.Y)
				local o = {
						image = img, 
						center = self.params.legs[i][j].rotation_center, 
						angle = 0
						--joint = self.params.legs[i][j].joint, 
						--joint_pos = self.params.legs[i][j].joint_pos
				}
				table.insert(obj, o)
			end
			table.insert(self.legs, obj)
		end
	
	-- поворачиваем ноги
	for i = 1, #self.params.legs do
		for j = 1, #self.params.legs[i] do
			local start_angle = self.NormalizeAngle(self.params.legs[i][j].start_angle)
			if sminigames.save then
				start_angle = sminigames.save.angles[i][j]
			end
			while (math.abs(start_angle - self.legs[i][j].angle) > math.pi/20) do
				self.RotateLeg(i, j, 1)
			end
		end
	end
	self.win = nil
	self.timer = __create_timer("", "qe_level")
	-- если еще не сохраняли, создадим переменную для сохранения
	if not sminigames.save then
		sminigames.save = {angles = {}}
		local legs_angles = {}
		for i = 1, #self.params.legs do
			local angles = {}
			for j = 1, #self.params.legs[i] do
				table.insert(angles, self.legs[i][j].angle)
			end
			table.insert(legs_angles, angles)
		end
		sminigames.save.angles = legs_angles
	end
end 


function self.GetUnrotatedPoint(_pos, _angle, _center)
	return _pos * sf.misc.MatrixRotation(-_angle, _center.X, _center.Y)	
end

function self.IsLeg(_pos)
	for i = 1, #self.legs do
		local j = #self.legs[i]
		while j > 0 do
			local rot_center = self.legs[i][j].image.GetOffset() + self.legs[i][j].center
			local unrot = self.GetUnrotatedPoint(_pos, self.legs[i][j].angle, rot_center)-- учитываем поворот виджета
			local o_x = self.legs[i][j].image.GetOffset().X
			local o_y =	self.legs[i][j].image.GetOffset().Y
			if misc.GetRect(self.legs[i][j].image).IsContains(unrot.X, unrot.Y) and 
				sminigames.IsVisiblePoint(self.legs[i][j].image.GetImage(), unrot.X - o_x, unrot.Y - o_y) then
				-- попали в объект
					return {i, j} -- нога, номер сустава
			end
			
			j = j - 1
		end
	end
end
-- поворачивает сустав _joint ноги _leg на угол self.params.step_angle
-- _flag указывает, в какую сторону вращаем, может быть равен 1 или -1
function self.RotateLeg(_leg, _joint, _flag)
	local center = self.legs[_leg][_joint].center
	local main_center = center + self.legs[_leg][_joint].image.GetOffset() -- центр вращения лапки, в которую ткнули
	local k = 0
	while _joint + k <= #self.legs[_leg] do 
		-- поворачиваем лапку и все, что с ней соединено
		local rot_center = self.legs[_leg][_joint + k].image.GetOffset() + self.legs[_leg][_joint + k].center
		
		local new_center = self.GetUnrotatedPoint(rot_center, -_flag *self.params.step_angle, main_center) -- вычисляем, куда перейдет центр лапки при повороте
		local new_offset = new_center - self.legs[_leg][_joint + k].center
		self.legs[_leg][_joint + k].image.SetOffset(new_offset.X, new_offset.Y)
		
		local k_angle = self.legs[_leg][_joint + k].angle + _flag *self.params.step_angle
		k_angle = self.NormalizeAngle(k_angle)
		local k_center = self.legs[_leg][_joint + k].center
		self.legs[_leg][_joint + k].angle = k_angle
		self.legs[_leg][_joint + k].image.SetRotation(sf.misc.MatrixRotation(k_angle, k_center.X, k_center.Y))
		
		k = k + 1
	end
end

function self.SaveAngles()
	for i = 1, #self.params.legs do
		for j = 1, #self.params.legs[i] do
			sminigames.save.angles[i][j] = self.legs[i][j].angle
		end
	end
end

function self.OnMouseDown(_owner, _pos, _button, _keyboard_state, _broadcast)
	local cur_leg = self.IsLeg(_pos)
	if cur_leg then
		if _button == sf.gui.CBaseWidget.LeftButton then
			self.RotateLeg(cur_leg[1], cur_leg[2], 1) -- по часовой стрелке
			self.SaveAngles()
			if self.params.sound_scroll then
				sound(self.params.sound_scroll, false)
			end
	--[[			else
			self.RotateLeg(cur_leg[1], cur_leg[2], -1) -- против часовой стрелки]]
			self.CheckEnd(_owner)
		end
	end
	return true
end 

function self.NormalizeAngle(_angle)
	local k_angle1 = _angle
	if k_angle1 < 0 then
		k_angle1 = k_angle1 + (math.pi * 2) * (((math.abs(k_angle1) - (math.abs(k_angle1) % (math.pi * 2))) / (math.pi * 2)) + 1)
	end
	if	math.abs(math.abs(k_angle1) - math.pi * 2) >= math.pi/40  then
		k_angle1 = k_angle1 % (math.pi * 2)
	end
--	__message("start=".._angle.." end="..k_angle1)
	return k_angle1
end

function self.CheckEnd(_owner)
	for i = 1, #self.legs do
		for l = 1, #self.legs[i] do
		
		local k_angle1 = self.NormalizeAngle(self.legs[i][l].angle)
		local k_angle2 = self.NormalizeAngle(self.params.legs[i][l].end_angle)
		
			if math.abs(k_angle2 - k_angle1) >= math.pi/20 then
		--		__message("нога "..i.." сустав "..l.." угол поворота "..k_angle1.." а нужен "..k_angle2 )
				return false
			end
		end
	end
	
	self.win = true
	self.start_win = self.timer.Get().GetTime()
end 

function self.OnUpdate(_owner)
	if  sf.core.g_Application.GetTimeManager().GetTimer(_T("qe_level")).GetK() < 0.01 then
		return
	end

	if not self.win then return end
	if self.timer.Get().GetTime() - self.start_win > self.params.win_delay then
		_owner.SetGameResult(1)
		_owner.OnEndGame()	
	end
end 