game_window = {}
game_window.actions = {}

game_window._hint_tutorial_pre_delay = 30000   -- время без ходов через которое покажется туториал на хинт
game_window._drop_tutorial_pre_delay = 60000   -- время без ходов через которое покажется туториал на сброс
game_window._drop_gems_max_to_win = 3   -- число камней, котоыре остались до победы при которых отображается туториал на сброс
game_window._player_level_for_tutorial = 4   -- уровень игрока при достижении которого покажется туториал на уровень игрока


game_window._hint_show_time = 5000   -- время отображения хинта(возможно потом будет перенесено)
game_window._hint_resume_time = 8000 -- время восстановления подсказки
game_window._auto_save_time = 20000  -- время автосохранения снепшота играы в файл
game_window._game_field_center = {660,378} -- центр игрового поля (используется для центрирования окна статистики отностиельно игрового поля)


game_window._first_move_tutorial_delay = 3000                          -- время перед туториалом на первый ход
game_window._first_move_tutorial_cap_type = s11.CFieldCap.CapTypeGreen   -- тип фишки на который будет показан тутуориал на превый ход

game_window._up_level_effect_id = "LevelUp"
game_window._up_level_effect_pos = sf.misc.FloatVector(202,128)

-- время которое прошло с момоента прошлого хода
game_window._hint_tutorial_time_delay = 0

-- время которое прошло с момоента прошлого сбора камня
game_window._drop_tutorial_time_delay = 0

-- задержка перед началом эффекта на поле
game_window._field_effect_delay = 500
-- id клипа в начале урвоня
game_window._start_level_clip = "level_begin03"
-- id виджетов, которые появляются моментально после проигрывания клипа
game_window._momental_widgets = {

	game_field_image = true,
	gem_bar_image = true,
	gui_1 = true,
	gui_2 = true,
	gui_3 = true,
	gui_4 = true,
	gui_5 = true,
	gui_6 = true
}

-- инициация переигрывания уровня
function game_window.Replay()
	-- восстаналиваем данные профайла на начало уровня
	game_window.profile_data.ReturnToSnapshot()
	-- перезапускаем урвоень
	game_window.Show(game_window.current_game_dif_level,game_window.current_game_level_index, nil, true)
end

game_window._totems_cheat_table = {
	[71] = s11.CFieldCap.CapTypeGreen,
	[89] = s11.CFieldCap.CapTypeYellow, 
	[82] = s11.CFieldCap.CapTypeRed, 
	[66] = s11.CFieldCap.CapTypeBlue,
	[79] = s11.CFieldCap.CapTypeOrange,
	[87] = s11.CFieldCap.CapTypeWhite, 
	[86] = s11.CFieldCap.CapTypeViolet
}

--[[***************  ПЕРЕГРУЗКА СОБЫТИЙ  ***************]]

function game_window.StartBenchmark(_game_field)
	if not game_window._bench_mark then
	
		for _, totem_name in pairs(totems_widget._totems_map) do
			game_window.gameplay_settings.SetItemLevel(totem_name, 4)
		end
		totems_widget.Init(game_window.game_field)
		local droped = s11.EnableFPSCounter(true)
		if not droped then
			s11.DropFPSCounter()
		end
		game_window._bench_mark = true
		math.randomseed (42)
		
		game_window._gem_tutorial = nil
		game_window._hint_tutorial = nil
		game_window._drop_tutorial = nil
		game_window._level_tutorial = nil
		game_window._hard_tutorial = nil
		game_window._expert_tutorial = nil
		game_window._red_totem_tutorial = nil
		
		_game_field.ClearAllAchievements()
		for i = 1, s11.bonus.BonusTypesCount-1 do
			game_window.gameplay_settings.SetBonusForce(i, 4)
		end
		
		local startegy = s11.CreateCBenchmarkStrategy(_game_field)
		
		local benchmark_info = g_App.GetSettings().GetChild("Constants", false).GetChildRef("benchmark_options", false)
		if benchmark_info then
			startegy.Load(benchmark_info)
		end
		game_window._bench_mark_id = startegy.GetId().c_str()
		_game_field.SetStrategy(startegy)
	end

end

function game_window.EndBenchmark()
	if game_window._bench_mark then
		math.randomseed (os.clock ())
		totems_widget.DropColors()
		game_window.game_field.DropStrategy()
		local fps_counter = s11.GetFPSCounter()
		
		s11.EnableFPSCounter(false)
		game_window._bench_mark = false
		local avr_fps = string.format("%3.2f\n\n", fps_counter.GetAvrFPS())
		local min_fps = string.format("%3.2f\n", fps_counter.GetMinFPS())
		local max_fps = string.format("%3.2f\n", fps_counter.GetMaxFPS())
		__message(game_window._bench_mark_id.."\n".."AvrFPS = "..avr_fps.." MaxFPS = "..max_fps.." MinFPS = "..min_fps)
	end
