achievements_window = achievements_window or {}
achievements_window.actions = achievements_window.actions or {}

achievements_window.params = 
{
	-- фоновое изображение неполученной ачивки
	back_image = "achievements_achievements",
	-- фоновое изображение полученной ачивки
	back_image_completed = "achievements_achievements_completed",
		
	-- изображение, заполняющее пространство между соседними ачивками
	chain_image = "achievements_chain",
	
	-- центр иконки ачивки
	image_pos_center = sf.misc.FloatVector(85, 57),
		
	-- настройки надписи - заголовок ачивки
	label_title_params = 
	{
		-- для неполученной ачивки
		{
			font = "mpc_semibold_30_light_brown",
			color = sf.graphics.Color(255,255,255,255),
		},
		-- для полученной ачивки
		{
			font = "mpc_semibold_30_green",
			color = sf.graphics.Color(255,255,255,255),
		}
	},
	label_title_pos = sf.misc.FloatVector(158, 16),
	
	-- настройки надписи - описание ачивки
	label_description_params = 
	{
		-- для неполученной ачивки
		{
			font = "mpc_21_light_brown",
			color = sf.graphics.Color(255,255,255,255),
		},
		-- для полученной ачивки
		{
			font = "mpc_21_black",
			color = sf.graphics.Color(255,255,255,255),
		}
	},
	label_description_pos = sf.misc.FloatVector(158, 50),
	-- максимальная ширина текста с описанием ачивки. если описание ачивки длиннее этого значения, то текст переносится на следующую строку
	label_description_width = 500,
	
	-- настройки надписи - прогресс ачивки
	label_progress_params = 
	{
		-- для неполученной ачивки
		{
			font = "mpc_21_brown",
			color = sf.graphics.Color(255,255,255,255),
		},
		-- для полученной ачивки
		{
			font = "mpc_21_brown",
			color = sf.graphics.Color(255,255,255,255),
		}
	},
	label_progress_pos = sf.misc.FloatVector(600, 25),
	
	-- настройки надписи - очков ачивки
	label_score_params = 
	{
		-- для неполученной ачивки
		{
			font = "na_gradient_44_grey",
			color = sf.graphics.Color(255,255,255,255),
		},
		-- для полученной ачивки
		{
			font = "na_gradient_44",
			color = sf.graphics.Color(255,255,255,255),
		}
	},
	label_score_pos = sf.misc.FloatVector(875, 33),
	
	-- настройки прогресс-бара
	progress_image = "achievements_progress02",
	progress_frame_image = "achievements_progress02_frame",
	progress_pos = sf.misc.FloatVector(520, 25)
}

-- формируем список идентификаторов ачивок в том порядке, в каком они заданы в файле achievements.xml.
-- в этом порядке ачивки будут располагаться в таблице.
if not achievements_window.params.achievements then
	local achs_info = sf.core.CSettings()

	local loaded = achs_info.LoadXml("properties\\achievements.xml")
	__assert(loaded, "не удалось загрузить файл achievements.xml")
	
	local root = achs_info.GetFirstChild()
	__assert(root.GetId().c_str() == "Achievements", "неправильный формат файла achievements.xml")

	achievements_window.params.achievements = {}
	
    local ach_settings = root.GetFirstChildRef()
	while ach_settings do
		__assert(ach_settings.GetId().c_str() == "ach", "неправильный формат файла achievements.xml")
        __assert(ach_settings.IsValue("id"), "неправильный формат файла achievements.xml")

		table.insert(achievements_window.params.achievements, ach_settings.GetValue("id").c_str())
		
		ach_settings = ach_settings.GetNextSiblingRef()
    end
end

function achievements_window.DoDraw(_this, _renderer)
	if game_background then
		game_background.Draw(_renderer)
	end
end

function achievements_window.DoUpdate(_this)
	if game_background then
		game_background.Update()
	end
end

function achievements_window.OnChar(_this, _char, _keyboard_state, _state, _broadcast)
    return _this.SuperOnChar(_char, _keyboard_state, _state, _broadcast)
