puzzle_window = {}
puzzle_window.actions = {}

puzzle_window._hint_show_time = 5000   -- время отображения хинта(возможно потом будет перенесено)

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

-- задержка перед началом эффекта на поле
puzzle_window._field_effect_delay = 500
-- id клипа в начале урвоня
puzzle_window._start_level_clip = "level_begin_puzzle"
-- id виджетов, которые появляются моментально после проигрывания клипа
puzzle_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
}


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

puzzle_window._overload_functions =
{
	IsLuaEffects = function ()
		return false
	end,

	OnAddScore = function()
		puzzle_window._scores_effect:SetTargetValue(puzzle_window.profile_data.GetScore())
	end,
	
	OnPlayerDestroyMatch = function(_color)
	end,
	
	OnAllGemsCollected = function()
	end,

	OnLoseGame = function ()
		__message("lose is no posible")
	end,
	
	OnLastGemAdd = function ()
		__sound("level_end")
		puzzle_window.game_field.FinishGame()
		puzzle_window.game_field.StopGameTime()
		puzzle_window.game_field.InitNoEffectsEvent()
        -- поздравление с выигрешом
		puzzle_window.game_field.PlayClipOnField("end_level")
	end,
	
	OnNoEffects = function ()
		puzzle_window.WinGame()
	end,

	OnCreateSnapshot = function ()
		effects_widget.visual_effects:CreateInstantEffect("NewUNDOEffect", puzzle_window._undo_pos)
		local null_cell = s11.game_helpers.GetRandomNullCell(puzzle_window.game_field)
		if null_cell and puzzle_window._on_first_start then
			puzzle_window._on_first_start = false
			local pos = null_cell.GetCellPos()
			--__message(tostring(pos.X) .."/".. tostring(pos.Y))
			puzzle_window._tutorial_flags.RaiseFlag(s11.CProfileDataPuzzle.TutorialFlagEmptyCell)
						
			local field_size = puzzle_window.game_field.GetFieldSize()
			local field_pos_x = game_window._game_field_center[1] - field_size.X / 2
			local field_pos_y = game_window._game_field_center[2] - field_size.Y / 2
			local cell_center = sf.misc.FloatVector(
				field_pos_x + (pos.X + 0.5) * field_size.X / s11.ConstsFieldSizeX,
				field_pos_y + (pos.Y + 0.5) * field_size.Y / s11.ConstsFieldSizeY )
			tutorial_window.Show(puzzle_window._self, "puzzle_first_match", nil, cell_center)
		end
		
		
	end,

	OnNoMoves = function ()
		avatar_widget.ChangeMood("no_moves_puzzle")
		puzzle_lose_window.Show(puzzle_window._self)
	end
}

puzzle_window._hint_map = nil

function puzzle_window.LoadLevelhints(_dif_level, _level_index)
	local level_info = s11.g_GameStruct.Instance().GetLevelsSystem(s11.CGameStruct.GameTypePuzzle).GetLevel(_dif_level, _level_index)
	local match_level = __cast(level_info, s11.CMatchLevelInfo)
	if not match_level then
		puzzle_window._hint_map = nil
		return
	end
	
	local hint_file_name = match_level.GetHintFileName()
	if hint_file_name ~= "" then
		puzzle_window._hint_map = s11.puzzle.CHintLoader()
		local load_res = puzzle_window._hint_map.Load(hint_file_name)
		if not load_res then
			puzzle_window._hint_map = nil
			--__message("bad_file")
		end
	else
		puzzle_window._hint_map = nil
	end
end

function puzzle_window.Replay()
	puzzle_window.profile_data.DropSavedLevelInfo()
	puzzle_window.profile_data.ReturnToSnapshot()
	puzzle_window.Show(puzzle_window.current_game_dif_level, puzzle_window.current_game_level_index, true, nil, true)
end

function puzzle_window.UnDo()
	if puzzle_window.profile_data.StepBack() then
		-- перезапускаем урвоень
		puzzle_window.Show(puzzle_window.current_game_dif_level, puzzle_window.current_game_level_index, true, true, true, true)
	end
end