end

game_window._overload_functions =
{
	
	OnBenchmarkUpdateGemBar = function ()
		gems_bar_widget.Init(game_window.game_field, game_window._self)
	end,

	-- на окончание бенчмарка
	OnFinishBenchmark = function ()
		game_window.EndBenchmark()
	end,

	IsLuaEffects = function ()
		return totems_widget.IsTotemEffects()
	end,

	OnAddScore = function()
		-- обновляем счет
		--game_window.score_label_widget.SetText(tostring(game_window.profile_data.GetScore()))
		game_window._scores_effect:SetTargetValue(game_window.profile_data.GetScore())
		--[[
		-- обновляем экспириенс
		
		local progress = game_window.profile_data.GetExpProgress()
		
		if progress < 0 then
			-- прогресс бар не активен
			--__message("disable")
			game_window.gray_progress.SetValue(math.abs(progress))
			__visible(game_window.gray_progress, true)
			__visible(game_window.green_shield, true)
		end
		
		if game_window._last_level == -1 and progress == 1 then
			-- уровень игрока максимлаьный, нужно соответсвующий эффект
			--__message("level_limit_on_level")
			__visible(game_window.blinking_progress, true)
			__visible(game_window.green_shield, true)
		end

		progress = math.abs(progress)
		
		game_window.progress_bar.SetValue(math.abs(progress))
		-- обновляем отображение уровня персонажа
		local player_level = game_window.profile_data.GetPlayerLevel()
		if game_window._last_level ~= -1 and game_window._last_level < player_level then
			-- инициация эффекта на достижения новгго уровня игрока
			--__message("level up")
			effects_widget.visual_effects:CreateInstantEffect(game_window._up_level_effect_id, game_window._up_level_effect_pos)
			if progress == 1 then
				-- уровень игрока максимлаьный, нужно соответсвующий эффект
				--__message("level_limit_on_level")
				__visible(game_window.blinking_progress, true)
				__visible(game_window.green_shield, true)
			end
		end
		
		game_window._last_level = player_level
		game_window.player_level_label.SetText(tostring(player_level))
		
		if game_window._level_tutorial and game_window._player_level_for_tutorial == player_level then
		
			game_window._level_tutorial = false
			--__message("Level tutorial")
			game_window._tutorial_flags.RaiseFlag(s11.CProfileDataClassic.TutorialFlagLevel)		
			tutorial_window.Show(game_window._self, "new_level_player")	
		end
		]]
	end,
	
	OnPlayerDestroyMatch = function(_color)
		-- добвляем цвет в очереди обработки тотемов
		totems_widget.AddColor(_color)
		game_window._hint_tutorial_time_delay = 0
	
	end,
	
	OnAllGemsCollected = function()
		__sound("level_end")
		game_window.game_field.FinishGame()
		game_window.game_field.StopGameTime()
        -- сообщение о завершении уровня
		game_window.game_field.PlayClipOnField("end_level")
		game_window.game_field.InitNoEffectsEvent()
	end,

	OnLoseGame = function ()
		-- показваем окно проигрыша уровня
		game_window.game_field.StopGameTime()
		game_window._hint_tutorial = false
		game_window._drop_tutorial = false
		time_widget.SetAllowTimeWarning(nil)		
		lose_level_window.Show(game_window._self)
	end,

	OnNoEffects = function ()
		game_window.WinGame()
	end,

	OnNoMoves = function ()
        -- сообщение что нет ходов
		__sound("no_moves_drop")
        game_window.game_field.PlayClipOnField("nomore_moves01");
		game_window.game_field.DropField()
		avatar_widget.ChangeMood("no_moves_classic")
	end,
	
	OnGemAdd = function ()
		game_window._drop_tutorial_time_delay = 0
	end,

}

-- настройки надписи "Нажмите любую клавишу...", которая появляется после закрытия окна статистики
game_window.press_any_key = {}
game_window.press_any_key.params = 
{
	-- текст или идентификатор текста
	text = "$282",
	-- идентификатор шрифта
	font = "mpc_semibold_30",
	-- позиция левого верхнего угла надписи
	pos = sf.misc.FloatVector(400,700),
	-- настройки анимации (мигания)
	anim = 
	{
		-- период мигания - время, за которое надпись переходит из начального состояния в конечное и возвращается обратно
		period = 3000,
		-- начальное значение цвета текста
		min_color = sf.graphics.Color(0,255,255,255),
		-- конечное значение цвета текста
		max_color = sf.graphics.Color(255,255,255,255)
	}
}

