endless_window = {}
endless_window.actions = {}

endless_window._hint_show_time = 5000   -- время отображения хинта(возможно потом будет перенесено)
endless_window._hint_resume_time = 5000 -- время восстановления подсказки
endless_window._auto_save_time = 20000  -- время автосохранения снепшота играы в файл
endless_window._gem_add_per_extro_session = 10  -- чило камней которые увеличиваются каждую сесию после поредленной

endless_window._level_name_str = sf.misc.g_StringTable.Instance().FormatByStringsID("$385")

endless_window._session_name_clip = "start_level"  -- id клипа для отображение начала сессии
endless_window._session_name_clip_pos = sf.misc.FloatVector(353.5, 353.5)  -- позиция клипа с названием сессии

local self = endless_window

endless_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
}

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

	game_field_image = true,
	gem_bar_image = true,
	gui_1 = true,
	gui_2 = true,
	gui_3 = true,
}

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

endless_window._overload_functions =
{
	IsLuaEffects = function ()
		return totems_widget.IsTotemEffects()
	end,

	OnAddScore = function()
		-- обновляем счет
		endless_window._scores_effect:SetTargetValue(endless_window.profile_data.GetScore())
	end,
	
	OnPlayerDestroyMatch = function(_color)
		-- добвляем цвет в очереди обработки тотемов
		totems_widget.AddColor(_color)
	end,
	
	OnAllGemsCollected = function()
	end,

	OnLoseGame = function ()
		__message("lose is no posible")
	end,
	
	OnLastGemAdd = function ()
		self.game_field.InitNoEffectsEvent()
	end,
	
	OnNoEffects = function ()
		endless_window.GoToNextStage(1)
	end,

	OnCreateSnapshot = function ()
	end,
	
	OnNoMoves = function ()
		__sound("no_moves_drop")
        -- отображение текста нет ходов
        endless_window.game_field.PlayClipOnField("nomore_moves01");

		self.profile_data.ReturnToStartLevelSnapshot()

		self.Show(self._dif_level, self._level_index, nil, true, true)
		avatar_widget.ChangeMood("no_moves_endless")
	end
}

function endless_window.GoToNextStage(_next)
		endless_window._stage_finish_count = endless_window._stage_finish_count + _next
		if endless_window._stage_finish_count == 15 then
			achievements.GetAchievement("endless_15_levels")
		end
		drop_buttons.SetDropButtonsCount(2)
		avatar_widget.ChangeMood("endless_finish_session")
		-- сбрасываем все камни
		self.game_field.DropCollectedGems()
		self.game_field.SetGameTime(0)
		
		-- переходим к следующем уровню
		local next_level = nil
		
		-- ищем следующий уровень
		self._level_index = self._level_index + _next

						
		local dif_levels_count = self._levels_struct.GetDifLevelsCount()
		
		if dif_levels_count > self._dif_level then
		
			local levels_count = self._levels_struct.GetLevelsCount(self._dif_level)
			if levels_count <= self._level_index then
				self._dif_level = self._dif_level + 1
				self._level_index = self._level_index - levels_count
			end
		end
		

		if endless_window._level_label then
			local level_index = self._levels_struct.GetLevelIndex(self._dif_level, self._level_index) + 1
			local level_name = s11.StringFormat(endless_window._level_name_str, level_index)
			endless_window._level_label.SetText(level_name)
			self.game_field.AddTextClip(endless_window._session_name_clip, level_name, endless_window._session_name_clip_pos, 1, self._game_timer)
		end

		-- получаем следующий уровень про координатам или последний если мы уже вышли за рамки предустановеных уровней
		local match_level, psevdo_level_index = endless_window.GetMatchLevel(self._dif_level, self._level_index)
		self.gameplay_settings.GetInfoFromLevel(match_level)
		
		
		if psevdo_level_index then
		    -- если вышли за рамки то формируем урвоень по номеру псевдоуровня
			self._FormPsevdoLevel(psevdo_level_index, self.gameplay_settings)
		else
		    -- иначе берем параметры из имеющегося уровня
			self.UpgradeItems(match_level)
		end
		
		self.profile_data.SetSavedLevelDifficulty(self._dif_level)
		self.profile_data.SetSavedLevelIndex(self._level_index)
		
		self.profile_data.CreateStartLevelSnapshot()
		self.gameplay_settings.FormSettingsInfo(match_level)
		
		
		-- иницируем прогрессбар с камнями
		gems_bar_widget.Init(self.game_field, self._self)
		-- инициируем тотемов
		totems_widget.Init(self.game_field)

		
		self.SaveGame()
end

function endless_window.GetMatchLevel(_dif_level, _level_index)
	local psevdo_level = nil
	local dif_level = _dif_level
	local level_index = _level_index
	if dif_level > self._last_dif_level then
		dif_level = self._last_dif_level
		level_index = self._last_level_index
		psevdo_level = _level_index
	end
	local level = self._levels_struct.GetLevel(dif_level, level_index)
	if not level then
		__message("level dif:"..tostring(self._dif_level).." index:"..tostring(self._level_index).."not found")
		return nil
	end
	local match_level = __cast(level, s11.CMatchLevelInfo)
	if not match_level then
		__message("level dif:"..tostring(self._dif_level).." index:"..tostring(self._level_index).."not Match level")
		return nil
	end
	return match_level, psevdo_level
