assemble_image_circle_click = {}
local self = assemble_image_circle_click

self.params = 
{
	step_count = 10,  -- количество разных положений кольца (определяет величину одного поворота)
	sound_rotation = "rotation_ring",
	sound_right = "",
	check_immediately = false,

	on_win_delay = 0, -- задержка экрана после победы
	speed = 3, -- скорость вращения колец (градусы в секунду)
	dependence = { -- настройка зависимостей колец друг от друга
		{ -- первое кольцо
			{num = 3, dif_angle = -3} -- на сколько сегментов сдвигается кольцо в номером 3 при нажатии на кольцо номер 1
		}, 
		{ -- второе кольцо
			{num = 3, dif_angle = 4}, 
			{num = 4, dif_angle = 2}
		},
		{ -- третье кольцо
			{num = 4, dif_angle = -5},
			{num = 6, dif_angle = 2}
		},		
		{ -- четвертое кольцо
			{num = 3, dif_angle = -3},
			{num = 1, dif_angle = 2}			
		},
		{ -- пятое кольцо
			{num = 2, dif_angle = -3},
			{num = 5, dif_angle = 1} 			
		},
		{ --шестое кольцо ничего не поворачивает
			
		}
	}
}
--[[
function self.OnPreferredSize(_owner)
	return sminigames.OnPreferredSize(_owner)
end]]

-- обработать двойной клик как одинарный
function self.OnDoubleClick(_owner, _pos, _state, _broadcast)
	return self.OnMouseDown(_owner, _pos, sf.gui.CBaseWidget.LeftButton,_state, _broadcast)
end

function self.OnMouseDown(_owner, _pos, _button, _state, _broadcast)
    local index = 1
	-- проверяем, не попали ли мы в какое-нибудь кольцо
    while index <= #self.data.array do
        if  misc.GetRect(self.data.array[index].widget).IsContains(_pos.X, _pos.Y) and 
			sminigames.IsVisiblePoint(self.data.array[index].widget.GetImage(), _pos.X - self.data.array[index].widget.GetOffset().X, _pos.Y - self.data.array[index].widget.GetOffset().Y) 
			and (index == self.is_moving or self.is_moving < 0) then
				local second
				local mov_ind = self.IsMoving(index)
				
				if _button == sf.gui.CBaseWidget.LeftButton then -- поворачиваем по или против часовой стрелки в зависимости от нажатой кнопки мыши
					if not mov_ind then
						second = self.data.array[index].angle + 2*math.pi/self.params.step_count
					else
						self.new_angles[mov_ind].angle = self.new_angles[mov_ind].angle + 2*math.pi/self.params.step_count
					end
				elseif _button == sf.gui.CBaseWidget.RightButton then
					if not mov_ind then
						second = self.data.array[index].angle - 2*math.pi/self.params.step_count
					else
						self.new_angles[mov_ind].angle = self.new_angles[mov_ind].angle - 2*math.pi/self.params.step_count
					end
				end
				if not mov_ind then
					local obj1 = {num = index, angle = second, active = not mov_ind}
				
					table.insert(self.new_angles, obj1)
					local first 
					if not mov_ind then 
						first = self.data.array[index].angle
					else
						first = self.new_angles[mov_ind].angle
					end
					local obj2 = {num = index, angle = first, start = self.timer.Get().GetTime()}
					table.insert(self.start_angles, obj2)

				-- поворачиваем зависящие от кольца кольца
					local i, n = 1, #self.params.dependence[index]
					while i<= n do
						local is_mov = self.IsMoving(self.params.dependence[index][i].num)
						if not is_mov then
							-- номер зависимого кольца
							local ind = self.params.dependence[index][i].num
						
							-- величина сдвига
							local diff = 2*math.pi/self.params.step_count * self.params.dependence[index][i].dif_angle 
							local new_angle = self.data.array[ind].angle + diff
						
							local first_ang = self.data.array[ind].angle
							local obj1 = {num = ind, angle = new_angle, active = not is_mov }
							table.insert(self.new_angles, obj1)
							local obj2 = {num = ind, angle = first_ang, start = self.timer.Get().GetTime()}
							table.insert(self.start_angles, obj2) -- запоминаем начальный угол
						end
						i = i + 1
					end
					self.is_moving = index
				end
				self.RefreshAngles()
				return true
        end
        index = index + 1
    end
    return false
end

function self.CheckEnd(_owner)
	local flag = true

	for	index in pairs(self.data.array) do
        local data_angle = self.data.angle
        local data_angle2 = math.pi * 2 - self.data.angle
        local angle = self.data.array[index].angle
		if	self.data.array[index].angle > self.data.angle and self.data.array[index].angle < math.pi * 2 - self.data.angle then
			flag = false
			break
		end
	end
	if	flag then
		if self.widgets then
			for _, w in pairs(self.widgets) do
				sminigames.ImageDropBuffer(w.GetImage())
			end
			self.widgets = nil
		end
		
		self.win = self.timer.Get().GetTime()
	end