function game_window.press_any_key._CalcColor()
	
	local t = game_window.press_any_key.timer.Get().GetTime()
	local p = game_window.press_any_key.params.anim.period
	local k = (math.cos(2.0 * math.pi * ((t % p) / p)) + 1.0) / 2.0
	
	local min_color = game_window.press_any_key.params.anim.min_color
	local max_color = game_window.press_any_key.params.anim.max_color
	
	local color = sf.graphics.Color()
	color.Alpha = min_color.Alpha + k * (max_color.Alpha - min_color.Alpha)
	color.Red = min_color.Red + k * (max_color.Red - min_color.Red)
	color.Green = min_color.Green + k * (max_color.Green - min_color.Green)
	color.Blue = min_color.Blue + k * (max_color.Blue - min_color.Blue)
	color.Clamp()
	
	return color
end

function game_window.press_any_key.Init()
	if not game_window.press_any_key.timer then
		game_window.press_any_key.timer = __create_timer()
	end
	game_window.press_any_key.timer.Get().SetTime(0)
	if not game_window.press_any_key.font then
		game_window.press_any_key.font = g_App.GetResourceManager().GetFont(game_window.press_any_key.params.font)
	end
	if not game_window.press_any_key.text then
		game_window.press_any_key.text = sf.misc.g_StringTable.Instance().FormatByStringsID(game_window.press_any_key.params.text)
	end
end

function game_window.press_any_key.Draw(_renderer)
	-- надпись отрисовывается только после завершения уровня
	if game_window._end_level_effect == nil then return end
	if not game_window.press_any_key.font or not game_window.press_any_key.text then return end
	
	_renderer.RenderString(game_window.press_any_key.font, game_window.press_any_key.text, 
		game_window.press_any_key.params.pos.X, game_window.press_any_key.params.pos.Y, -1, -1, 1, 
			game_window.press_any_key._CalcColor(), sf.graphics.Color(0, 255, 255, 255))
end

