achievements = achievements or {}

achievements.params = 
{
	back_image = "screens_achievements_achievements_scenes", -- изображение подложки
	back_rect  = { x = 200, y = 505, x2 = 739, y2 = 648 }, -- расположение подложки
	icon_pos = { x = 210, y = 525 }, -- позиция левого верхнего угла иконки ачивмента
    
    effects = -- эффекты на всплывающем окне ачивментов
    {
        on_popup_get = -- эффект при появлении всплывающего окна, если просто увеличили прогресс ачивки
        {
            bottom = -- под окном
            {
                clip = "", 
                pos = { x = 500, y = 553 }
            },
            
            top = -- над окном
            {
                clip = "achievements_completed_effect03",
                pos = { x = 490, y = 503 }
            }
        },
        on_popup_complete = -- эффект на окно если получили ачивку полностью
        {
            bottom = -- под окном
            {
                clip = "achievements_completed_effect01", 
                pos = { x = 430, y = 503 }
            },
            
            top = -- над окном
            {
                clip = "achievements_completed_effect02",
                pos = { x = 490, y = 503 }
            }
        },
        
        clip_on_take = "achievements_effect02" -- ид клипа для achievements.CreateTakeEffect
    },
    
	texts = -- описания текстов 
    {
        title =  -- название ачивки
        {
            font = "font_20", -- шрифт
            color = sf.graphics.Color(255, 255, 255, 255), -- цвет
            pos = { x = 310, y = 542 } -- позиция
        },
        score = -- очки
        {
            font = "font_40",
            color = sf.graphics.Color(255, 255, 255, 255),
            pos = { x = 644, y = 554 }
        },
        progress = -- прогресс ачивки текстом
        {
            font = "font_12_black",
            color = sf.graphics.Color(255, 255, 255, 255),
            pos = { x = 570, y = 595 }
        },
        description = -- описание ачивки
        {
            font = "font_12_black",
            color = sf.graphics.Color(255, 255, 255, 255),
            pos = { x = 300, y = 562 },
            width = 300 -- максимальная ширина текста; излишки переносятся на след. строку
        },
        info = 
        {
            font = "font_12_black",
            color = sf.graphics.Color(255, 255, 255, 255),
            pos = { x = 640, y = 547 },
            text = 2268
        },
        info2 = 
        {
            font = "font_12_black",
            color = sf.graphics.Color(255, 255, 255, 255),
            pos = { x = 640, y = 594 },
            text = 2269
        }
    },
    
    progress = -- настройки прогресс-бара
    {
        image = "screens_achievements_progressbar", -- изображение заполнения прогресбара
        frame_image = "screens_achievements_progressbar_back", -- фон прогрессбара
        pos = { x = 365, y = 594 } -- позиция
    },

	view_time = 4000, -- время в мс, сколько будет отображаться окошко с ачивкой
    sound_show_popup = "mini_scene_open_01", -- звук при появлении всплывающего окна
    sound_achievement_complete = "mini_game_completed", -- звук на получение ачивмента; звук всплывающего окна не проигрывается
}

function achievements.GetAchievement(_achievement)
	-- если game не забинден, значит вызов идет из QEditor
	-- в QE ачивки не работают => игнорируем вызов
	if not game then return end
	
	local profile = game.g_ProfileManager.Instance().GetCurrentProfile()
	__assert(profile)
		
	local achs = game.g_Achievements.Instance().GetProfileAchievements(profile)

	if achs.IsCompleted(_achievement) ~= 0 then return end
	
	achs.AddProgress(_achievement, 1)
    
	local cur_progress = achs.GetProgress(_achievement)
	local ach_settings = game.g_Achievements.Instance().GetAchievementSettings(_achievement)
	local completed = cur_progress == ach_settings.MaxProgress 
	local show_progress = cur_progress == 1 or (ach_settings.MaxProgress > 1 and cur_progress % ach_settings.ShowProgressStep == 0)
	if completed or show_progress then
        -- показываем окно ачивментов
		achievements._ShowPopup(_achievement, achs.GetProgress(_achievement)) 
        -- воспроизводим подходящий звук
        if completed then
            if achievements.params.sound_achievement_complete ~= "" then
                sound(achievements.params.sound_achievement_complete)
            end
        elseif show_progress then
            if achievements.params.sound_show_popup ~= "" then
                sound(achievements.params.sound_show_popup)
            end
        end
	end
