assemble_image_circle = {}
local self = assemble_image_circle
self.params = 
{
	cursor = "gui_cursors_rotation",
	sound_step_angle = math.pi / 10.0,
	sound_step_time = 100, -- не больше одного раза в заданное время
	sound_rotation = "rotation_ring",
	sound_right = "",
	check_immediately = false,
	clip_on_win = "",
	
	-- цвет правильно расположенного кольца
	color_in_place = sf.graphics.Color(255, 255, 255, 255),
	
	-- цвет НЕправильно расположенного кольца
	color_out_place = sf.graphics.Color(255, 160, 200, 255)
}

function self.UpdateColors()
	if not self.params.color_in_place or not self.params.color_out_place then
		return
	end	
	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
		local color = self.params.color_in_place
		if	self.data.array[index].angle > self.data.angle and self.data.array[index].angle < math.pi * 2 - self.data.angle then
			color = self.params.color_out_place
		end
		self.data.array[index].widget.SetColor(color)
	end
end

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

function self.UpdateCursor(_show, _pos)
	if _show and self.cursor.GetImage().GetTexture() then
		local p1 = sf.misc.FloatVector(100.0, -100.0)
		local p2 = sf.misc.FloatVector(_pos.X - self.data.center_x, _pos.Y - self.data.center_y)
		
		local a = sf.misc.CalculateFloatVectorModule(p1)
		local b = sf.misc.CalculateFloatVectorModule(p2)
		local c = sf.misc.CalculateFloatVectorModule(p1-p2)

		local cos_a = (a*a + b*b - c*c) / (2.0 * a*b)
		if cos_a > 1.0 then cos_a = 1.0 end		
		if cos_a < -1.0 then cos_a = -1.0 end		
		local angle = math.acos(cos_a)
		
		local _p1 = p2 * sf.misc.MatrixRotation(angle, 0.0, 0.0)
		local _p2 = p2 * sf.misc.MatrixRotation(-angle, 0.0, 0.0)
		
		if (p1-_p2).ModSqr() < (p1-_p1).ModSqr() then
			angle = angle * -1.0
		end
			
		local size = self.cursor.GetSize()
		local offset = self.cursor.GetOffset()
		local matrix = sf.misc.MatrixTranslation(-offset.X - size.X / 2.0, -offset.Y - size.Y / 2.0)
		matrix = matrix * sf.misc.MatrixRotation(-angle, 0.0, 0.0)
		matrix = matrix * sf.misc.MatrixTranslation(_pos.X, _pos.Y)
		self.cursor.SetRotation(matrix)
		
		self.cursor.RemFlags(sf.gui.CBaseWidget.FlagHidden)
		
		sf.gui.g_Cursor.Instance().SetCursor(sf.gui.CCursor.CursorNone)
	else
		self.cursor.AddFlags(sf.gui.CBaseWidget.FlagHidden)
	end
end

function self.OnMouseMove(_owner, _pos, _button, _state, _broadcast)
	local show_cursor_rotation = false
	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) then
				show_cursor_rotation = true
				break				
		end
		index = index + 1
	end
	self.UpdateCursor(show_cursor_rotation or self.drag_index, _pos)
    if  _button == sf.gui.CBaseWidget.LeftButton then		
		if  self.drag_index then
			local angle = sf.misc.GetAngle(
                sf.misc.FloatVector(self.data.center_x, self.data.center_y),
                self.start_pos,
                _pos)
            if  angle.first then
                self.SetAngle(self.drag_index, self.start_angle - angle.second)
            end
			
			local curr_time = self.timer.Get().GetTime()
			if (not self.sound_id or not sf.core.g_Application.GetAudioManager().IsSound(self.sound_id) or 
				math.abs(self.sound_angle - angle.second) >= self.params.sound_step_angle) and
				(not self.sound_time or (curr_time - self.sound_time) >= self.params.sound_step_time) then
					self.sound_id = 
						sf.core.g_Application.GetAudioManager().Play(self.params.sound_rotation, -2, -2, -2, -2, -2)
					self.sound_angle = angle.second			
					self.sound_time = curr_time
			end
			
			if self.params.check_immediately then
				self.UpdateColors()
				self.CheckEnd(_owner)
			end
        end
	end
    return false
end

function self.OnMouseDown(_owner, _pos, _button, _state, _broadcast)
    if  _button == sf.gui.CBaseWidget.LeftButton then
        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) then
	                self.start_pos = sf.misc.FloatVector(_pos.X, _pos.Y)
					self.drag_index = index
					self.start_angle = self.data.array[index].angle
					return true
            end
            index = index + 1
        end
    end
    self.drag_index = nil
    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
		if not self.clip_on_win then
			_owner.SetGameResult(1)
			_owner.OnEndGame()
		else
			self.win = true
			self.win_start = self.timer.Get().GetTime()
			self.clip_on_win.RemFlags(sf.gui.CWidget.FlagHidden)
			self.clip_on_win.GetClip().Play()
		end
	end
end

function self.OnUpdate(_owner)
	if self.win then
		local clip = self.clip_on_win.GetClip()
		local now = self.timer.Get().GetTime()
		if (now - self.win_start) >= qe.GetClipTime(clip) then
			_owner.SetGameResult(1)
			_owner.OnEndGame()
		end
	end
	return true
end

function self.OnMouseUp(_owner, _pos, _button, _state, _broadcast)
    if  _button == sf.gui.CBaseWidget.LeftButton then
		-- проверяем, встало ли кольцо на место
		local item = self.data.array[self.drag_index]
		if item then
			if	not (item.angle > self.data.angle and item.angle < math.pi * 2 - self.data.angle) then
				if self.params.sound_right then
					sf.core.g_Application.GetAudioManager().Play(self.params.sound_right, -2, -2, -2, -2, -2)
				end
			end
		end
        self.drag_index = nil
		self.UpdateColors()
		self.CheckEnd(_owner)
        return true
    end
    return false
end

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)
	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 angle = math.random(math.pi * 2 * 200) / 200
		while not(angle > self.data.angle and angle < math.pi * 2 - self.data.angle) do
			angle = math.random(math.pi * 2 * 200) / 200
		end
		self.SetAngle(index, angle)
        index = index + 1
	end
--	self.SetAngle(1, 15)
    local size = _owner.GetPreferredSize()
	_owner.SetSize(size.X, size.Y)
	if self.params.clip_on_win then
		self.clip_on_win = __cast(_owner.GetWidget(self.params.clip_on_win, true), sf.gui.CClipWidget)
		--[[if not self.clip_on_win then
			self.clip_on_win = __cast(_owner.GetWidget(self.params.clip_on_win, true), sf.gui.CImageWidget)
		end]]
		if self.clip_on_win then
			self.clip_on_win.AddFlags(sf.gui.CWidget.FlagHidden)
		end
		self.win = nil
	end
end

function self.Init(_owner)
	local data = {}
	data.angle = math.pi / 180 * 5
	
	self.sound_time = 0
		
	self.Load(_owner, data)
	
	local cursor_widget = sf.gui.CImageWidget(_T(self.params.cursor), _T(""), -1, 0)
	cursor_widget.AddFlags(sf.gui.CBaseWidget.FlagHidden)
	local cursor_wudget_ptr = sf.gui.CImageWidgetPtrT(cursor_widget)
	_owner.AddWidget(cursor_wudget_ptr)
	self.cursor = cursor_widget
	
	self.timer = __create_timer("", "qe_level")
	
	self.UpdateColors()
end