function game_window.Show(_dif_level, _level_index, _load_level, _no_effect, _unload_resources)
	window = __ChangeWindowWithEffect(_no_effect, _unload_resources)
	if not window then
		return
	end
	
	game_time_counter.Init()
	
	game_window._last_level = -1
	game_window._start_effect = start_level_effect
	
	game_window._bench_mark = nil
	
	sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)
	game_window._hint_tutorial_time_delay = 0

	game_window._drop_tutorial_time_delay = 0

	game.GameEventsOverload(game_window._overload_functions)
    -- сбрасываем режим скринсейвера, который мог остаться с конца уровня
    game_window._end_level_effect = nil
	game_window._autosave_timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().GetTimer("game_timer").AttachTimer(""))
		
	game_window.current_game_dif_level = _dif_level
	game_window.current_game_level_index = _level_index
	
	game_window._self =  window

	window.Load(
		g_App.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "game_window", true), 
		g_App.GetSettings().GetChild("GUITemplates", false))
	window.SetSize(g_App.GetRenderer().GetWidth(), g_App.GetRenderer().GetHeight())
	window.UpdateLayout()
	
	game_window.current_profile = s11.g_ProfileManager.Instance().GetCurrentProfile()
	avatar_widget.InitAvatar(game_window.current_profile.IsFemale())
	game_window.profile_data = game_window.current_profile.GetClassicData()
	
	game_window._game_timer = sf.core.g_Application.GetTimeManager().GetTimer("game_timer")
	
	-- инициализация объекта для управлениея флагами отображэения туториала
	game_window._tutorial_flags = game_window.profile_data.GetTutorialFlags()
	-- туториал на первый камень
	game_window._gem_tutorial = not game_window._tutorial_flags.ReadFlag(s11.CProfileDataClassic.TutorialFlagGem)
	if game_window._gem_tutorial then
		game.OnGemAddToGemBar = function ()
			-- вызов туториала на первый собраный камень
			if game_window._gem_tutorial and game_window.game_field.HasStrategy() == false then
				tutorial_window.Show(game_window._self, "classic_first_gem")
				--__message("First gem tutorial")
				game_window._gem_tutorial = false
				game_window._tutorial_flags.RaiseFlag(s11.CProfileDataClassic.TutorialFlagGem)
			end
		end
	end
	-- туториал на кнопку хинт
	game_window._hint_tutorial = not game_window._tutorial_flags.ReadFlag(s11.CProfileDataClassic.TutorialFlagHint)
	-- туториал на кнопку сброс
	game_window._drop_tutorial = not game_window._tutorial_flags.ReadFlag(s11.CProfileDataClassic.TutorialFlagDrop)
	-- туториал на уровень
	game_window._level_tutorial = not game_window._tutorial_flags.ReadFlag(s11.CProfileDataClassic.TutorialFlagLevel)
	-- туториал на первый уровень режима Hard
	game_window._hard_tutorial = not game_window._tutorial_flags.ReadFlag(s11.CProfileDataClassic.TutorialFlagHardLevels)
	-- туториал на первый уровень режима Expert
	game_window._expert_tutorial = not game_window._tutorial_flags.ReadFlag(s11.CProfileDataClassic.TutorialFlagExpertLevels)
	-- туториал на красного тотема
	game_window._red_totem_tutorial = not game_window._tutorial_flags.ReadFlag(s11.CProfileDataClassic.TutorialFlagTotem)
	if _dif_level ~= 0 or _level_index ~= 2 then
		game_window._red_totem_tutorial = nil
	end
	-- туториал на красного тотема
	game_window._first_move_tutorial = not game_window._tutorial_flags.ReadFlag(s11.CProfileDataClassic.TutorialFlagFirstMove)
	
	if game_window._first_move_tutorial and (_level_index ~= 0 or _dif_level ~= 0) then
		game_window._tutorial_flags.RaiseFlag(s11.CProfileDataClassic.TutorialFlagFirstMove)
		game_window._first_move_tutorial = false
	end

	
	game_window.game_field_image_widget = get_child_widget(window, "game_field_image", sf.gui.CImageWidget, "ошибка" )
	
	game_window.game_widget = get_child_widget(window, "game_widget", s11.CGameFieldWidget, "ошибка" )
	
	game_window.score_label_widget = get_child_widget(window, "score_label", sf.gui.CLabelWidget, "ошибка" )
	
	--game_window.progress_bar = get_child_widget(window, "exp_progress", sf.gui.CProgressBarWidget, "ошибка" )
	--game_window.blinking_progress = get_child_widget(window, "blinking_progress", sf.gui.CLuaWidget, "ошибка" )
	--game_window.gray_progress = get_child_widget(window, "gray_progress", sf.gui.CProgressBarWidget, "ошибка" )
	--game_window.green_shield = get_child_widget(window, "green_shield", sf.gui.CImageWidget, "ошибка" )
	
	--__visible(game_window.blinking_progress, false)
	--__visible(game_window.gray_progress, false)
	--__visible(game_window.green_shield, false)
	
	--game_window.player_level_label = get_child_widget(window, "player_level_label", sf.gui.CLabelWidget, "ошибка" )
    
    offer_label = get_child_widget(game_window._self, "end_level_offer_label", sf.gui.CLabelWidget, "ошибка" )
    offer_label.AddFlags(offer_label.FlagHidden)
	
	
	game_window._player_name_label = get_child_widget(window, "player_name_label", sf.gui.CLabelWidget, "ошибка" )
	
	game_window._player_name_label.SetText(game_window.current_profile.GetName())
	
	game_window._scores_effect = CScoresEffect(game_window.score_label_widget)
	
	-- если кнопки для хинта нет, то ругаемся и выходим
	game_window._hint_button_widget = get_child_widget(window, "hint_button", sf.gui.CButtonWidget)
	if not game_window._hint_button_widget then
		__message("Button hint_button not found")
		return
	end
	
	game_window._drop_button_widget = get_child_widget(window, "drop_button", sf.gui.CButtonWidget)
	if not game_window._drop_button_widget then
		__message("Button drop_button not found")
		return
	end
	
	game_window._Init(_dif_level, _level_index, _load_level)
	
	drop_buttons.Init(window, game_window.game_info)	
	
	if game_window.game_field_image_widget then
		game_window.game_field.SetShakedWidget(game_window.game_field_image_widget)
	end
	
	game_helpers.SetFieldPos(game_window.game_widget.GetOffset())
	
	s11.g_TrackManager.Instance().UpdateCurrentTrack("gameplay", false)
	__sound("new_level")

	game_window._start_effect.InitStartEffect(window, 
	                                          game_window._start_level_clip, 
											  game_window.game_widget, 
											  game_window._momental_widgets, 
											  game_window.level_name or "", 
											  game_window._field_effect_delay,
											  game_window._OnFormLevel)
	game_window._start_effect.HideWidgets()

	
	game_window.OnShowWindow = function ()
		
		if game_window._start_effect then
			game_window._start_effect.StartBeginLevelEffect()
		end
	end
	
	if _no_effect then
		g_App.SetMainWindow(window)
	end
	
	window = 0
	collectgarbage()