end

function achievements_window.OnKeyDown(_this, _key, _keyboard_state, _state, _broadcast)
	return _this.SuperOnKeyDown( _key, _keyboard_state, _state, _broadcast)
end

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

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

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

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

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

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

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

	local dialog = sf.gui.CWindow()
	dialog.Load(g_App.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "achievements_staticstics_window", true),
		g_App.GetSettings().GetChild("GUITemplates", false))
	
	achievements_window._InitWindow(dialog)
	achievements_window._parent = _window
	
	dialog.UpdateLayout()

	-- выставляем окно относительно родительского таким образом, чтобы абсолютные координаты равнялись (0, 0)
	local offset = sf.misc.FloatVector(0, 0)
	local parent = _window
	while parent do
		offset.X = offset.X - parent.GetOffset().X
		offset.Y = offset.Y - parent.GetOffset().Y
		parent = parent.GetParentWindow()
	end
	dialog.SetOffset(offset.X, offset.Y)
	
	if not _dont_show_recived then
		local tab_widget = get_child_widget(dialog, "achievements_tab_list", sf.gui.CTabWidget)
		if tab_widget then
			tab_widget.SelectPanel(1)
		end
	end
	--set_widget_flag_value(_window, sf.gui.CBaseWidget.FlagHidden, true)  
	
	s11.AddShowEffectToWidget(dialog, misc.hide_window_delay, misc.show_window_delay, misc.shift_before_hide, _window)
	
    _window.AddChildWindow(dialog)
end