function puzzle_window.Show(_dif_level, _level_index, _load_level, _do_not_drop_mood, _no_effect, _no_start_effect)

	local window = __ChangeWindowWithEffect(_no_effect)
	if not window then
		return
	end
	game_time_counter.Init()
	
	sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)

	puzzle_window.current_game_dif_level = _dif_level
	puzzle_window.current_game_level_index = _level_index
	game.GameEventsOverload(puzzle_window._overload_functions)

    -- сбрасываем режим скринсейвера, который мог остаться с конца уровня

	puzzle_window._autosave_timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().GetTimer("game_timer").AttachTimer(""))
		
	puzzle_window._game_timer = sf.core.g_Application.GetTimeManager().GetTimer("game_timer")
	
	puzzle_window._self =  window

	window.Load(
		g_App.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "puzzle_window", true), 
		g_App.GetSettings().GetChild("GUITemplates", false))
	window.SetSize(g_App.GetRenderer().GetWidth(), g_App.GetRenderer().GetHeight())
	window.UpdateLayout()
	
	puzzle_window.current_profile = s11.g_ProfileManager.Instance().GetCurrentProfile()

	avatar_widget.InitAvatar(puzzle_window.current_profile.IsFemale(), _do_not_drop_mood)

	puzzle_window.profile_data = puzzle_window.current_profile.GetPuzzleData()
	
	
	-- инициализация объекта для управлениея флагами отображэения туториала
	puzzle_window._tutorial_flags = puzzle_window.profile_data.GetTutorialFlags()
	-- туториал на первый запуск
	puzzle_window._on_first_start = not puzzle_window._tutorial_flags.ReadFlag(s11.CProfileDataPuzzle.TutorialFlagEmptyCell)
	-- туториал на первый уровень без хинтов
	puzzle_window._on_no_hints = not puzzle_window._tutorial_flags.ReadFlag(s11.CProfileDataPuzzle.TutorialFlagNoHints)
	
	puzzle_window._undo_button_widget = get_child_widget(window, "undo_button", sf.gui.CButtonWidget)
	puzzle_window._undo_pos = puzzle_window._undo_button_widget.GetOffset() + puzzle_window._undo_button_widget.GetSize()/2
	
	puzzle_window.game_field_image_widget = get_child_widget(window, "game_field_image", sf.gui.CImageWidget, "ошибка" )
	
	puzzle_window._drop_button = get_child_widget(window, "drop_button", sf.gui.CButtonWidget, "ошибка" )
	
	puzzle_window.game_widget = get_child_widget(window, "game_widget", s11.CGameFieldWidget, "ошибка" )
	
	puzzle_window.score_label_widget = get_child_widget(window, "score_label", sf.gui.CLabelWidget, "ошибка" )
	
    offer_label = get_child_widget(puzzle_window._self, "end_level_offer_label", sf.gui.CLabelWidget, "ошибка" )

    offer_label.AddFlags(offer_label.FlagHidden)
	
	
	puzzle_window._player_name_label = get_child_widget(window, "player_name_label", sf.gui.CLabelWidget, "ошибка" )
	
	puzzle_window._player_name_label.SetText(puzzle_window.current_profile.GetName())
	
	puzzle_window._scores_effect = CScoresEffect(puzzle_window.score_label_widget)
	
	-- если кнопки для хинта нет, то ругаемся и выходим
	puzzle_window._hint_button_widget = get_child_widget(window, "hint_button", sf.gui.CButtonWidget)
	if not puzzle_window._hint_button_widget then
		__message("Button hint_button not found")
		return
	end
	
	puzzle_window._Init(_dif_level, _level_index, _load_level)
	
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagSuperCombo)
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagFastDestroy)
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagSuperModePerLevel)
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagSevenCaps)
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagSuperModeTotal)
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagGemsInCombo)
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagCapsInCombo)
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagBonusesInCombo)
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagChainInCombo)
	puzzle_window.game_field.ClearAchFlag(s11.CGameField.AchievementFlagFastGemsCollect)
    
	if puzzle_window.game_field_image_widget then
		puzzle_window.game_field.SetShakedWidget(puzzle_window.game_field_image_widget)
	end
	
	game_helpers.SetFieldPos(puzzle_window.game_widget.GetOffset())
	
	s11.g_TrackManager.Instance().UpdateCurrentTrack("gameplay", false)
	
	
	if not _no_start_effect then
		puzzle_window._start_effect = start_level_effect
		
		puzzle_window._start_effect.InitStartEffect(window, 
												  puzzle_window._start_level_clip, 
												  puzzle_window.game_widget, 
												  puzzle_window._momental_widgets, 
												  puzzle_window.level_name or "", 
												  puzzle_window._field_effect_delay,
												  puzzle_window._OnFormLevel)
		puzzle_window._start_effect.HideWidgets()
	else
		puzzle_window._start_effect = nil
	end
	
	puzzle_window.OnShowWindow = function ()
		
		if puzzle_window._start_effect then
			puzzle_window._start_effect.StartBeginLevelEffect()
		end
	end
	
	if _no_effect then
		g_App.SetMainWindow(window)
	end
	
	window = 0
	collectgarbage()