end

function endless_window.UpgradeItems(_level)
	if _level.EnumDependences() ~= 0 then
		local current_dep = _level.GetDependences()
		while not current_dep.IsEnd() do
			local dependence = current_dep.Get()
			
			local upgrade = dependence.BuildingId.c_str()
			local current_level = self.gameplay_settings.GetItemLevel(upgrade)
			if current_level < 4 then
				self.gameplay_settings.SetItemLevel(upgrade, current_level + 1)
				self.profile_data.SetItemLevel(upgrade, current_level + 1)
			else
				__message("max upgrade level error :" ..upgrade)
			end
			
			current_dep.Next()
		end
	end
end

function endless_window.Show(_dif_level, _level_index, _load_level, _do_not_save_on_start, _do_not_drop_mood, _unload_resources)

	local window = __ChangeWindowWithEffect(nil, _unload_resources)
	if not window then
		return
	end
	
	endless_window._start_effect = start_level_effect
	
	sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)	
	
	endless_window._stage_finish_count = 0
	
	game_time_counter.Init()
	
	local endless_info = g_App.GetSettings().GetChild("Constants", false).GetChild("endless_options", false)
	
	endless_window._gem_add_per_extro_session = tonumber(endless_info.GetValue("gems_on_exto_session").c_str())

	game.GameEventsOverload(self._overload_functions)
    -- сбрасываем режим скринсейвера, который мог остаться с конца уровня
    
	self._levels_struct = s11.g_GameStruct.Instance().GetLevelsSystem(s11.CGameStruct.GameTypeEndless)
	
	self._game_timer = sf.core.g_Application.GetTimeManager().GetTimer("game_timer")
	
	self._last_dif_level = self._levels_struct.GetDifLevelsCount() - 1
	self._last_level_index = self._levels_struct.GetLevelsCount(self._last_dif_level) - 1

	self._end_level_effect = nil
	self._autosave_timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().GetTimer("game_timer").AttachTimer(""))


	self._self =  window

	window.Load(
		g_App.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "endless_window", true), 
		g_App.GetSettings().GetChild("GUITemplates", false))
	window.SetSize(g_App.GetRenderer().GetWidth(), g_App.GetRenderer().GetHeight())
	window.UpdateLayout()
	
	self.current_profile = s11.g_ProfileManager.Instance().GetCurrentProfile()
	
	avatar_widget.InitAvatar(self.current_profile.IsFemale(), _do_not_drop_mood)
	self.profile_data = self.current_profile.GetEndlessData()
	
	-- инициализация объекта для управлениея флагами отображэения туториала
	self._tutorial_flags = self.profile_data.GetTutorialFlags()
	-- туториал на первый камень
	self._start_tutorial = not self._tutorial_flags.ReadFlag(s11.CProfileDataEndless.TutorialFlagNoMoves)
	
	
	self.game_field_image_widget = get_child_widget(window, "game_field_image", sf.gui.CImageWidget, "ошибка" )
	
	self.game_widget = get_child_widget(window, "game_widget", s11.CGameFieldWidget, "ошибка" )
	
	self.score_label_widget = get_child_widget(window, "score_label", sf.gui.CLabelWidget, "ошибка" )
	
	endless_window._scores_effect = CScoresEffect(self.score_label_widget)
    
	self._session_time_label = get_child_widget(window, "session_time_label", sf.gui.CLabelWidget, "ошибка" )
	self._game_time_label = get_child_widget(window, "game_time_label", sf.gui.CLabelWidget, "ошибка" )
	
	
    offer_label = get_child_widget(self._self, "end_level_offer_label", sf.gui.CLabelWidget, "ошибка" )
    offer_label.AddFlags(offer_label.FlagHidden)
	
	
	self._player_name_label = get_child_widget(window, "player_name_label", sf.gui.CLabelWidget, "ошибка" )
	
	self._player_name_label.SetText(self.current_profile.GetName())
	
	-- если кнопки для хинта нет, то ругаемся и выходим
	self._hint_button_widget = get_child_widget(window, "hint_button", sf.gui.CButtonWidget)
	if not self._hint_button_widget then
		__message("Button hint_button not found")
		return
	end
	
	self._Init(_dif_level, _level_index, _load_level, _do_not_save_on_start)
	
	drop_buttons.Init(window, self.game_info)	
	if not _load_level then
		drop_buttons.SetDropButtonsCount(2)
	end
	if self.game_field_image_widget then
		self.game_field.SetShakedWidget(self.game_field_image_widget)
	end
	
	game_helpers.SetFieldPos(self.game_widget.GetOffset())
	
	s11.g_TrackManager.Instance().UpdateCurrentTrack("town_map", false)

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

	-- событие на открытие окна
	self.OnShowWindow = function ()
		if self._start_effect then
			self._start_effect.StartBeginLevelEffect()
		end
	end
	
	window = 0
	collectgarbage()
end

