main_menu = main_menu or {}
main_menu.actions = main_menu.actions or {}

main_menu.alpha_hide_delay = 5000
main_menu.alpha_show_delay = 2000
main_menu.start_effect_state = nil
main_menu.start_effect_time = nil
main_menu.total_effect_time = nil
main_menu.timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().GetTimer(_T("main")).AttachTimer(_T("")))

main_menu.name_title_string_id = sf.misc.g_StringTable.Instance().FormatByStringsID(g_App.GetSettings().GetChild(_T("Constants"), false).GetChild(_T("main_menu"), false).GetValue(_T("simple_title_id")).c_str())
main_menu.simple_title_string_id = sf.misc.g_StringTable.Instance().FormatByStringsID(g_App.GetSettings().GetChild(_T("Constants"), false).GetChild(_T("main_menu"), false).GetValue(_T("name_title_id")).c_str())

main_menu.menu_track_id = g_App.GetSettings().GetChild(_T("Constants"), false).GetChild(_T("main_menu"), false).GetValue(_T("track")).c_str()

function main_menu.init_welcome(_target_window)
        local label_widget = __cast(_target_window.GetWidget(_T("welcome_label")).get(), "sf.gui.CLabelWidget")
        local change_button_widget = __cast(_target_window.GetWidget(_T("change_player_button")).get(), "sf.gui.CButtonWidget")
        if label_widget then
                local num_profiles = game.g_ProfileManager.Instance().EnumProfiles()
                local current_profile = game.g_ProfileManager.Instance().GetCurrentProfile()
                if num_profiles ~= 0 and current_profile then
                        local profile_name = game.g_ProfileManager.Instance().GetCurrentProfile().GetName()
                        label_widget.SetText(
                        qe.StringFormat(main_menu.name_title_string_id, profile_name)
                        )
                        set_widget_flag_value(change_button_widget, sf.gui.CBaseWidget.FlagHidden, false)
                        set_widget_flag_value(change_button_widget, sf.gui.CBaseWidget.FlagDisabled, false)

                        if main_menu.start_effect_state then
                            set_widget_flag_value(change_button_widget, sf.gui.CBaseWidget.FlagDisabled, true)
                        end
                        
                else
                        label_widget.SetText(main_menu.simple_title_string_id)
                        set_widget_flag_value(change_button_widget, sf.gui.CBaseWidget.FlagHidden, true)
                        set_widget_flag_value(change_button_widget, sf.gui.CBaseWidget.FlagDisabled, true)
                end
        end
end

function main_menu.DoDraw(_this, _renderer)
end

main_menu.cheat_queue = {"a", "n", "a", "s", "t", "a", "s", "i", "a"}

main_menu.cheat_index = 1

function main_menu.OnChar(_this, _char, _keyboard_state, _state, _broadcast)
    if _this.SuperOnChar(_char, _keyboard_state, _state, _broadcast) then return true end	
	local a = sf.core.g_Application.GetDebugLevel()
	if sf.core.g_Application.GetDebugLevel() >= sf.core.g_Application.DebugCheats and _broadcast == false then
		local char_number = game.CharToInt(_char)
		local number = tonumber(_char)
		if _char == "0" then number = 10 end
		if _char == "-" then number = 11 end
		if _char == "=" then number = 12 end
		if _char == "\\" then number = 13 end
		if char_number == 8 then  number = 14 end
		if number and number>=1 and number<=14 then
			main_menu.RunGame(number)
			return true
		end
		if _char == 'F' or _char == 'f' then
			-- Font viewer
			local dialog = game.CFontViewerWindow()
			dialog.Load(g_App.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "font_viewer", true),
				g_App.GetSettings().GetChild("GUITemplates", false))
			dialog.UpdateLayout()
		    local parent_offset = _this.GetAbsPos(true)
			dialog.SetOffset((1024 - dialog.GetSize().X)/2 - parent_offset.X, (768 - dialog.GetSize().Y)/2 - parent_offset.Y)
		    local dialog_ptr = sf.gui.CBaseWindowPtrT(dialog)
		    local modal_res = _this.DoModal(dialog_ptr)
			return true
		end
	end
    if main_menu.cheat_index < #main_menu.cheat_queue+1 then
        if _char == main_menu.cheat_queue[main_menu.cheat_index] then
            main_menu.cheat_index = main_menu.cheat_index + 1
            if main_menu.cheat_index > #main_menu.cheat_queue then
                if sf.core.g_Application.GetDebugLevel() >= 1 then
                    sf.core.g_Application.SetDebugLevel(0)
                else
                    sf.core.g_Application.SetDebugLevel(1)
                end
                main_menu.cheat_index = 1
            end
        else
            main_menu.cheat_index = 1
        end
    end
	
    return false