end

function achievements.IsAchievementComplete(_achievement)
	-- если game не забинден, значит вызов идет из QEditor
	-- в QE ачивки не работают => игнорируем вызов
	if not game then return false end
    
    local profile = game.g_ProfileManager.Instance().GetCurrentProfile()
	__assert(profile)
    local achs = game.g_Achievements.Instance().GetProfileAchievements(profile)

	return achs.IsCompleted(_achievement) ~= 0
end

-- создает эффект-клип на объекте _object со сдвигом (_offset_x, _offset_y)
-- id клипа берется из achievements.params
function achievements.CreateTakeEffect(_object, _offset_x, _offset_y)
    if not _offset_x then _offset_x = 0 end
    if not _offset_y then _offset_y = 0 end
    
    local obj_pos = quest.get_object_pos(_object)
    __assert(obj_pos, "Объект '".._object.."' не найден!")
    
    -- создаем клип-эффект и располагаем его так, чтобы центр нижнего края клипа совпадал
    -- с центром объекта
    local clip = over_scene_effect_widget.AddClipEffect(achievements.params.effects.clip_on_take)
    clip.SetPos(obj_pos + sf.misc.FloatVector(_offset_x, -clip.GetSize().Y/2 + _offset_y))
end

function achievements._ShowPopup(_achievement, _progress)
	local settings = game.g_Achievements.Instance().GetAchievementSettings(_achievement)

	achievements.icon = sf.core.g_Application.GetResourceManager().GetTexture(settings.Image)
	__assert(achievements.icon, "ACHIEVEMENTS: не найдена иконка ачивмента '"..tostring(settings.Image).."'!")
	
	-- если макс. прогресс больше 1, то надо отобразить текущий прогресс
	achievements.progress = nil
	if settings.MaxProgress > 1 then
		achievements.progress = _progress
		achievements.max_progress = settings.MaxProgress
        
        achievements.progress_bar.SetValue(achievements.progress / achievements.max_progress)
	end
	
    achievements.score = settings.Score
	achievements.title = settings.Title
    achievements.description = settings.Description
    
    -- инициализируем клипы эффектов
    achievements.effects = {}
    local effect = nil
    if _progress == settings.MaxProgress then
        -- эффект на получение ачивки полностью
        effect = achievements.params.effects.on_popup_complete
    else
        -- эффект на увеличение прогресса ачивки
        effect = achievements.params.effects.on_popup_get
    end
    if effect.top and effect.top.clip and effect.top.clip ~= "" then
        achievements.effects.top = sf.misc.anim.CClip()
        achievements.effects.top.Load(effect.top.clip, true)
        achievements.effects.top.SetPos(sf.misc.FloatVector(effect.top.pos.x, effect.top.pos.y))
    end
    if effect.bottom and effect.bottom.clip and effect.bottom.clip ~= "" then
        achievements.effects.bottom = sf.misc.anim.CClip()
        achievements.effects.bottom.Load(effect.bottom.clip, true)
        achievements.effects.bottom.SetPos(sf.misc.FloatVector(effect.bottom.pos.x, effect.bottom.pos.y))
    end
    
	achievements.timer.Get().SetTime(0)
	
	achievements.visible = true
end

