scene3_open_box = 
{
	password = { 4, 6, 5, 3, 1, 2 },
	
	sequences = 
	{
		{1, 2, 3, 6, 5, 4},
		{1, 4, 6, 3, 5, 2},
		{5, 3, 6, 1, 4, 2}
	},
	
	pause_before_show_sequence = 500,
	show_sequence_part_time = 300
}

local enter_password = {}
local repeat_sequence = {}


function scene3_open_box.CallStateFunc(_func, ...)
	if scene3_open_box.state and scene3_open_box.state[_func] then 
		return scene3_open_box.state[_func](...) 
	end
end

function scene3_open_box.OnMouseDown(_owner, _pos, _button, _state, _broadcast)
	if scene3_open_box.CallStateFunc("OnMouseDown", _owner, _pos, _button, _state, _broadcast) then return true end
	return false
end

function scene3_open_box.OnMouseMove(_owner, _pos, _state, _broadcast)
	if scene3_open_box.CallStateFunc("OnMouseMove", _owner, _pos, _state, _broadcast) then return true end
	return false
end

function scene3_open_box.OnChildAction(_owner, _action, _child)
	scene3_open_box.CallStateFunc("OnChildAction", _owner, _action, _child)
end

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

function scene3_open_box.OnUpdate(_owner)
	scene3_open_box.CallStateFunc("OnUpdate", _owner)
end

function scene3_open_box.SetCurrentState(_state, _owner)
	scene3_open_box.state = _state
	scene3_open_box.CallStateFunc("Start", _owner)
end

function scene3_open_box.ChangeState(_owner)
	if scene3_open_box.state==scene3_open_box.enter_password then
		scene3_open_box.SetCurrentState(scene3_open_box.repeat_sequence, _owner)
	elseif scene3_open_box.state==scene3_open_box.repeat_sequence then
		scene3_open_box.state = nil
		-- закончить миниигру сразу после повторения последней последовательности
		_owner.SetGameResult(1)
		_owner.OnEndGame()
	else assert(false) end
end

function scene3_open_box.Init(_owner)
	scene3_open_box.enter_password.Init(_owner)
	scene3_open_box.repeat_sequence.Init(_owner)
	
	sminigames.SetStandartScriptName(_owner, scene3_open_box)
	
	scene3_open_box.SetCurrentState(scene3_open_box.enter_password, _owner)
end



-- ENTER PASSWORD ON MOUSE
scene3_open_box.enter_password = enter_password

function enter_password.OnChildAction(_owner, _action, _child)
	if _action.c_str()=="pressed" then
		local number = tonumber(_child.GetId().c_str())
		if number then 
			assert(enter_password.buttons[number])
			
			enter_password.OnButtonPressed(number, _owner)
		end
	end
end