end

function main_menu.OnKeyDown(_this, _key, _keyboard_state, _state, _broadcast)	
	if _this.SuperOnKeyDown( _key, _keyboard_state, _state, _broadcast) then
        return true
    end
    return false
end

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

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

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

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

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

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

function main_menu.OnChildAction(_this, _action, _child)
	if not _child then return end
	local handler = main_menu.actions[_child.GetId().c_str()]
	if handler then handler = handler[_action.c_str()] end
	if handler then handler(_this, _child) end
end
	
main_menu.actions.quit_button = 
{
	pressed = function(_window) 
        local modal_res = dialog_window.RunQuitDialog(_window)
        if modal_res == 1 then
            game.g_GameOptions.Instance().Save()
            game.g_RecordTable.Instance().Save()
            sf.core.g_Application.Shutdown()
        end
	end
}

main_menu.actions.options_button = 
{
	pressed = function(_window) 
        local num_profiles = game.g_ProfileManager.Instance().EnumProfiles()
        if num_profiles == 0 then
            main_menu.create_profile(_window)
            num_profiles = game.g_ProfileManager.Instance().EnumProfiles()
        end
        if num_profiles ~= 0 then
            options_window_dialog.Show(_window)
        end
	end
}
--[[
main_menu.actions.scores = 
{
	pressed = function(_window) 		
        records_window_dialog.Show(_window)
	end
}]]

main_menu.actions.achievements = 
{
	pressed = function(_window)
        local num_profiles = game.g_ProfileManager.Instance().EnumProfiles()
        
        if num_profiles == 0 then
                main_menu.create_profile(_window)
                num_profiles = game.g_ProfileManager.Instance().EnumProfiles()
        end
        if num_profiles ~= 0 then
            achievements.statistics_window.Show(_window)	
        end
    end
}

main_menu.actions.replay = 
{
	pressed = function(_window) 		
        replay_window.Show(_window)	
	end
}

main_menu.actions.change_player_button = 
{
	pressed = function(_window) 
        user_profiles.run_profiles_dialog(_window)
	end
}

function table_to_string(_table)
    local table_struct = ""
    local first_element = true
    table_struct = "{"

    for i,o in pairs(_table) do
        if not first_element then
            table_struct = table_struct ..", "
        end
        table_struct = table_struct .."\""..o.."\""
        first_element = false
    end
    table_struct = table_struct.."}"
    return table_struct
end