end
-- установить угол поворота у кольца с номером _index
function self.SetAngle(_index, _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
	self.data.array[_index].angle = _angle
	self.data.array[_index].widget.SetRotation(sf.misc.MatrixRotation(_angle, self.data.array[_index].widget.GetSize().X / 2, self.data.array[_index].widget.GetSize().Y / 2))
end

function self.Load(_owner, _data)
	self.data = _data	
	sminigames.SetStandartScriptName(_owner, assemble_image_circle_click)
	local iterator = _owner.GetWidgets()
	_data.center_x = 0
	_data.center_y = 0
	_data.array = {}
	
	self.widgets = {}
	
	-- Поиск всех изображений
	while iterator.IsEnd() == false do
		local widget = __cast(iterator.Get(), sf.gui.CImageWidget)
		if  widget and widget.GetId() == _T("circle") then
			table.insert(self.widgets, widget)
			local index = #_data.array + 1				
			_data.array[index] = {}
			_data.array[index].widget = widget
			_data.center_x = math.max(_data.center_x, widget.GetSize().X / 2)
			_data.center_y = math.max(_data.center_y, widget.GetSize().Y / 2)
		end
        iterator.Next()
	end
	-- Сортировка по размеру (X компанента) по убыванию
	local i1 = 1
	while i1 <= #_data.array do
		local i2 = i1 + 1
		while i2 <= #_data.array do
			if _data.array[i1].widget.GetSize().X < _data.array[i2].widget.GetSize().X then
				local temp = _data.array[i1]
				_data.array[i1] = _data.array[i2]
				_data.array[i2] = temp 
			end
			i2 = i2 + 1
		end
		i1 = i1 + 1
	end
    -- Расстановка по местам и выставление Z-уровня
	index = 1
	while index <= #_data.array do
		misc.MoveCenterTo(_data.array[index].widget, _data.center_x, _data.center_y)
		_data.array[index].widget.SetLayer(index)
        index = index + 1
	end
	-- Случайный поворот картинок
	math.randomseed(os.time())
	index = 1
	while index <= #_data.array do
		local new_angle = 2*math.pi/self.params.step_count * random(1, self.params.step_count)
		self.SetAngle(index, new_angle)
        index = index + 1
	end

    --[[local size = _owner.GetPreferredSize()
	_owner.SetSize(size.X, size.Y)]]
end

function self.Init(_owner)
	local data = {}
	data.angle = math.pi / 180 * 6
	
	self.sound_time = 0
		
	self.Load(_owner, data)
	
	self.timer = __create_timer("", "qe_level")
	self.win = -1 -- время победы
	
	self.is_moving = -1 -- кольца сейчас  не вращаются
	self.new_angles = {}
	self.start_angles = {}
	self.last_start = 0 -- начало последнего движения

end

function self.OnUpdate(_owner)
	if self.win == -1 then 
		if  self.is_moving < 0 then
			return 
		else
			if self.params.sound_rotation then
				sound(self.params.sound_rotation)
			end
			-- анимируем движение - вычисляем для всех движущихся колец новый угол в данный момент времени
			local flag = true
			local i, n = 1, #self.new_angles
			while i <= n do
				
				local k = self.new_angles[i].num
				local need_time = math.abs(self.new_angles[i].angle - self.start_angles[i].angle) / self.params.speed * 1000
				
				local current_time = (self.timer.Get().GetTime() - self.start_angles[i].start)/need_time
				local flag_delete = false -- если надо будет завершить движение
				if current_time > 1 then
					flag_delete = true
					current_time = 1  -- мы не можем зайти дальше 
				else
					flag = false
				end
				local cur_angle

				cur_angle = self.start_angles[i].angle +  (self.new_angles[i].angle - self.start_angles[i].angle) * current_time
				if self.new_angles[i].active then
					self.SetAngle(k, cur_angle)
				end
				if flag_delete then
						table.remove( self.start_angles, i)
						table.remove( self.new_angles, i)
						n = n - 1
				else
					i = i + 1
				end
			end
			
			-- проверяем, не закончилось ли время
			if #self.new_angles == 0 then
				self.is_moving = -1 -- кольца сейчас  не вращаются
				self.new_angles = {}
				self.start_angles = {}
				self.last_start = 0 -- начало последнего движения
				
				self.CheckEnd(_owner)
			end
			return
		end	
	end
	
	if self.timer.Get().GetTime() - self.win >= self.params.on_win_delay then
		_owner.SetGameResult(1)
		_owner.OnEndGame()
	end
	return
end

-- проверяет, движется ли уже это кольцо
function self.IsMoving(_index)
	if self.new_angle then
		for i = 1, #self.new_angle do
			if self.new_angle[i].num == _index and self.new_angle[i].active then
				return i
			end
		end
	end
	return nil
end

-- корректирует значения углов прибытия
function self.RefreshAngles()
	local step = 2*math.pi/self.params.step_count
	for k = 1, #self.new_angles do
		if math.floor(self.new_angles[k].angle/step) ~= math.ceil(self.new_angles[k].angle/step)  then
			-- перемещаем углы на фиксированные на круге точки
			local t = self.new_angles[k].angle/step - math.floor(self.new_angles[k].angle/step)
			local corr_ang = math.floor(self.new_angles[k].angle/step) * step
			if t > 0.5 then
				corr_ang = math.ceil(self.new_angles[k].angle/step) * step
			end
			self.new_angles[k].angle = corr_ang
		end
	end
	return
end