end

function game_window._OnFormLevel()
	if game_window._hard_tutorial and game_window.current_game_dif_level == 1 then
		game_window._hard_tutorial = false
		--инициация туториала а режим игры Hard
		game_window._tutorial_flags.RaiseFlag(s11.CProfileDataClassic.TutorialFlagHardLevels)
		sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(0)
		dialog_do_modal("hard_enable_dialog", game_window._self)
		sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)
	end

	if game_window._expert_tutorial and game_window.current_game_dif_level == 2 then
		game_window._expert_tutorial = false
		--инициация туториала а режим игры Expert
		game_window._tutorial_flags.RaiseFlag(s11.CProfileDataClassic.TutorialFlagExpertLevels)
		sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(0)
		dialog_do_modal("expert_enable_dialog", game_window._self)
		sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)
	end
	local red_totem_level = game_window.gameplay_settings.GetItemLevel("red_totem")
	if red_totem_level > 0 and game_window._red_totem_tutorial then
		totem_tutorial.Init(game_window.game_field, game_window._tutorial_flags)
	end
	if game_window._first_move_tutorial then
		game_window.game_field.SetStrategy(s11.strategy.CreateFirstMoveTutorial(game_window.game_field, game_window._first_move_tutorial_cap_type, game_window._first_move_tutorial_delay))	
	end
	

end

function game_window._Init(_dif_level, _level_index, _load_level)
	local level = s11.g_GameStruct.Instance().GetLevelsSystem(s11.CGameStruct.GameTypeClassic).GetLevel(_dif_level, _level_index)
	if level then
		local chapter_index = level.GetChapterIndex()
		local level_index_in_chapter = level.GetLevelIndexInChapter()

		-- инициализируем фон
		game_window._chapter_index = chapter_index
		game_window._level_index_in_chapter = level_index_in_chapter

		game_window.OnStartShowWindow = function ()
			s11.g_GameBackground.Instance().Init(game_window._chapter_index, game_window._level_index_in_chapter)
			s11.g_GameBackground.Instance().SetUseClip(false)
		end
		
		-- инициализируем номер уровня
		
		local level_label = get_child_widget(game_window._self, "level_label", sf.gui.CLabelWidget, "ошибка" )
		if level_label then
			game_window.level_name = s11.StringFormat(level_label.GetText(), chapter_index + 1, level_index_in_chapter + 1)
			level_label.SetText(game_window.level_name)
		end
	
		local match_level = __cast(level, s11.CMatchLevelInfo)
		if not match_level then
			__message("Wrong level type")
			return
		end
		local profile_data =  game_window.profile_data
		if not _load_level then
			profile_data.CreateSnapshot()
		
			profile_data.SetSavedLevelDifficulty(_dif_level)
			profile_data.SetSavedLevelIndex(_level_index)
			game_window.SaveGame()
		end
		
		--profile_data.SetMaxExpLevel(match_level.GetCharacterLevelLimit())
		-- формируем игровые настройки
		game_window.gameplay_settings = s11.GameplaySettings(match_level)
		game_window.gameplay_settings.GetInfoFromProfile(profile_data)
		--game_window.gameplay_settings.SetItemLevel("dynamite_bonus", 2)
		game_window.gameplay_settings.FormSettingsInfo(match_level)
		
		game_window.game_widget.InitGameField(match_level, profile_data, game_window.gameplay_settings, _load_level or false)

		game_window.game_field = game_window.game_widget.GetGameField()
		
		
		
		-- устанаваливаем условие завершения урвоня
		if _dif_level == 1 then
			game_window.game_field.SetLoseTime(s11.CMatchLevelInfo.PrizeTimeDef)
		elseif _dif_level == 2 then
			game_window.game_field.SetLoseTime(s11.CMatchLevelInfo.PrizeTimeSilver)
		end
		
		
		-- нужно ли загрузить уровень 
		if not _load_level then
			--game_window.game_field.Save()
			game_window.SaveGame()
		end
		
		game_window.game_info = game_window.game_field.GetGameInfo()
		
		-- формируем кнопку hint на основании виджета кнопки
		hint_button.FormHintButton(game_window._hint_button_widget)
		-- иницируем кнопку hint в зависимости от игровой информации
		game_window.InitHintButton()
		
		-- иницируем прогрессбар с камнями
		gems_bar_widget.Init(game_window.game_field, game_window._self)
		
		-- инициируем часы
		time_widget.Init(match_level)
		-- часы будут менять аватар на грустный если время заканчивается совсем
		if _dif_level == 1 then
			time_widget.InitAvatartWarningIndex(1)
		elseif _dif_level == 2 then
			time_widget.InitAvatartWarningIndex(0)
		end
		
		-- инициируем отображение тотемов
		totems_widget.Init(game_window.game_field)
	end