function main_menu.RunLevel(_window, _level_id, _load_level, _track, _go_silence_end, _go_silence_start)
	sf.core.g_Application.GetResourceManager().UnloadAllOnDemandSurfaces()
	local level = g_QuestData.GetLevelById(_level_id)
	__assert(level)
    
    local current_profile = game.g_ProfileManager.Instance().GetCurrentProfile()
    if current_profile ~= nil then
        local load_file_name = ""
        if _load_level == false then
            current_profile.SetStep(_level_id)
            current_profile.SetStepType(game.CProfile.GameStepTypeLevel)
            current_profile.SetLevelState(game.CProfile.LevelStateTypeNew)
            game.g_ProfileManager.Instance().Save()
        else
            local level_state = current_profile.GetLevelState()
            if level_state == game.CProfile.LevelStateTypeInGame then
                local save_file_name = current_profile.GetSaveFileName()
                load_file_name = save_file_name
            elseif level_state == game.CProfile.LevelStateTypeFinished then
                return 0
            end
        end
        local aditional_params = "\n"..[[g_MusicTable = ]]..table_to_string(_track)
        if _go_silence_end then
            aditional_params = aditional_params .."\n"..[[g_GoSilenceInEndLevel = true]]
        end
        if _go_silence_start then
            aditional_params = aditional_params .."\n"..[[g_GoSilenceInStartLevel = true]]
        end


        _window.AddFlags(_window.FlagHidden)
        local result = quest.PlayLevel(g_App.GetSettings(), _window, level, nil, 
        [[	quest.g_Lua.LoadScript("scripts/quest_window.lua")
            quest.g_Lua.LoadScript("scripts/game_menu.lua")
            quest.g_Lua.LoadScript("scripts/dificulty_window.lua")
            quest.g_Lua.LoadScript("scripts/dialog_window.lua")
            quest.g_Lua.LoadScript("scripts/overloads.lua")
 ]]..aditional_params, load_file_name, "" , true)
        _window.RemFlags(_window.FlagHidden)
        return result
    end
end

function main_menu.RunComics(_window, _comics_id, _childs_table, _track, _go_silence, _show_replay)
	sf.core.g_Application.GetResourceManager().UnloadAllOnDemandSurfaces()
    local current_profile = game.g_ProfileManager.Instance().GetCurrentProfile()
    if current_profile ~= nil then
        current_profile.SetStep(_comics_id)
        current_profile.SetStepType(game.CProfile.GameStepTypeComics)
        game.g_ProfileManager.Instance().Save()
    end
    if _childs_table then
        return comics_window.Show(_window, _childs_table, _track, _go_silence, _show_replay)  
    else
        return comics_window.Show(_window, {{id = _comics_id.c_str()}}, _track, _go_silence, _show_replay)  
    end
    
end

function main_menu.GenerateHints()
    local game_window = sf.gui.CWindow()
    game_window.Load(g_App.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "game_window", true),
        g_App.GetSettings().GetChild("GUITemplates", false))

    game_window.UpdateLayout()

    local window_ptr = sf.gui.CBaseWindowPtrT(game_window)
    sf.core.g_Application.SetMainWindow(window_ptr)
    window_ptr = nil
	
    for i,o in pairs(g_QuestStr) do
		if o.Type == "level" then
		    main_menu.RunLevel(game_window, o.Id, false, "", 0)
		end
    end
	
	sf.core.g_Application.Shutdown()
end



