Alvaro2112/Money_run

View on GitHub
app/src/main/java/sdp/moneyrun/ui/menu/MenuActivity.java

Summary

Maintainability
A
3 hrs
Test Coverage
B
84%
package sdp.moneyrun.ui.menu;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.material.navigation.NavigationView;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.squareup.picasso.Picasso;

import java.io.IOException;

import sdp.moneyrun.R;
import sdp.moneyrun.database.DatabaseProxy;
import sdp.moneyrun.database.riddle.RiddlesDatabase;
import sdp.moneyrun.location.AndroidLocationService;
import sdp.moneyrun.location.LocationRepresentation;
import sdp.moneyrun.menu.JoinGameImplementation;
import sdp.moneyrun.menu.NewGameImplementation;
import sdp.moneyrun.ui.authentication.LoginActivity;
import sdp.moneyrun.ui.map.OfflineMapDownloaderActivity;
import sdp.moneyrun.ui.menu.friendlist.FriendListActivity;
import sdp.moneyrun.ui.menu.leaderboards.MainLeaderboardActivity;
import sdp.moneyrun.user.User;
import sdp.moneyrun.weather.OpenWeatherMap;
import sdp.moneyrun.weather.WeatherForecast;
import sdp.moneyrun.weather.WeatherReport;


@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal"})
public class MenuActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
    //In meters
    public static final float DISTANCE_CHANGE_BEFORE_UPDATE = (float) 100.0;
    private static final long MINIMUM_TIME_BEFORE_UPDATE = 10000;
    private final ActivityResultLauncher<String[]> requestPermissionsLauncher =
            registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(),
                    map -> {
                    });
    private final String TAG = MenuActivity.class.getSimpleName();
    @Nullable
    public NewGameImplementation newGameImplementation;
    protected DrawerLayout mDrawerLayout;
    DatabaseReference databaseReference;
    FusedLocationProviderClient fusedLocationClient;
    @Nullable
    AndroidLocationService locationService;
    private User user;
    private OpenWeatherMap openWeatherMap;
    private WeatherForecast currentForecast;
    private LocationRepresentation currentLocation;
    @NonNull
    LocationListener locationListenerGPS = new LocationListener() {
        @Override
        public void onLocationChanged(@NonNull Location location) {
            loadWeather(location);
            if (currentForecast != null)
                setWeatherFieldsToday(currentForecast.getWeatherReport());

        }

        @Override
        public void onProviderDisabled(@NonNull String provider) {

        }

        @Override
        public void onProviderEnabled(@NonNull String provider) {

        }

    };
    private Dialog helpDialog;
    private ImageView informationImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        locationService = AndroidLocationService.buildFromContextAndProvider(getApplicationContext(), "");

        setContentView(R.layout.activity_menu);
        setNavigationViewListener();
        mDrawerLayout = findViewById(R.id.drawer_layout);

        // setup database instance
        FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
        databaseReference = firebaseDatabase.getReference();

        // Get player location
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        helpDialog = new Dialog(this);

        runFunctionalities();

        addInfoImageButton();


        DatabaseProxy.addOfflineListener(MenuActivity.this, TAG);
    }


    private void addInfoImageButton() {
        informationImage = findViewById(R.id.info_image);
        informationImage.setOnClickListener(v -> showPopup());
    }

    public void runFunctionalities() {
        //Setting the current player object
        user = (User) getIntent().getSerializableExtra("user");
        if (user == null) {
            throw new IllegalStateException("the Intent that launched MenuActivity has null \"user\" value");
        }
        boolean guestPlayer = getIntent().getBooleanExtra("guestPlayer", false);
        setGuestPlayerFields(guestPlayer);

        JoinGameImplementation joinGameImplementation = new JoinGameImplementation(this,
                databaseReference,
                user,
                requestPermissionsLauncher,
                locationService,
                true,
                R.layout.join_game_popup);

        newGameImplementation = new NewGameImplementation(this,
                databaseReference,
                user,
                requestPermissionsLauncher,
                locationService);

        runWeather();

        Button joinGame = findViewById(R.id.join_game);
        joinGame.setOnClickListener(joinGameImplementation::onClickShowJoinGamePopupWindow);

        Button newGame = findViewById(R.id.new_game);
        newGame.setOnClickListener(newGameImplementation::onClickShowNewGamePopupWindow);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        RiddlesDatabase.reset();
        DatabaseProxy.removeOfflineListener();
    }

    /**
     * This functions takes care of the logic regarding the buttons that are in the navigation side bar
     */
    @SuppressLint("NonConstantResourceId")
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        MediaPlayer.create(this, R.raw.button_press).start();
        switch (item.getItemId()) {

            case R.id.profile_button: {
                onButtonSwitchToActivity(UserProfileActivity.class, false);
                break;
            }

            case R.id.friend_list_button: {
                onButtonSwitchToActivity(FriendListActivity.class, false);
                break;
            }

            case R.id.main_leaderboard_button: {
                onButtonSwitchToActivity(MainLeaderboardActivity.class, false);
                break;
            }

            case R.id.log_out_button: {
                FirebaseAuth.getInstance().signOut();
                onButtonSwitchToActivity(LoginActivity.class, true);
                break;
            }

            case R.id.download_map: {
                onButtonSwitchToActivity(OfflineMapDownloaderActivity.class, false);
                break;

            }


        }
        //close navigation drawer
        mDrawerLayout.closeDrawer(GravityCompat.START);
        return true;
    }

    private void setNavigationViewListener() {
        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
    }

    private void setPutExtraArguments(@NonNull Intent intent) {
        intent.putExtra("user", user);
    }

    public void onButtonSwitchToActivity(Class activityClass, boolean shouldFinish) {
        Intent switchActivity = new Intent(MenuActivity.this, activityClass);
        setPutExtraArguments(switchActivity);
        startActivity(switchActivity);
        if (shouldFinish) {
            finish();
        }
    }

    public void showPopup() {
        Button txtclose;
        helpDialog.setContentView(R.layout.help_pop_up);
        txtclose = helpDialog.findViewById(R.id.txtclose);
        txtclose.setOnClickListener(v1 -> helpDialog.dismiss());
        helpDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        helpDialog.show();

    }

    public void setGuestPlayerFields(boolean guest) {
        if (guest) {
            Button joinGame = findViewById(R.id.join_game);
            joinGame.setEnabled(false);
        }
    }

    private void runWeather() {
        Criteria criteria = new Criteria();
        criteria.setPowerRequirement(Criteria.POWER_MEDIUM);
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        currentLocation = new LocationRepresentation(0, 0);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        try {
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MINIMUM_TIME_BEFORE_UPDATE, DISTANCE_CHANGE_BEFORE_UPDATE, locationListenerGPS);
        } catch (Exception e) {
            System.out.println("Your device does not have network capabilities");
        }
        openWeatherMap = OpenWeatherMap.build();
    }


    public void loadWeather(@NonNull android.location.Location location) {
        try {
            LocationRepresentation loc;
            loc = new LocationRepresentation(location.getLatitude(), location.getLongitude());
            this.currentLocation = loc;
            this.currentForecast = openWeatherMap.getForecast(loc);

        } catch (IOException e) {
            Log.e("WeatherActivity", "Error when retrieving forecast.", e);
        }
    }

    public WeatherForecast getCurrentForecast() {
        return currentForecast;
    }

    public LocationRepresentation getCurrentLocation() {
        return currentLocation;
    }

    public void setWeatherFieldsToday(@NonNull WeatherReport report) {
        TextView weatherTypeText = findViewById(R.id.weather_type);
        TextView weatherTempText = findViewById(R.id.weather_temp_average);
        ImageView weatherIconView = findViewById(R.id.weather_icon);

        String url = "https://openweathermap.org/img/wn/" + report.getWeatherIcon() + "@4x.png";
        Picasso obj = Picasso.get();
        obj.setLoggingEnabled(true);
        obj.load(url).fit().into(weatherIconView);
        weatherIconView.setContentDescription(report.getWeatherType());
        weatherTempText.setText(String.format("%s C", report.getAverageTemperature()));
        weatherTypeText.setText(report.getWeatherType());
    }

    @Override
    public void onBackPressed() {
        // disable the back button from menu since the user should not be able to log in again once logged in properly
    }

    /**
     * @return the location service
     */
    @Nullable
    public AndroidLocationService getLocationService() {
        return locationService;
    }

    public void setLocationService(@NonNull AndroidLocationService locationService) {
        this.locationService = locationService;
    }

}