-- для очередной ачивки создае, добавлят и выстраивыает все необходимые изображения/надписи на заданной панели
-- _panel - целевая панель - scrollable_panel
-- _i - количество уже добавленных ачивок на заданную панель. используется для определения позиций виджетов.
-- _ach_id - идентификтор ачивки
function achievements_window._AddAchievementWidgets(_panel, _i, _ach_id)
	
	-- по идентификатору получаем настройки ачивки и узнаем, выполнена ли она для екущего профиля
	local ach_settings = s11.g_Achievements.Instance().GetAchievementSettings(_ach_id)
	local ach_completed = achievements_window.achs.IsCompleted(_ach_id) ~= 0
	
	local label_param = 1
	if ach_completed then label_param = 2 end
	
	-- создаем изображение, соединяющее две соседних ачивки
	local ach_chain = sf.gui.CImageWidget(achievements_window.params.chain_image, "", 0, 0)	
				
	-- выбираем фоновое изображение в зависимости от того, выполнена ачивка или нет
	local back_image = achievements_window.params.back_image
	if ach_completed then
		back_image = achievements_window.params.back_image_completed
	end
	
	-- создаем фоновое изображение
	local ach_back = sf.gui.CImageWidget(back_image, "", 0, 0)	
		
	-- верхняя позиция (y) ачивки - вычисляется с учетом того, сколько уже ачивок добавлено на панель
	-- правая позиция (x) всегда равно 0
	local top = (ach_back.GetSize().Y + ach_chain.GetSize().Y) * _i
	
	if _i > 0 then	
		-- выставляем изображение, соединяющее две соседних ачивки, и добавляем его на панель
		ach_chain.SetOffset(0, top - ach_chain.GetSize().Y)
		local ach_chain_ptr = sf.gui.CImageWidgetPtrT(ach_chain)
		scrollable_panel.AddContentWidget(_panel, ach_chain_ptr, false)
	end
	
	-- выставляем фон и добавляем его на панель
	ach_back.SetOffset(0, top)
	local ach_back_ptr = sf.gui.CImageWidgetPtrT(ach_back)
	scrollable_panel.AddContentWidget(_panel, ach_back_ptr, false)
	
	-- создаем, выставляем и добавляем на панель иконку ачвики
	local icon_image_id = ach_settings.Image
	if not ach_completed then
		icon_image_id = ach_settings.Image.."_uncompleted"
	end
	local ach_image = sf.gui.CImageWidget(icon_image_id, "", 0, 0)
	ach_image.SetOffset(
		achievements_window.params.image_pos_center.X - ach_image.GetSize().X / 2, 
		achievements_window.params.image_pos_center.Y - ach_image.GetSize().Y / 2 + top)
	local ach_image_ptr = sf.gui.CImageWidgetPtrT(ach_image)
	scrollable_panel.AddContentWidget(_panel, ach_image_ptr, false)
	
	-- создаем, выставляем и добавляем на панель заголовок ачивки
	local ach_title = sf.gui.CLabelWidget(achievements_window.fonts_title[label_param], ach_settings.Title, "", 0, 0)
	ach_title.SetOffset(
		achievements_window.params.label_title_pos.X, 
		achievements_window.params.label_title_pos.Y + top)
	ach_title.SetColor(achievements_window.params.label_title_params[label_param].color)
	local ach_title_ptr = sf.gui.CLabelWidgetPtrT(ach_title)
	scrollable_panel.AddContentWidget(_panel, ach_title_ptr, false)
	
	-- создаем, выставляем и добавляем на панель описание ачивки
	local ach_description = sf.gui.CLabelWidget(achievements_window.fonts_description[label_param], ach_settings.Description, "", 0, 0)
	ach_description.SetOffset(
		achievements_window.params.label_description_pos.X, 
		achievements_window.params.label_description_pos.Y + top)
	ach_description.SetColor(achievements_window.params.label_description_params[label_param].color)
	ach_description.SetWordBreak(true)
	ach_description.SetSize(achievements_window.params.label_description_width, 0)
	local ach_description_ptr = sf.gui.CLabelWidgetPtrT(ach_description)
	scrollable_panel.AddContentWidget(_panel, ach_description_ptr, false)
	
	-- создаем, выставляем и добавляем на панель количество очков за ачивку
	local ach_score = sf.gui.CLabelWidget(achievements_window.fonts_score[label_param], s11.StringFormat("%i", ach_settings.Score), "", 0, 0)
	ach_score.SetOffset(
		achievements_window.params.label_score_pos.X, 
		achievements_window.params.label_score_pos.Y + top)
	ach_score.SetColor(achievements_window.params.label_score_params[label_param].color)
	local ach_score_ptr = sf.gui.CLabelWidgetPtrT(ach_score)
	scrollable_panel.AddContentWidget(_panel, ach_score_ptr, false)
	
	-- есть ли у ачивки прогресс ?
	if ach_settings.MaxProgress ~= 1 then
		
		-- текущий прогресс ачивки
		local progress = achievements_window.achs.GetProgress(_ach_id)
		
		-- создаем прогресс-бар
		local ach_progress_bar = sf.gui.CProgressBarWidget("", 0, 0)
		-- фоновое изображение прогресс-бара
		local image_progress_frame = sf.graphics.CImage(achievements_window.params.progress_frame_image)
		-- изображение поргресса в прогресс-баре
		local image_progress = sf.graphics.CImage(achievements_window.params.progress_image)
		-- устанавливаем изображения для прогресс-бара
		ach_progress_bar.SetImages(image_progress_frame, image_progress)
		-- устанавливаем размер виджета прогресс-бара в соответствии с размерами фонового изображения (без этого работать не будет)
		ach_progress_bar.SetSize(image_progress.GetTextureSize().X, image_progress.GetTextureSize().Y)
		-- значение прогресс-бара: текущий прогресс / максимальный прогресс
		ach_progress_bar.SetValue(progress / ach_settings.MaxProgress)
		-- выставляем прогресс-бар и добавляем его на панель
		ach_progress_bar.SetOffset(
			achievements_window.params.progress_pos.X, 
			achievements_window.params.progress_pos.Y + top)
		local ach_progress_bar_ptr = sf.gui.CProgressBarWidgetPtrT(ach_progress_bar)
		scrollable_panel.AddContentWidget(_panel, ach_progress_bar_ptr, false)
		
		-- создаем, выставляем и добавляем на панель надпись с текущим прогрессом
		local ach_progress = sf.gui.CLabelWidget(achievements_window.fonts_progress[label_param], 
			s11.StringFormat("%i/%i", progress, ach_settings.MaxProgress), "", 0, 0)
		ach_progress.SetOffset(
			achievements_window.params.label_progress_pos.X, 
			achievements_window.params.label_progress_pos.Y + top)
		ach_progress.SetColor(achievements_window.params.label_progress_params[label_param].color)
		local ach_progress_ptr = sf.gui.CLabelWidgetPtrT(ach_progress)
		scrollable_panel.AddContentWidget(_panel, ach_progress_ptr, false)		
	end	
	
	scrollable_panel.UpdateSize(_panel)