end

function game_window.DoDraw(_this, _renderer)
    s11.effects.StartShaderSurface(_renderer)

	s11.g_GameBackground.Instance().Draw(_renderer)
	if game_window._start_effect then
		game_window._start_effect.Draw(_renderer)
	end
	
	game_window.press_any_key.Draw(_renderer)
	
end

function game_window.DoUpdate(_this)

	if game_window._start_effect then
		game_window._start_effect.Update()
		if game_window._start_effect and game_window._start_effect.IsDead() then
			game_window._start_effect = nil
		end
	end

	if game_window.OnStartShowWindow then
		game_window.OnStartShowWindow()
		game_window.OnStartShowWindow = nil
	end

	if game_window.OnShowWindow then
		if not s11.WindowHasEffects(game_window._self) then
			local show_func = game_window.OnShowWindow
			game_window.OnShowWindow = nil
			show_func()
		end
	end
    
	-- обновляем фон
    s11.g_GameBackground.Instance().Update()
    
    -- обновляем эффект конца уровня (обновляется только если он включен)
    game_window._UpdateEndLevelEffect()

	game_window._scores_effect:Update()
	
	-- обновление кнопки хинт
	game_window.UpdateHintButton()
	
	if game_window._autosave_timer.Get().GetTime() > game_window._auto_save_time then
		game_window.SaveGame()
		game_window._autosave_timer.Get().SetTime(0)
	end	
	local frame_delta = game_window._game_timer.GetFrameDelta()
	
	game_time_counter.AddGameTime(frame_delta)
	
	-- туториал на кнопку хинт
	if game_window._hint_tutorial then
		game_window._hint_tutorial_time_delay = game_window._hint_tutorial_time_delay + frame_delta
		if game_window._hint_tutorial_time_delay > game_window._hint_tutorial_pre_delay then
			game_window._hint_tutorial = false
			tutorial_window.Show(game_window._self, "hint_button", 
				{widget=game_window._hint_button_widget, flags={update=true,on_mouse_move=true,on_mouse_down=true,on_mouse_up=true}})
			game_window._tutorial_flags.RaiseFlag(s11.CProfileDataClassic.TutorialFlagHint)
		end
	end
	-- туториал на кнопку сброс
	if game_window._drop_tutorial then
		game_window._drop_tutorial_time_delay = game_window._drop_tutorial_time_delay + frame_delta
		local gems_to_win = game_window.game_field.GetGemsCountToWin()
		if game_window._drop_tutorial_time_delay > game_window._drop_tutorial_pre_delay and gems_to_win <= game_window._drop_gems_max_to_win then
			game_window._drop_tutorial = false
			if drop_buttons.GetDropsCount() > 0 then
				tutorial_window.Show(game_window._self, "mix_button", 
					{widget=game_window._drop_button_widget, flags={update=true,on_mouse_move=true,on_mouse_down=true,on_mouse_up=true}})
				game_window._tutorial_flags.RaiseFlag(s11.CProfileDataClassic.TutorialFlagDrop)
			end
		end
	end
	
end

--[[***************  ЭФФЕКТ ЗАВЕРШЕНИЯ УРОВНЯ  ***************]]
-- запускает отображение эффектов завершения уровня
-- вводит game_window  в режим скринсейвера
-- если нажали клавишу или кликнули мышкой происходит переход на карту
function game_window.ShowEndLevelEffects()
	s11.g_GameBackground.Instance().SetUseClip(true)
    -- инициализируем эффект конца уровня
	game_window._end_level_effect = 
    {
        offer_label = get_child_widget(game_window._self, "end_level_offer_label", sf.gui.CLabelWidget, "ошибка" ),
        timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().AttachTimer("", nil)),
        gui_hidden = false
    }
    local widget = game_window._self.GetWidgets()
    while not widget.IsEnd() do
		set_widget_flag_value(widget.Get(), sf.gui.CBaseWidget.FlagDisabled, true)
        widget.Next()
    end
	
	game_window.press_any_key.Init()
	s11.g_GameBackground.Instance().DisableSounds(false)
	blinking_progress_widget.Stop()
