void OptionsScreenInput::eventCallback(Widget* widget, const std::string& name, const int playerID)
{
    //const std::string& screen_name = this->getName();

    if (name == "options_choice")
    {
        std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str();

        if (selection == "tab_audio") StateManager::get()->replaceTopMostScreen(OptionsScreenAudio::getInstance());
        else if (selection == "tab_video") StateManager::get()->replaceTopMostScreen(OptionsScreenVideo::getInstance());
        else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(TabbedUserScreen::getInstance());
        else if (selection == "tab_controls") StateManager::get()->replaceTopMostScreen(OptionsScreenInput::getInstance());
        else if (selection == "tab_ui") StateManager::get()->replaceTopMostScreen(OptionsScreenUI::getInstance());
    }
    else if (name == "add_device")
    {
        new AddDeviceDialog();
    }
    else if (name == "back")
    {
        StateManager::get()->escapePressed();
    }
    else if (name == "devices")
    {
        ListWidget* devices = this->getWidget<ListWidget>("devices");
        assert(devices != NULL);

        const std::string& selection = devices->getSelectionInternalName();
        if (selection.find("gamepad") != std::string::npos)
        {
            int i = -1, read = 0;
            read = sscanf( selection.c_str(), "gamepad%i", &i );
            if (read == 1 && i != -1)
            {
                OptionsScreenInput2::getInstance()->setDevice( input_manager->getDeviceList()->getGamepadConfig(i) );
                StateManager::get()->replaceTopMostScreen(OptionsScreenInput2::getInstance());
                //updateInputButtons( input_manager->getDeviceList()->getGamepadConfig(i) );
            }
            else
            {
                std::cerr << "Cannot read internal gamepad input device ID : " << selection.c_str() << std::endl;
            }
        }
        else if (selection.find("keyboard") != std::string::npos)
        {
            int i = -1, read = 0;
            read = sscanf( selection.c_str(), "keyboard%i", &i );
            if (read == 1 && i != -1)
            {
                // updateInputButtons( input_manager->getDeviceList()->getKeyboardConfig(i) );
                OptionsScreenInput2::getInstance()->setDevice( input_manager->getDeviceList()->getKeyboardConfig(i) );
                StateManager::get()->replaceTopMostScreen(OptionsScreenInput2::getInstance());
            }
            else
            {
                std::cerr << "Cannot read internal keyboard input device ID : " << selection.c_str() << std::endl;
            }
        }
        else
        {
            std::cerr << "Cannot read internal input device ID : " << selection.c_str() << std::endl;
        }
    }

}   // eventCallback
void TracksScreen::eventCallback(Widget* widget, const std::string& name,
                                 const int playerID)
{
    if ((name == "lap-spinner" || name == "reverse") &&
         STKHost::existHost() && m_selected_track != NULL)
    {
        voteForPlayer();
    }

    else if (name == "vote-list")
    {
        auto cl = LobbyProtocol::get<ClientLobby>();
        ListWidget* list = dynamic_cast<ListWidget*>(widget);
        DynamicRibbonWidget* tracks_widget =
            getWidget<DynamicRibbonWidget>("tracks");

        if (!list || !cl || !tracks_widget || !m_laps || !m_reversed)
            return;
        // Vote to agree with selection of host id
        uint32_t host_id = -1;
        if (StringUtils::fromString(list->getSelectionInternalName(),
            host_id) && host_id != STKHost::get()->getMyHostId())
        {
            const PeerVote* host_vote = cl->getVote(host_id);
            if (host_vote)
            {
                m_selected_track = track_manager->getTrack(
                    host_vote->m_track_name);
                if (!m_selected_track)
                    return;
                tracks_widget->setBadge(host_vote->m_track_name, OK_BADGE);
                m_laps->setValue(host_vote->m_num_laps);
                m_reversed->setState(host_vote->m_reverse);
                voteForPlayer();
            }
        }
    }
    else if (name == "tracks")
    {
        DynamicRibbonWidget* w2 = dynamic_cast<DynamicRibbonWidget*>(widget);
        if(!w2) return;

        std::string selection = w2->getSelectionIDString(PLAYER_ID_GAME_MASTER);
        if (UserConfigParams::logGUI())
        {
            Log::info("TracksScreen", "Clicked on track '%s'.",
                       selection.c_str());
        }

        UserConfigParams::m_last_track = selection;
        if (selection == "locked" && race_manager->getNumLocalPlayers() == 1)
        {
            unlock_manager->playLockSound();
            return;
        }
        else if (selection == RibbonWidget::NO_ITEM_ID)
        {
            return;
        }

        if (selection == "random_track")
        {
            if (m_random_track_list.empty()) return;

            selection = m_random_track_list.front();
            m_random_track_list.pop_front();
            m_random_track_list.push_back(selection);
        }   // selection=="random_track"

        m_selected_track = track_manager->getTrack(selection);

        if (m_selected_track)
        {
            if (STKHost::existHost())
            {
                w2->setBadge(selection, OK_BADGE);
                voteForPlayer();
            }
            else
            {
                TrackInfoScreen::getInstance()->setTrack(m_selected_track);
                TrackInfoScreen::getInstance()->push();
            }
        }   // if clicked_track

    }   // name=="tracks"
    else if (name == "trackgroups")
    {
        RibbonWidget* tabs = this->getWidget<RibbonWidget>("trackgroups");
        UserConfigParams::m_last_used_track_group = tabs->getSelectionIDString(0);
        buildTrackList();
        
        if (m_network_tracks)
        {
            auto cl = LobbyProtocol::get<ClientLobby>();
    
            const PeerVote* vote = cl->getVote(STKHost::get()->getMyHostId());
            if (vote)
            {
                DynamicRibbonWidget* w2 = getWidget<DynamicRibbonWidget>("tracks");
                w2->setBadge(vote->m_track_name, OK_BADGE);
            }
        }
    }
    else if (name == "back")
    {
        StateManager::get()->escapePressed();
    }
}   // eventCallback
void TutorialScreen::eventCallback(GUIEngine::Widget* widget, const std::string& name, const int playerID)
{
    if (name == "back")
    {
        StateManager::get()->escapePressed();
    }
    else if (name == "tutorials")
    {
        ListWidget* tutorials = this->getWidget<ListWidget>("tutorials");
        const std::string& selection = tutorials->getSelectionInternalName();
        if (selection == BASIC_DRIVING)
        {
            // Verify the kart in the config exists
            if (kart_properties_manager->getKart(UserConfigParams::m_default_kart) == NULL)
                UserConfigParams::m_default_kart.revertToDefaults();
            
            // Use latest used device
            InputDevice* device = input_manager->getDeviceList()->getLatestUsedDevice();

            // Create player and associate player with device (FIXME: ask for player ident)
            StateManager::get()->createActivePlayer( UserConfigParams::m_all_players.get(0), device );

            // Set up race manager appropriately
            race_manager->setNumLocalPlayers(1);
            race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart);

            // ASSIGN should make sure that only input from assigned devices is read.
            input_manager->getDeviceList()->setAssignMode(ASSIGN);

            // Go straight to the race
            StateManager::get()->enterGameState();

            // Initialise global data - necessary even in local games to avoid
            // many if tests in other places (e.g. if network_game call
            // network_manager else call race_manager).
            network_manager->initCharacterDataStructures();
            
            // Launch tutorial
            m_tutorial_manager->getTutorial(selection)->setRace();
            
            // FIXME this code have to be in Tutorial class (and loaded from file xD)
            RaceManager::MajorRaceModeType m_major;
            RaceManager::MinorRaceModeType m_minor;
            RaceManager::Difficulty        m_difficulty;

            m_minor = RaceManager::MINOR_MODE_NORMAL_RACE;
            m_major = RaceManager::MAJOR_MODE_SINGLE;
            m_difficulty = RaceManager::RD_EASY;

            race_manager->setMinorMode(m_minor);
            race_manager->setMajorMode(m_major);
            race_manager->setTrack((std::string)"canyon");
            
            race_manager->setDifficulty(m_difficulty);
            race_manager->setNumLaps(1);
            race_manager->setNumKarts(1);
            race_manager->setNumLocalPlayers(1);              
            //race_manager->setCoinTarget(m_energy);*/

            // Sets up kart info, including random list of kart for AI
            network_manager->setupPlayerKartInfo();
            race_manager->startNew();
        }
        else if (name == SHARP_TURN)
        {
        }
        else if (name == NITRO)
        {
        }
        else if (name == COLLECTIBLE_WEAPONS)
        {
        }
        else if (name == SHOOTING_BACKWARDS)
        {
        }
    }
}