function endless_window._OnFormLevel()
	if self._start_tutorial then
		self._start_tutorial = false
		--инициация туториала для первого запуска режима endless
		self._tutorial_flags.RaiseFlag(s11.CProfileDataEndless.TutorialFlagNoMoves)
		sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(0)
		dialog_do_modal("endless_first_game_dialog", self._self)
		sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)
	end
end

function endless_window._FormPsevdoLevel(_psevdo_level_index, _gameplay_settings)
	_gameplay_settings.SetGemTarget(_gameplay_settings.GetGemTarget() + endless_window._gem_add_per_extro_session*(_psevdo_level_index + 1))
end

function endless_window._Init(_dif_level, _level_index, _load_level, _do_not_save_on_start)

	local match_level, _psevdo_level_index =  endless_window.GetMatchLevel(_dif_level, _level_index)
	if match_level then 
			
		self._dif_level = _dif_level
		self._level_index = _level_index

		-- инициализируем фон
		-- нужен рандомный
		s11.g_GameBackground.Instance().Init(1, 1)
		s11.g_GameBackground.Instance().SetUseClip(false)

		-- инициализируем номер уровня
		endless_window._level_label = get_child_widget(self._self, "level_label", sf.gui.CLabelWidget, "ошибка" )
		if endless_window._level_label then
			local level_index = self._levels_struct.GetLevelIndex(_dif_level, _level_index) + 1
			endless_window.level_name = s11.StringFormat(endless_window._level_name_str, level_index)
			endless_window._level_label.SetText(endless_window.level_name)
		end
		
		local current_profile = self.profile_data
		if not _load_level and not _do_not_save_on_start then
			current_profile.CreateStartLevelSnapshot()
		
			current_profile.SetSavedLevelDifficulty(_dif_level)
			current_profile.SetSavedLevelIndex(_level_index)

			self.SaveGame()
		end
		
		
		-- формируем игровые настройки
		self.gameplay_settings = s11.GameplaySettings(match_level)
		if _psevdo_level_index then
			endless_window._FormPsevdoLevel(_psevdo_level_index, self.gameplay_settings)
		end

		if _load_level or _do_not_save_on_start then
			for i = 0, s11.items.ItemsCount do
				local item_id = s11.game_helpers.GetItemIdByIndex(i)
				self.gameplay_settings.SetItemLevel(item_id, current_profile.GetItemLevel(item_id))
			end
		end
		
		self.gameplay_settings.FormSettingsInfo(match_level)
	
		self.game_widget.InitGameField(match_level, self.profile_data, self.gameplay_settings, _load_level or false)
	
		self.game_field = self.game_widget.GetGameField()
		game_window.game_field = self.game_field
		
		self.game_info = self.game_field.GetGameInfo()
		
		-- формируем кнопку hint на основании виджета кнопки
		hint_button.FormHintButton(self._hint_button_widget)
		-- иницируем кнопку hint в зависимости от игровой информации
		self.InitHintButton()
		
		-- иницируем прогрессбар с камнями
		gems_bar_widget.Init(self.game_field, self._self)
		-- инициируем отображение тотемов
		totems_widget.Init(self.game_field)
	end
end

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

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

function endless_window.DoUpdate(_this)

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

	if endless_window.OnShowWindow then
		if not s11.WindowHasEffects(self._self) then
			local show_func = endless_window.OnShowWindow
			endless_window.OnShowWindow = nil
			show_func()
		end
	end

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

	-- обновление кнопки хинт
	self.UpdateHintButton()
	
	endless_window._scores_effect:Update()
	
	if self._autosave_timer.Get().GetTime() > self._auto_save_time then
		self.SaveGame()
		self._autosave_timer.Get().SetTime(0)
	end	
	
	local frame_delta = self._game_timer.GetFrameDelta()
	
	game_time_counter.AddGameTime(frame_delta)
	
	self._session_time_label.SetText(TimeToString(self.game_field.GetGameTime()))
	self._game_time_label.SetText(TimeToString(self.profile_data.GetTotalTime(), true))
end

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

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

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

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

function endless_window.OnKeyDown(_this, _key, _keyboard_state, _state, _broadcast)
	if sf.core.g_Application.GetDebugLevel() >= sf.core.g_Application.DebugCheats then
		if _key == 115 then
			for i = 0, 10 do
				endless_window.GoToNextStage(1)
			end
		end
		if _key == 116 then
			endless_window.GoToNextStage(1)
		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 = self._totems_cheat_table[_key]
		if totem_color then
			totems_widget.AddColor(totem_color)
		end
	end
    
	if _this.SuperOnKeyDown( _key, _keyboard_state, _state, _broadcast) then
		return true
	end
	
	if _key == 27 then
		endless_window.ShowMenu()
		return true
	end
	
	return false
end

function endless_window.ShowMenu()
	endless_menu_window.Show(self._self)
	if endless_window._start_effect then
		endless_window._start_effect.InstantApply()
	end
end

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

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

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

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

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

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

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

function endless_window.SaveGame()
	self.current_profile.SaveGameType(s11.CGameStruct.GameTypeEndless)
	s11.g_Achievements.Instance().SaveProfilesAchievements()
end

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

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

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

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

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