end

-- обновляет эффект конца уровня
-- плавно прячет всю гую
-- потом переводит фон на следующий уровень
function game_window._UpdateEndLevelEffect()
    if not game_window._end_level_effect 
        or game_window._end_level_effect.gui_hidden 
    then 
        return 
    end
    
    local effect = game_window._end_level_effect
    
    local alpha = 255
    
    local time = effect.timer.Get().GetTime()
    if time >= 2000 then
        alpha = 0
        effect.gui_hidden = true
        effect.offer_label.RemFlags(offer_label.FlagHidden)
        s11.g_GameBackground.Instance().AdvanceLevel()
    else
        alpha = 255 * (1 - time / 2000)
    end
    
    local widget = game_window._self.GetWidgets()
    while not widget.IsEnd() do
        widget.Get().SetColor(sf.graphics.Color(alpha, 255, 255, 255))
        widget.Next()
    end
end

-- завершает отображение эффекта завершения уровня, если он отображается в данный момент, и переходит на карту
-- вызывается при клике мышкой и при нажатии клавишы
function game_window._FinishEndLevelEffect()
	-- если не находимся в состоянии отображения эффекта конца уровня
    if game_window._end_level_effect == nil then return end
	sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)
    s11.g_GameBackground.Instance().DisableSounds(true)
    
    game_window._end_level_effect = nil
    map_window.Show()
end

--[[***************  КНОПКА ХИНТА  ***************]]
-- первоначальная инициализация кнопки
-- в зависимости от загруженого времени меняем тип кнопки
function game_window.InitHintButton()
	local progress_time = game_window.game_field.GetHintBonusTime()
	if progress_time > 0.01 then
		hint_button.StartBonusHintTimer()
	else
		progress_time = 1 - game_window.game_field.GetHintResumeTime()/game_window._hint_resume_time
		hint_button.StartHintButtonResume()
		hint_button.SetHintButtonDisabled(progress_time > 0.01)
	end
	hint_button.UpdateHintButton(progress_time)
end

-- обновление кнопки ихнта
function game_window.UpdateHintButton()
	-- если кнопка активна, то ничего не делаем
	if hint_button.IsHintButtonDisabled() then
		-- если кнопка деактивирована, то узнаем время хинта или подсказчика 
		local progress_time = game_window.game_field.GetHintBonusTime()
		if progress_time <= 0.01 then
			progress_time = 1 - game_window.game_field.GetHintResumeTime()/game_window._hint_resume_time
		end
		--- и апдейтим ее содержимое
		hint_button.UpdateHintButton(progress_time)
	end
end

-- возврат позиции, в которую летит бонус-подсказчик перед применением(кнопка Hint)
function game_window.GetHintFlyTarget()
	local widget = game_window._hint_button_widget
	if not widget then return sf.misc.FloatVector(0, 0) end
	
	return widget.GetOffset() + widget.GetSize()/2
end


--[[***************  ОБРАБОТКА СОБЫТИЙ  ***************]]
function game_window.OnChar(_this, _char, _keyboard_state, _state, _broadcast)
    return _this.SuperOnChar(_char, _keyboard_state, _state, _broadcast) 
end

-- пройти уровень читерский метод
function game_window.WinGame()
	drop_buttons.DropToolTips()
	game_window._self.HideToolTip()

	avatar_widget.ChangeMood("finish_level")
	-- останаваливаем игру
	game_window.game_field.StopGameTime()
	game_window._hint_tutorial = false
	game_window._drop_tutorial = false
	time_widget.SetAllowTimeWarning(nil)

	game_stat_window.Show(game_window._self)
end