end

function endless_window._OnFormLevel()
	if puzzle_window._on_no_hints and puzzle_window._hint_map == nil then
		puzzle_window._on_no_hints = false
		--__message("No hint - normal fo some level")
		puzzle_window._tutorial_flags.RaiseFlag(s11.CProfileDataPuzzle.TutorialFlagNoHints)
		sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(0)
		dialog_do_modal("hints_disable_dialog", puzzle_window._self)
		sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)
	end
end

function puzzle_window._Init(_dif_level, _level_index, _load_level)
	local level = s11.g_GameStruct.Instance().GetLevelsSystem(s11.CGameStruct.GameTypePuzzle).GetLevel(_dif_level, _level_index)
	if level then
		local mach_level = __cast(level, s11.CMatchLevelInfo)
		puzzle_window._min_moves_for_win = mach_level.GetMinMovesForWin()
		
		local chapter_index = level.GetChapterIndex()
		local level_index_in_chapter = level.GetLevelIndexInChapter()

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

		puzzle_window.OnStartShowWindow = function ()
			s11.g_GameBackground.Instance().Init(puzzle_window._chapter_index, puzzle_window._level_index_in_chapter)
			s11.g_GameBackground.Instance().SetUseClip(false)
		end
		
		-- инициализируем фон
		s11.g_GameBackground.Instance().Init(chapter_index, level_index_in_chapter)
		s11.g_GameBackground.Instance().SetUseClip(false)

		-- инициализируем номер уровня
		local level_label = get_child_widget(puzzle_window._self, "level_label", sf.gui.CLabelWidget, "ошибка" )
		if level_label then
			puzzle_window.level_name = s11.StringFormat(level_label.GetText(), chapter_index + 1, level_index_in_chapter + 1)
			level_label.SetText(puzzle_window.level_name)
		end
	
		local match_level = __cast(level, s11.CMatchLevelInfo)
		if not match_level then
			__message("Wrong level type")
			return
		end
		puzzle_window._caps_on_start_level = match_level.GetCupsOnStartLevel() or 1
		local profile_data =  puzzle_window.profile_data
		if not _load_level then
			profile_data.CreateSnapshot()
		
			profile_data.SetSavedLevelDifficulty(_dif_level)
			profile_data.SetSavedLevelIndex(_level_index)
			puzzle_window.SaveGame()
		end

		-- формируем игровые настройки
		
		puzzle_window.gameplay_settings = s11.GameplaySettings(match_level)
		puzzle_window.gameplay_settings.FormSettingsInfo(match_level)
		puzzle_window.gameplay_settings.SetGemTarget(match_level.GetGemsOnStartLevel())
		
		puzzle_window.game_widget.InitGameField(match_level, puzzle_window.profile_data, puzzle_window.gameplay_settings, _load_level or false)

		puzzle_window.game_field = puzzle_window.game_widget.GetGameField()
		puzzle_window.game_field.ShouldDropNewCaps(false)
		puzzle_window.game_field.SetShowComboText(false)
		
		game_window.game_field = puzzle_window.game_field
		

		puzzle_window.game_info = puzzle_window.game_field.GetGameInfo()

		-- формируем кнопку hint на основании виджета кнопки
		hint_button.FormHintButton(puzzle_window._hint_button_widget)
		
		-- иницируем прогрессбар с камнями
		gems_bar_widget.Init(puzzle_window.game_field, puzzle_window._self)
	end
end

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

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