function main_menu.RunGame(_start_from_level)
	sf.core.g_Application.GetAudioManager().StopGroup("sound", 0)
	sf.core.g_Application.GetAudioManager().StopGroup("voice", 0)
    local dialog = sf.gui.CWindow()
    dialog.Load(g_App.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "game_window", true),
        g_App.GetSettings().GetChild("GUITemplates", false))

    dialog.UpdateLayout()
    local window_ptr = sf.gui.CBaseWindowPtrT(dialog)
    main_menu.game_window = window_ptr
    sf.core.g_Application.SetMainWindow(window_ptr)
    window_ptr = nil
    local step_id = ""
    local step_type = nil
    local current_profile = game.g_ProfileManager.Instance().GetCurrentProfile()
    if current_profile ~= nil then

        step_id = current_profile.GetStep().c_str()
        step_type = current_profile.GetStepType()
        if step_type == game.CProfile.GameStepTypeLevel then
            step_type = "level"
        elseif step_type == game.CProfile.GameStepTypeComics then
            step_type = "comics"
        end
        if _start_from_level ~= nil or step_id == ""  then
            current_profile.SetHintsCount(1010)
            current_profile.SetThermometerPoints(0)
            current_profile.SetPointsCount(0)
            current_profile.SetHintsUseFlag(0)
            current_profile.SetGameGUID(game.misc.CreateGUIDString())
        end

    end
    local part_res = -1
    local level_index = 1
    local last_track = ""
    for i,o in ipairs(g_QuestStr) do
        local go_silence = false
        if g_QuestStr[i + 1] then
			go_silence_end = g_QuestStr[i + 1].Track[1] ~= o.Track[1]
        else
            go_silence_end = true
        end

        local continue = false
        local load_level = false
        if step_id ~= "" and _start_from_level == nil then
            if o.Id.c_str() ~= step_id then
                continue = true
            else
                if step_type ~= o.Type then
                    continue = true
                end
                load_level = true
                step_id = ""
            end
        end
        if continue ~= true then
			if _start_from_level and _start_from_level>level_index then 
				if o.Type == "level" then level_index = level_index + 1 end
			else
                local track = o.Track[1]
                local go_silence_start = true
                if track == last_track then
                    go_silence_start = nil
                end
				part_res = -1
				if o.Type == "level" then
                    if load_level == false and current_profile then
                        current_profile.SetHintsUseCount(0)
                        current_profile.SetHintsCount(1010)
                        current_profile.SetThermometerPoints(0)
                    end             
					current_profile.SetLevelStepAvailable(tostring(o.Id))
				    part_res = main_menu.RunLevel(dialog, o.Id, load_level, o.Track, go_silence_end, go_silence_start)
                    sf.core.g_Application.GetAudioManager().StopGroup("sound", 0)
                    sf.core.g_Application.GetAudioManager().StopGroup("voice", 0)
                    _start_from_level = nil
                    step_id = ""
				elseif o.Type == "comics" and _start_from_level == nil then
					current_profile.SetComicsStepAvailable(tostring(o.Id))
				    part_res = main_menu.RunComics(dialog, o.Id, o.Childs, track, go_silence_end, go_silence_start)
                    sf.core.g_Application.GetAudioManager().StopGroup("sound", 0)
					sf.core.g_Application.GetAudioManager().StopGroup("voice", 0)
    
                    step_id = ""
				end
                
                if o.Type == "level" and part_res == 2 then
                    local current_profile = game.g_ProfileManager.Instance().GetCurrentProfile()
                    if current_profile ~= nil then
                        game.g_RecordTable.Instance().AddRecord(current_profile, current_profile.GetPointsCount())
                    end
                    game.g_RecordTable.Instance().Save()
                end
				last_track = o.Track[1]
				if part_res == 1 or quest.close_flag == true then
			        break
				end
                
                -- функционал двойной концовки
                if o.Type == "level" and tostring(o.Id) == "Chapter06_01" then
                    local achs = game.g_Achievements.Instance().GetProfileAchievements(current_profile)
                    if achs.IsCompleted("newspapers_seeker") ~= 0 then
                        -- нашли все доказательства - переходим к комиксу второй концовки
                        local comics_id = "comics_end_game_2"
                        local found = false
                        for i,step in ipairs(g_QuestStr) do
                            if step.Type == "comics" and tostring(step.Id) == comics_id then
                                found = true
                                o = step
                                break
                            end
                        end
                        __assert(found)
                        main_menu.RunComics(dialog, o.Id, o.Childs, o.Track[1] or "", true, true)
                    end
                end
                -- ежели просмотрен один из двух конечных комиксов - завершаем игру
                if o.Type == "comics" and tostring(o.Id) == "comics_end_game_1" then
                    -- первая концовка
                    local message = sf.gui.CWindow()
                    message.Load(g_App.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "end_game_message", true),
                        g_App.GetSettings().GetChild("GUITemplates", false))
                    message.UpdateLayout()
                    message.SetOffset((1024 - message.GetSize().X)/2, (768 - message.GetSize().Y)/2)

                    dialog.DoModal(message)
                    part_res = 2
                    break
                end
                if o.Type == "comics" and tostring(o.Id) == "comics_end_game_2" then
                    -- вторая концовка
                    part_res = 2
                    break
                end
			end
            
        end
    end
	local show_credits = nil
    if part_res ~= 1 then --and quest.close_flag ~= true 
    
        if game.g_DemoRestrictions.Instance().IsEnabled() then
            -- прошли демоверсию
            game.g_ProfileManager.Instance().Save()
            game.g_DemoRestrictions.Instance().OpenMessageWindow()
            if true then return end
        else
            local current_profile = game.g_ProfileManager.Instance().GetCurrentProfile()
            if current_profile ~= nil then
                current_profile.SetStep(_T(""))
                game.g_ProfileManager.Instance().Save()
                show_credits = true
            end
        end
    end
    main_menu.game_window = nil
    main_menu.Show(nil, show_credits)