function game_window.OnKeyDown(_this, _key, _keyboard_state, _state, _broadcast)
	if sf.core.g_Application.GetDebugLevel() >= sf.core.g_Application.DebugCheats then
		if _key == 83 then
			game_window.StartBenchmark(game_window.game_field)
		end
		if _key == 49 then
			avatar_widget.ChangeSate("sad")
		end
		if _key == 50 then
			avatar_widget.ChangeSate("neutral")
		end
		if _key == 51 then
			avatar_widget.ChangeSate("happy")
		end
		if _key == 52 then
			avatar_widget.ChangeMood("test_down")
		end
		if _key == 53 then
			avatar_widget.ChangeMood("test_up")
		end
		
		
		if _key == 112 then
			totems_widget.DemonstrateTotem(s11.CFieldCap.CapTypeYellow)
		end
		
		if _key == 113 then
			totems_widget.DemonstrateTotem(s11.CFieldCap.CapTypeGreen)
		end
		
		if _key == 114 then
			totems_widget.DemonstrateTotem(s11.CFieldCap.CapTypeOrange)
		end
		
		if _key == 115 then
			totems_widget.DemonstrateTotem(s11.CFieldCap.CapTypeRed)
		end
		
		if _key == 116 then
			game_window.WinGame()
		end
		-- чит для получения ачивмента
		if _key == 117 then
			achievements.GetAchievement("complete_minigame")
		end
		if _key == 118 then
			game.OnNoMoves()
		end
		
		if _key == 122 then
			s11.CahngeTestCapsCahngeDraw()
		end
		
		local totem_color = game_window._totems_cheat_table[_key]
		if totem_color then
			totems_widget.AddColor(totem_color)
		end
	end
    
    game_window._FinishEndLevelEffect()
    
	if _this.SuperOnKeyDown( _key, _keyboard_state, _state, _broadcast) then
		return true
	end
	
	if _key == 27 then
		if game_window._bench_mark then
			game_window.EndBenchmark()		
		else
			game_window.ShowMenu()		
		end
	
		return true
	end
	
	return false
end

function game_window.OnKeyUp(_this, _key, _keyboard_state, _state, _broadcast)
	return _this.SuperOnKeyUp( _key, _keyboard_state, _state, _broadcast)
end

function game_window.OnMouseMove(_this, _pos, _state, _broadcast)
	return _this.SuperOnMouseMove( _pos, _state, _broadcast) 
end

function game_window.OnMouseDown(_this, _pos, _button, _state, _broadcast)
    if game_window._start_effect then
		game_window._start_effect.InstantApply()
	end
	game_window._FinishEndLevelEffect()
	return _this.SuperOnMouseDown( _pos, _button, _state, _broadcast) 
end

function game_window.OnMouseUp(_this, _pos, _button, _state, _broadcast)
	return _this.SuperOnMouseUp( _pos, _button, _state, _broadcast) 
end

function game_window.OnDoubleClick(_this, _pos, _state, _broadcast)
	return _this.SuperOnDoubleClick( _pos, _state, _broadcast) 
end

function game_window.OnMouseWheel(_this, _pos, _delta, _state, _broadcast)
	return _this.SuperOnMouseWheel( _pos, _delta, _state, _broadcast)
end

function game_window.OnChildAction(_this, _action, _child)
	if not _child then return end
	local handler = game_window.actions[_child.GetId().c_str()]
	if handler then handler = handler[_action.c_str()] end
	if handler then handler(_this, _child) end
end

function game_window.ShowMenu()
	if not game_window._bench_mark then
		if game_window._start_effect then
			game_window._start_effect.InstantApply()
		end
		time_widget.SetAllowTimeWarning(false)
		game_menu_window.Show(game_window._self)
	end
end

function game_window.SaveGame()
	game_window.current_profile.SaveGameType(s11.CGameStruct.GameTypeClassic)
	-- инициацию сохранения для текущеей игры
	s11.g_Achievements.Instance().SaveProfilesAchievements()
end

function game_window.Drop()
	if not game_window.game_field.IsEffectsOnField() then
		__sound("shuffle_use")
		effects_widget.AddCapsMix()
		return true
	end
	return false
end

--[[***************  ACTIONS ***************]]
game_window.actions.drop_button = 
{
	pressed = function(_window) 
		if game_window.Drop() then
			drop_buttons.SetDropButtonsCount(1)
			drop_buttons.DropToolTips()
			_window.HideToolTip()
		end
	end
}

game_window.actions.drop_button02 = 
{
	pressed = function(_window) 
		if game_window.Drop() then
			drop_buttons.SetDropButtonsCount(0)
			drop_buttons.DropToolTips()
			_window.HideToolTip()
		end
	end
}

game_window.actions.hint_button = 
{
	pressed = function(_window)
		-- пытаемся доавбить хинт на поле
		local res = game_window.game_field.ShowHintForMove(game_window._hint_show_time)
		if res then
			-- если удалось
			-- проигрываем звук использования подсказки
			__sound("hint_apply")
			-- активируем восстанвоение хинта
			hint_button.StartHintButtonResume()
			-- инициализируем это время в игре, для его обновления и сохранения/загрузки
			game_window.game_field.SetHintResumeTime(game_window._hint_resume_time)
		end
	end
}

game_window.actions.menu_button = 
{
	pressed = function(_window) 
		if game_window._bench_mark then
			game_window.EndBenchmark()		
		else
			game_menu_window.Show(game_window._self)
		end
	end
}