function achievements.DoDraw(_this, _renderer)
	if not achievements.visible then return false end
	
    -- отрисовываем эффект под всем
    if achievements.effects.bottom then
        achievements.effects.bottom.Draw(_renderer)
    end
    
	-- отрисовываем подложку
	local dest = sf.misc.FloatRect(achievements.params.back_rect.x, achievements.params.back_rect.y, 0, 0)
	dest.Width = achievements.params.back_rect.x2 - dest.X
	dest.Height = achievements.params.back_rect.y2 - dest.Y
	_renderer.RenderTextureBox(achievements.back_image.GetTexture(0), dest, 
		sf.misc.IntRect(0, 0, achievements.back_image.GetWidth(), achievements.back_image.GetHeight()), sf.graphics.Color(255, 255, 255, 255)) 
	
	-- отрисовываем иконку ачивмента
	_renderer.RenderTexture(achievements.icon.GetTexture(0), 
		achievements.params.icon_pos.x, achievements.params.icon_pos.y, sf.graphics.Color(255, 255, 255, 255))
        
    -- отрисовываем прогресс бар, если надо
    if achievements.progress then
        achievements.progress_bar.Draw(_renderer)
    end
        
    -- заполняем тексты
    local text_content = {}
    text_content.title = achievements.title
    text_content.score = tostring(achievements.score)
    -- прогресс отображается не всегда
    if achievements.progress then
        text_content.progress = string.format("%i/%i", achievements.progress, achievements.max_progress)
    else
        text_content.progress = false
    end
    text_content.description = achievements.description
    
    -- отрисовываем текста
    for id, text_info in pairs(achievements.params.texts) do
        local text = text_info.text or text_content[id]
        __assert(text ~= nil)
        if text ~= false then
            if type(text) == "number" then
                text = sf.misc.g_StringTable.Instance().GetString(text)
            end
            
            local back_color = sf.graphics.Color(0, 255, 255, 255)
            if text_info.width then -- отрисовываем как мультистринг
                _renderer.RenderText(achievements._fonts[id], text,
                    sf.misc.IntRect(text_info.pos.x, text_info.pos.y, text_info.width, 0), 
                    sf.graphics.CRenderer.TextWordBreak, 0, text_info.color, back_color)
            else -- отрисовываем как однострочный текст
                _renderer.RenderString(achievements._fonts[id], text, text_info.pos.x, text_info.pos.y, -1, -1, 1, 
                    text_info.color, sf.graphics.Color(0, 255, 255, 255))
            end
        end
    end
    
    -- отрисовываем эффект над всем
    if achievements.effects.top then
        achievements.effects.top.Draw(_renderer)
    end
    
	if achievements.timer.Get().GetTime() >= achievements.params.view_time then
		achievements.visible = false
        achievements.effects = {}
	end
	
	return false
end

function achievements.OnEndLevel()
    local profile = game.g_ProfileManager.Instance().GetCurrentProfile()
    local stats = profile.GetAchievementsStats()
    
    local level_id = quest.global_played_level.GetId()
    
    if not quest.g_LuaVariables.difficulty_changed then
        if difficulty.IsEasyDifficulty() then
            stats.AddEasyLevel(level_id)
            if stats.EnumEasyLevels() == 9 then
                achievements.GetAchievement("play_by_novice")
            end
        else
            stats.AddHardLevel(level_id)
            if stats.EnumHardLevels() == 9 then
                achievements.GetAchievement("play_by_expert")
            end
        end
    end
end

function achievements.DoUpdate(_this)
	if achievements.effects then
        for _,clip in pairs(achievements.effects) do
            clip.Update()
        end
    end
	return false
end

function achievements.OnMouseDown(_this, _pos, _button, _state, _broadcast)
	if not _broadcast then
		local rect = achievements.params.back_rect
		if _pos.X >= rect.x and _pos.X <= rect.x2 and _pos.Y >= rect.y and _pos.Y <= rect.y2 then
			achievements.visible = false
		end
	end
	return false
end

function achievements.Load(_this)
	achievements.this = _this
    
    -- инициализируем шрифты для текста
    achievements._fonts = {}
    for id, content in pairs(achievements.params.texts) do
        local font = g_App.GetResourceManager().GetFont(content.font)
        __assert(font, "ACHIEVEMENTS: шрифт '"..content.font.."' не найден!")
        achievements._fonts[id] = font
    end
	
	achievements.back_image = sf.core.g_Application.GetResourceManager().GetTexture(achievements.params.back_image)
	__assert(achievements.back_image, "ACHIEVEMENTS: изображение '"..achievements.params.back_image.."' не найдено!")
    
    -- создаем прогресс-бар
    ach_progress_bar = sf.gui.CProgressBarWidget("", 0, 0)
    -- фоновое изображение прогресс-бара
    local image_progress_frame = sf.graphics.CImage(achievements.params.progress.frame_image)
    -- изображение поргресса в прогресс-баре
    local image_progress = sf.graphics.CImage(achievements.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.SetOffset(achievements.params.progress.pos.x, achievements.params.progress.pos.y)
    achievements.progress_bar = ach_progress_bar
	
	achievements.visible = false
	achievements.timer = __create_timer()
end

function achievements.__CreateInstance()
	return "achievements"
end

__inherite( achievements, null_lua_widget_handler() )