end
--[[
function main_menu.Load(_this, _info, _templates)
end
]]

function main_menu.DoUpdate(_this)
    if main_menu.start_effect_state and main_menu.start_effect_time then
        local current_time = main_menu.timer.Get().GetTime()
        local koef = (current_time - main_menu.start_effect_time)/main_menu.total_effect_time
        if koef >= 1 then
            koef = 1
        end
        if main_menu.start_effect_state == 1 then
            if koef == 1 then
                main_menu.start_effect_state = 2
                main_menu.start_effect_time = current_time
                main_menu.total_effect_time = main_menu.alpha_show_delay
                for i,o in pairs(main_menu.alpha_widgets_id_table) do
                    set_widget_flag_value(o.widget, sf.gui.CBaseWidget.FlagDisabled, false)      
                end
            end
        elseif main_menu.start_effect_state == 2 then
            for i,o in pairs(main_menu.alpha_widgets_id_table) do
		if o.widget then
				local clr = sf.graphics.Color(255, 255, 255, 255)
				if tostring(o.widget.GetId()) == "welcome_label" then
					clr.Red = 208
					clr.Green = 176
					clr.Blue = 137
				end
                clr.Alpha = koef * o.alpha
				clr.Clamp()
                o.widget.SetColor(clr)
		end	
            end

            if koef == 1 then

                for i,o in pairs(main_menu.hide_widgets_id_table) do
                    local widget = _this.GetWidget(i).get()
                    if widget then
                        o.widget = play_button_widget
                        set_widget_flag_value(widget, sf.gui.CBaseWidget.FlagDisabled, true)
                        set_widget_flag_value(widget, sf.gui.CBaseWidget.FlagHidden, true)
                    end
                end


                main_menu.start_effect_state = nil
                main_menu.start_effect_time = nil
                main_menu.total_effect_time = nil
                main_menu.init_welcome(_this)
            end
        end

    end


end

main_menu.alpha_widgets_id_table = { }
main_menu.hide_widgets_id_table = { }
main_menu.last_frame_id_table = { }

main_menu.alpha_widgets_table = {}