function puzzle_window.DoUpdate(_this)
	if puzzle_window._start_effect then
		puzzle_window._start_effect.Update()
		if puzzle_window._start_effect and puzzle_window._start_effect.IsDead() then
			puzzle_window._start_effect = nil
		end
	end
	
	if puzzle_window.OnStartShowWindow then
		puzzle_window.OnStartShowWindow()
		puzzle_window.OnStartShowWindow = nil
	end
	
	if puzzle_window.OnShowWindow then
		if not s11.WindowHasEffects(puzzle_window._self) then
			local show_func = puzzle_window.OnShowWindow
			puzzle_window.OnShowWindow = nil
			show_func()
		end
	end

	-- обновляем фон
    s11.g_GameBackground.Instance().Update()

	-- обновление кнопки хинт
	--puzzle_window.UpdateHintButton()
	
	puzzle_window._scores_effect:Update()
	
	
	local frame_delta = puzzle_window._game_timer.GetFrameDelta()
	
	game_time_counter.AddGameTime(frame_delta)
	
	if puzzle_window._autosave_timer.Get().GetTime() > puzzle_window._auto_save_time then
		puzzle_window.SaveGame()
		puzzle_window._autosave_timer.Get().SetTime(0)
	end	
end

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

-- пройти уровень
function puzzle_window.WinGame()
	avatar_widget.ChangeMood("finish_level")
	puzzle_window.DropToolTips()
	-- останаваливаем игру
	puzzle_window.game_field.StopGameTime()
	-- показываем окно игровой статистики
	puzzle_stat_window.Show(puzzle_window._self)
end

function puzzle_window.OnKeyDown(_this, _key, _keyboard_state, _state, _broadcast)
	if sf.core.g_Application.GetDebugLevel() >= sf.core.g_Application.DebugCheats then
		if _key == 116 then
			puzzle_window.WinGame()
		end
		if _key == 118 then
			game.OnNoMoves()
		end
		if _key == 122 then
			s11.CahngeTestCapsCahngeDraw()
		end
	end
    
	if _this.SuperOnKeyDown( _key, _keyboard_state, _state, _broadcast) then
		return true
	end
	
	if _key == 27 then
		puzzle_window.ShowMenu()
		return true
	end
	
	return false
end

function puzzle_window.ShowMenu()
	puzzle_menu_window.Show(puzzle_window._self)
	if puzzle_window._start_effect then
		puzzle_window._start_effect.InstantApply()
	end
end

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

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

function puzzle_window.OnMouseDown(_this, _pos, _button, _state, _broadcast)
    if puzzle_window._start_effect then
		puzzle_window._start_effect.InstantApply()
	end

	return _this.SuperOnMouseDown( _pos, _button, _state, _broadcast) 
end

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

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

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

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

function puzzle_window.SaveGame()
	puzzle_window.current_profile.SaveGameType(s11.CGameStruct.GameTypePuzzle)
	s11.g_Achievements.Instance().SaveProfilesAchievements()
end

--[[***************  ACTIONS ***************]]

puzzle_window.actions.hint_button = 
{
	pressed = function(_window) 
	
		if puzzle_window._hint_map then
			local _dst = sf.misc.IntVector(0,0);
			local _src = sf.misc.IntVector(0,0);
			
			local hash = puzzle_window.game_field.GetHash().c_str();
			if puzzle_window._hint_map.GetHintByHash(hash, _src, _dst) then
				puzzle_window.game_field.ShowHintByIndexes(_src, _dst, puzzle_window._hint_show_time)
				effect_on_undo = false
			else
				effects_widget.visual_effects:CreateInstantEffect("HintOnUnDoEffect", puzzle_window._undo_pos)			
			end
		else
			sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(0)
			dialog_do_modal("no_hints_dialog", puzzle_window._self)
			sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)
		end
	end
}

function puzzle_window.DropToolTips()
	local tool_tip_helper = get_child_widget(puzzle_window._drop_button, "ToolTipHelperWidget", sf.gui.CToolTipHelperWidget, "ошибка получения тоолтипа") 
	tool_tip_helper.StopShowToolTip()
	puzzle_window._self.HideToolTip()
end

puzzle_window.actions.drop_button = 
{
	pressed = function(_window) 
		puzzle_window.Replay()
	end
}

puzzle_window.actions.undo_button = 
{
	pressed = function(_window) 
		puzzle_window.UnDo()
	end
}

puzzle_window.actions.menu_button = 
{
	pressed = function(_window) 
		puzzle_window.ShowMenu()
	end
}