end

-- инициализация окна ачивок
function achievements_window._InitWindow(_window)

	-- надпись - очки достижений
	local current_score_label = get_child_widget(_window, "current_score", sf.gui.CLabelWidget)
	__assert(current_score_label, "не удалось загрузить current_score")

	local tab_widget = get_child_widget(_window, "achievements_tab_list", sf.gui.CTabWidget)
	__assert(tab_widget, "не удалось загрузить achievements_tab_list")

	-- количество панелей на таб-виджете должно равняться 3: все, полученные и неполученные
	local panels_num = tab_widget.EnumPanels()
	__assert(panels_num == 3, "количство панелей на achievements_tab_list не равно 3")
	
	-- получаем указатели на панели.
	-- панели представляют собой луа-виджеты, поведение которых определяется scrollable_panel
	local panels = 
	{
		tab_widget.GetPanelContent(0).GetWidget("panel", true).get(),
		tab_widget.GetPanelContent(1).GetWidget("panel", true).get(),
		tab_widget.GetPanelContent(2).GetWidget("panel", true).get()
	}
	
	local i = 0
	
	-- получаем шрифты для всех надписей ачивки
	achievements_window.fonts_title = 
		{
			g_App.GetResourceManager().GetFont(achievements_window.params.label_title_params[1].font),
			g_App.GetResourceManager().GetFont(achievements_window.params.label_title_params[2].font)
		}
	achievements_window.fonts_description = 
		{
			g_App.GetResourceManager().GetFont(achievements_window.params.label_description_params[1].font),
			g_App.GetResourceManager().GetFont(achievements_window.params.label_description_params[2].font)
		}
	achievements_window.fonts_progress = 
		{
			g_App.GetResourceManager().GetFont(achievements_window.params.label_progress_params[1].font),
			g_App.GetResourceManager().GetFont(achievements_window.params.label_progress_params[2].font)
		}
	achievements_window.fonts_score = 
		{
			g_App.GetResourceManager().GetFont(achievements_window.params.label_score_params[1].font),
			g_App.GetResourceManager().GetFont(achievements_window.params.label_score_params[2].font)
		}
	
	-- текущий профайл
	local profile = s11.g_ProfileManager.Instance().GetCurrentProfile()
	__assert(profile)
		
	-- параметры ачивки для текущего профайла.
	-- параметры включают в себя 2 значения: текущий прогресс (равен 1, если у ачивки не может быть прогресса) и порядковый номер 
	-- получения ачивки, т.е. какой по счету ачивку заработали (равен 0, если ачивка еще не получена)
	achievements_window.achs = s11.g_Achievements.Instance().GetProfileAchievements(profile)
	
	-- записываем очки достижений текущего профайла в соответствующую надпись 
	local current_score_text = 
		s11.StringFormat(current_score_label.GetText(), achievements_window.achs.GetScore())
	current_score_label.SetText(current_score_text)
	
	-- теперь формируем списки ачивок. всего 3 списка: все, полученные и неполученные.
	-- "все": первым в списке идет ачивка, которую получили последней, за ней располагаются остальные ачивки в том порядке, в каком они были
	-- заданы в файле achievements.xml
	-- "полученные" - ачивки располагаются в порядке их получения, начиная с последней полученной (стек)
	-- "неполученные" - ачивки располагаются в в том порядке, в каком они были заданы в файле achievements.xml
	
	-- achievements_window.params.achievements хранит список идентификатовро ачивок в том порядк, в котором они были заданы в файле achievements.xml
	
	-- теперь формируем список идеетификаторов ачивок, который будет отсортирован таким образом, что сначала в нем будут идти ачивки в порядке их
	-- получения, начиная с последней полученной, а затем все остальные в том порядке, в котором они были заданы в файле achievements.xml.
	
	local achs = {}
	local sort_achs = {}
	
	-- создаем список идентификаторов ачивок на основе achievements_window.params.achievements
	for i,a in ipairs(achievements_window.params.achievements) do
		table.insert(sort_achs, a)
		achs[a] = i
	end
	
	-- функция сортировки.
	-- сравниваем две ачивки. 
	-- возвращает true, если первая ачивка была получена раньше второй.
	-- если обе ачивки не получены, то проверяет, какая из ачивок в файле achievements.xml описана раньше,
	-- и возвращает true, если первая ачивка описана раньше второй.
	-- во всех остальных случаях возвращает false
	-- _ach1 - идентификатор первой ачивки
	-- _ach2 - идентификатор второй ачивки
	local sort_func = 	
		function (_ach1, _ach2)
			-- номер получения первой ачивки (0, если не получена)
			local completed1 = achievements_window.achs.IsCompleted(_ach1)
			-- номер получения второй ачивки (0, если не получена)
			local completed2 = achievements_window.achs.IsCompleted(_ach2)
			
			-- если ачивки не равны значит хотя бы одна из обязательно получена и значит можно сравнить их по номер получения.
			if completed1 ~= completed2 then
				return completed1 > completed2
			end
			
			-- если ачивки оказались равными, значит они обе не получены.
			-- будем выяснять, как из них описана раньше в файле achievements.xml.
			return achs[_ach1] < achs[_ach2]
		end 
		
	-- зыпускаем сортировку
	table.sort(sort_achs, sort_func)

	local i=0
	
	-- узнаем, есть ли хоть одна завершенная ачивка
	local has_completed = achievements_window.achs.IsCompleted(sort_achs[1]) ~= 0
	
	-- если завершенные ачивки есть, добавляем последнюю полученную из них  в список "все"
	if has_completed then
		achievements_window._AddAchievementWidgets(panels[1], i, sort_achs[1])
		i = i + 1
	end
	
	-- заполняем список "все".
	-- добавлем все ачивки в том порядке, в котором они расположены в файле achievements.xml.
	-- добавляем все, кроме уже добавленной (последняя полученная)
	for _,a in ipairs(achievements_window.params.achievements) do
		if not has_completed or a ~= sort_achs[1] then
			achievements_window._AddAchievementWidgets(panels[1], i, a)
			i = i + 1
		end
	end
	
	-- заполняем списки "полученные" и "неполученные"
	-- в списке sort_achs идут сначала все полученные, потом нполученные. поэтому идем по списку до тех пор, пока ни встретится первая
	-- неполученная ачивка, и добавляем каждую в панель "полученные".
	-- как только встретилась неполученная ачивка, меняем целевую панель на "неполученные" и все остальные ачивки уже добавляем на неё.
	local i = 0
	local p = 2 -- номер панели 
	for _,a in ipairs(sort_achs) do
		if p == 2 then
			if achievements_window.achs.IsCompleted(a) == 0 then
				i = 0
				p = 3
			end
		end
		achievements_window._AddAchievementWidgets(panels[p], i, a)
		i = i + 1
	end
	
	if game_background then
		game_background.Init()
		game_background.SetUseClip(false)
	end
end

achievements_window.actions.close = 
{
	pressed = function(_window) 
		s11.AddHideEffectToWidget(_window, 300, 300, 300, achievements_window._parent)
	end
}

achievements = achievements or {}
achievements.statistics_window = achievements_window or {}