function main_menu.Show(_show_alpha_widgets, _show_credits)



    local main_menu_info =  g_App.GetSettings().GetChild(_T("Constants"), false).GetChild(_T("main_menu"), false)
    if main_menu_info then


        local res = tonumber(main_menu_info.GetValue("alpha_hide_delay").c_str())
        if res ~= nil then main_menu.alpha_hide_delay = res end

        res = tonumber(main_menu_info.GetValue("alpha_show_delay").c_str())
        if res ~= nil then main_menu.alpha_show_delay = res end


        main_menu.alpha_widgets_id_table = {}
        local alpha_item = main_menu_info.GetChild(_T("alpha_group"), false).GetFirstChildRef()
        while alpha_item do
            local id_value = alpha_item.GetValue("id").c_str()
            if id_value ~= "" then
                main_menu.alpha_widgets_id_table[  id_value] = {}
            end
            
            alpha_item = alpha_item.GetNextSiblingRef()
        end
        main_menu.hide_widgets_id_table = {}
        local hide_item = main_menu_info.GetChild(_T("hide_group"), false).GetFirstChildRef()
        while hide_item do
            local id_value = hide_item.GetValue("id").c_str()
            if id_value ~= "" then
                main_menu.hide_widgets_id_table[  id_value] = {}
            end
            
            hide_item = hide_item.GetNextSiblingRef()
        end
        main_menu.last_frame_id_table = {}
        local last_frame_item = main_menu_info.GetChild(_T("last_frame_group"), false).GetFirstChildRef()
        while last_frame_item do
            local id_value = last_frame_item.GetValue("id").c_str()
            if id_value ~= "" then
                main_menu.last_frame_id_table[  id_value] = {}
            end
            
            last_frame_item = last_frame_item.GetNextSiblingRef()
        end
    end

	local window = sf.gui.CWindow()
	window.Load(
		g_App.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "main_menu", true), 
		g_App.GetSettings().GetChild("GUITemplates", false))
	window.SetSize(1024, 768)
	window.UpdateLayout()
    game.g_GameOptions.Instance().ApplyMusicChanges()
    sf.core.g_Application.GetAudioManager().StopGroup("sound", 0)
    sf.core.g_Application.GetAudioManager().StopGroup("voice", 0)
    sf.core.g_Application.GetAudioManager().StopGroup("music", 0)
    sf.core.g_Application.GetAudioManager().StopGroup("gui_sounds", 0)

	if main_menu.menu_track_id ~= "" then
        sf.core.g_Application.GetAudioManager().Play(main_menu.menu_track_id, -2, -2, -2, -2, -2)
    end

    if _show_alpha_widgets then

        main_menu.start_effect_state = 1
        main_menu.start_effect_time = main_menu.timer.Get().GetTime()
        main_menu.total_effect_time = main_menu.alpha_hide_delay


        for i,o in pairs(main_menu.alpha_widgets_id_table) do
            local play_button_widget = window.GetWidget(i).get()
            if play_button_widget then
                o.widget = play_button_widget
				local color = sf.graphics.Color(play_button_widget.GetColor())
                o.alpha = color.Alpha
				color.Alpha = 0
                play_button_widget.SetColor(color)
                set_widget_flag_value(play_button_widget, sf.gui.CBaseWidget.FlagDisabled, true)
            end
        end

    else
        for i,o in pairs(main_menu.hide_widgets_id_table) do
            local widget = window.GetWidget(i).get()
            if widget then
                o.widget = play_button_widget
                set_widget_flag_value(widget, sf.gui.CBaseWidget.FlagDisabled, true)
                set_widget_flag_value(widget, sf.gui.CBaseWidget.FlagHidden, true)
            end
        end

        for i,o in pairs(main_menu.last_frame_id_table) do
            local widget = window.GetWidget(i).get()
            if widget then                                 
                local clip_widget = __cast(widget, "sf.gui.CClipWidget")
                if clip_widget then
                    local a = qe.GetClipTime(clip_widget.GetClip())
                    clip_widget.GetClip().MoveTime(a)
                    --local b = 0
                end
            end
        end
    end


    main_menu.init_welcome(window)

	g_App.SetMainWindow(window)
	if _show_credits then
	-- это показывается, если мы прошли игру
		credits_window.Show(window)
	end

	window = 0

	collectgarbage()
end

function main_menu.create_profile(_owner)
        local modal_res = user_profiles.run_modify_name_dialog(_owner, "new")
        if modal_res == 1 then
                main_menu.init_welcome(_owner)
                game.g_ProfileManager.Instance().Save()
        elseif modal_res == 0 then
        end
end

main_menu.actions.play_button = 
{
	pressed = function(_window) 
        local num_profiles = game.g_ProfileManager.Instance().EnumProfiles()
        
        if num_profiles == 0 then
                main_menu.create_profile(_window)
                num_profiles = game.g_ProfileManager.Instance().EnumProfiles()
        end
        if num_profiles ~= 0 then
            main_menu.RunGame()
        end
	end
}

beta_dialog = 
{
    __CreateInstance = function() return "beta_dialog" end,
    
    _actions = 
    {
        yes_button = 
        {
            pressed = function(_this)
                _this.AddFlags(_this.FlagDead)
                sf.core.g_Application.Shutdown()
            end
        }
    }
}
__inherite(beta_dialog, default_lua_widget_handler(beta_dialog._actions))