function enter_password.OnButtonPressed(_number, _owner)
	assert(#enter_password.current_input < #enter_password.password)
	
	local button = enter_password.buttons[_number]
	assert(button.GetButtonState()~=sf.gui.CButtonWidget.StateDisabled)
	button.DisableButton(true)
	
	table.insert(enter_password.current_input, _number)
	if #enter_password.current_input == #enter_password.password then
		local right_input = true
		for i = 1,#enter_password.current_input do
			if enter_password.current_input[i]~=enter_password.password[i] then
				right_input = false
				break
			end
		end
		
		enter_password.current_input = {}
		for _,b in ipairs(enter_password.buttons) do
			b.DisableButton(false)
		end
		
		if right_input then
			scene3_open_box.ChangeState(_owner)
		end	
	end
end

function enter_password.Load(_owner)
	local w, count = _owner.GetWidgets(), 0
	while not w.IsEnd() do
		local widget = w.Get()
		local number = tonumber(widget.GetId().c_str())
		if number then 
			enter_password.buttons[number] = __cast(widget, sf.gui.CButtonWidget)
			assert(enter_password.buttons[number])
			count = count + 1
		end
		w.Next()
	end
	
	-- проверяем, чтобы не была пропущена кнопка, т.е. не было так: id кнопок - 1,2,3,5
	local test_distribution = function() 
		for i = 1,count do 
			if not enter_password.buttons[i] then return false end
		end
		return true
	end
	assert(test_distribution())
end

function enter_password.Init(_owner)
	enter_password.buttons = {}
	enter_password.current_input = {}
	enter_password.password = scene3_open_box.password
	
	enter_password.Load(_owner)
end


-- REPEAT SEQUENCE
scene3_open_box.repeat_sequence = repeat_sequence

repeat_sequence.enum = {}
repeat_sequence.enum.before_show = 1
repeat_sequence.enum.show_sequence = 2
repeat_sequence.enum.play = 3

function repeat_sequence.DisableButtons(_owner, _flag)
	local w = _owner.GetWidgets()
    while w.IsEnd() == false do
        local button = __cast(w.Get(), sf.gui.CButtonWidget)
        if  button then
			button.DisableButton(false)
            if _flag == true then
                button.AddFlags(sf.gui.CBaseWidget.FlagDisabled)
            else
                button.RemFlags(sf.gui.CBaseWidget.FlagDisabled)
            end
        end
        w.Next()
    end
	if not _flag then _owner.OnMouseMove(sf.misc.IntVector(-1000,-1000), 0, true) end
end

function repeat_sequence.SetState(_state, _owner)
	if _state==repeat_sequence.enum.before_show then
		repeat_sequence.DisableButtons(_owner, true)
		repeat_sequence.next_action_time = repeat_sequence.timer.Get().GetTime() + repeat_sequence.pre_show_time
	elseif _state==repeat_sequence.enum.show_sequence then
		repeat_sequence.index = 0
	elseif _state==repeat_sequence.enum.play then
		repeat_sequence.DisableButtons(_owner, false)
		repeat_sequence.input = {}
	end
	
	repeat_sequence.state = _state
end

function repeat_sequence.LightSequencePart(_owner, _index, _light)
	local button = __cast(_owner.GetWidget(tostring(repeat_sequence.sequence[_index]), true), sf.gui.CButtonWidget)
	assert(button)
	button.DisableButton(_light)
end

function repeat_sequence.ShowNextSequencePart(_owner)

	local sequence = repeat_sequence.sequence
	
	if repeat_sequence.index > 0 then
		repeat_sequence.LightSequencePart(_owner, repeat_sequence.index, false)
	end
	
	if #sequence <= repeat_sequence.index then
		-- последовательность закончилась
		return false
	end
	
	repeat_sequence.index = repeat_sequence.index + 1
	repeat_sequence.LightSequencePart(_owner, repeat_sequence.index, true)
	
	repeat_sequence.next_action_time = repeat_sequence.timer.Get().GetTime() + repeat_sequence.part_show_time
	return true
end

function repeat_sequence.OnUpdate(_owner)
	local current_time = repeat_sequence.timer.Get().GetTime()
	
	if repeat_sequence.next_action_time > current_time then return end
	
    if repeat_sequence.state == repeat_sequence.enum.before_show then
		-- pause before show
		repeat_sequence.SetState(repeat_sequence.enum.show_sequence, _owner)
	elseif repeat_sequence.state == repeat_sequence.enum.show_sequence then
		-- show sequence
		if not repeat_sequence.ShowNextSequencePart(_owner) then
			repeat_sequence.SetState(repeat_sequence.enum.play, _owner)
		end
    end
end

function repeat_sequence.OnInput(_owner, _number, _widget)
	assert(#repeat_sequence.input < #repeat_sequence.sequence)
	
	table.insert(repeat_sequence.input, _number)
	
	for i,_ in ipairs(repeat_sequence.input) do
		if repeat_sequence.input[i]~=repeat_sequence.sequence[i] then
			repeat_sequence.SetState(repeat_sequence.enum.before_show, _owner)
			return
		end
	end
	
	local button = __cast(_widget, sf.gui.CButtonWidget)
	assert(button)
	button.DisableButton(true)
	
	if #repeat_sequence.input == #repeat_sequence.sequence then
		-- ввели все правильно
		if repeat_sequence.current_sequence >= #scene3_open_box.sequences then
			-- это была последняя последовательность
			scene3_open_box.ChangeState(_owner)
		else
			-- показываем следующую последовательность
			repeat_sequence.current_sequence = repeat_sequence.current_sequence + 1
			repeat_sequence.sequence = scene3_open_box.sequences[repeat_sequence.current_sequence]
			repeat_sequence.SetState(repeat_sequence.enum.before_show, _owner)
		end
	end
end

function repeat_sequence.OnChildAction(_owner, _action, _child)
	if	repeat_sequence.state == repeat_sequence.enum.play then
		if	_action.c_str() == "pressed" then
			local number = tonumber(_child.GetId().c_str())
			if number then
				-- нажали кнопку с ид "1","2","3"...
				repeat_sequence.OnInput(_owner, number, _child)
			end
		end
	end
end

function repeat_sequence.Start(_owner)
	repeat_sequence.SetState(repeat_sequence.enum.before_show, _owner)
end

function repeat_sequence.Load(_owner)
end

function repeat_sequence.Init(_owner)
	repeat_sequence.timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().AttachTimer(_T(""), nil))
	
	assert(#scene3_open_box.sequences>0)
	repeat_sequence.current_sequence = 1
	repeat_sequence.sequence = scene3_open_box.sequences[1]
	repeat_sequence.pre_show_time = scene3_open_box.pause_before_show_sequence
	repeat_sequence.part_show_time = scene3_open_box.show_sequence_part_time
	
    repeat_sequence.Load(_owner)
end
