content: package ui.location;
  
  import android.annotation.SuppressLint;
  import android.app.ProgressDialog;
  import android.content.Intent;
  import android.graphics.Color;
  import android.location.Address;
  import android.location.Geocoder;
  import android.location.Location;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.animation.AccelerateInterpolator;
  import android.widget.Button;
  import android.widget.EditText;
  import android.widget.Toast;
  
  import androidx.annotation.NonNull;
  import androidx.appcompat.app.AppCompatActivity;
  
  import ui.cart.CartItemActivity;
  import com.example.munche.MainActivity;
  import com.example.munche.R;
  import com.google.android.gms.maps.GoogleMap;
  import com.google.android.gms.maps.MapView;
  import com.google.android.gms.maps.OnMapReadyCallback;
  import com.google.firebase.auth.FirebaseAuth;
  import com.google.firebase.firestore.FirebaseFirestore;
  import com.mapbox.android.core.location.LocationEngine;
  import com.mapbox.android.core.location.LocationEngineCallback;
  import com.mapbox.android.core.location.LocationEngineProvider;
  import com.mapbox.android.core.location.LocationEngineRequest;
  import com.mapbox.android.core.location.LocationEngineResult;
  import com.mapbox.android.core.permissions.PermissionsListener;
  import com.mapbox.android.core.permissions.PermissionsManager;
  import com.mapbox.mapboxsdk.Mapbox;
  import com.mapbox.mapboxsdk.location.LocationComponent;
  import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions;
  import com.mapbox.mapboxsdk.location.LocationComponentOptions;
  import com.mapbox.mapboxsdk.location.modes.CameraMode;
  import com.mapbox.mapboxsdk.location.modes.RenderMode;
  import com.mapbox.mapboxsdk.maps.MapboxMap;
  import com.mapbox.mapboxsdk.maps.Style;
  
  import java.io.IOException;
  import java.lang.ref.WeakReference;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Locale;
  import java.util.Map;
  import java.util.Objects;
  
  public class ChangeLocationActivity extends AppCompatActivity implements
          OnMapReadyCallback, PermissionsListener {
      private MapboxMap mapboxMap;
      private MapView mapView;
      private PermissionsManager permissionsManager;
      private LocationEngine locationEngine;
      private long DEFAULT_INTERVAL_IN_MILLISECONDS = 8000L;
      private long DEFAULT_MAX_WAIT_TIME = DEFAULT_INTERVAL_IN_MILLISECONDS * 5;
      private final ChangeLocationCallback callback = new ChangeLocationCallback(this);
      private FirebaseFirestore db;
      private String uid;
      private String city;
      private String postalCode;
      private String knownName;
      private String subLocality;
      private String mIntentKey;
      private EditText mLocationText;
      private List<Address> addresses;
      private Geocoder geocoder;
      private Button mSaveLocationBtn;
      private ProgressDialog mProgressDialog;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          Mapbox.getInstance(this, getString(R.string.mapbox_access_token));
          setContentView(R.layout.activity_change_location);
          mapView = findViewById(R.id.mapView);
          mapView.onCreate(savedInstanceState);
          mapView.getMapAsync(this);
  
          init();
  
      }
  
      private void init() {
          mIntentKey = getIntent().getStringExtra("INT");
          db = FirebaseFirestore.getInstance();
          uid = Objects.requireNonNull(FirebaseAuth.getInstance().getCurrentUser()).getUid();
          mProgressDialog = new ProgressDialog(this);
          mLocationText = findViewById(R.id.locationActualText);
          geocoder = new Geocoder(this, Locale.getDefault());
          mSaveLocationBtn = findViewById(R.id.saveLocationBtn);
      }
  
      public void onMapReady(@NonNull final MapboxMap mapboxMap) {
          this.mapboxMap = mapboxMap;
  
          mapboxMap.setStyle(Style.MAPBOX_STREETS,
                  this::enableLocationComponent);
      }
  
      @SuppressWarnings( {"MissingPermission"})
      private void enableLocationComponent(@NonNull Style loadedMapStyle) {
          if (PermissionsManager.areLocationPermissionsGranted(this)) {
              LocationComponent locationComponent = mapboxMap.getLocationComponent();
              LocationComponentOptions locationComponentOptions =
                      LocationComponentOptions.builder(this)
                              .pulseEnabled(true)
                              .pulseColor(Color.DKGRAY)
                              .pulseAlpha(.4f)
                              .pulseInterpolator(new AccelerateInterpolator())
                              .build();
              LocationComponentActivationOptions locationComponentActivationOptions =
                      LocationComponentActivationOptions.builder(this, loadedMapStyle)
                              .useDefaultLocationEngine(false)
                              .locationComponentOptions(locationComponentOptions)
                              .build();
              locationComponent.activateLocationComponent(locationComponentActivationOptions);
              locationComponent.setLocationComponentEnabled(true);
              locationComponent.setCameraMode(CameraMode.TRACKING);
              locationComponent.setRenderMode(RenderMode.COMPASS);
              initLocationEngine();
          } else {
              permissionsManager = new PermissionsManager(this);
              permissionsManager.requestLocationPermissions(this);
          }
      }
  
      /**
       * Set up the LocationEngine and the parameters for querying the device's location
       */
      @SuppressLint("MissingPermission")
      private void initLocationEngine() {
          locationEngine = LocationEngineProvider.getBestLocationEngine(this);
  
          LocationEngineRequest request = new LocationEngineRequest.Builder(DEFAULT_INTERVAL_IN_MILLISECONDS)
                  .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
                  .setMaxWaitTime(DEFAULT_MAX_WAIT_TIME).build();
  
          locationEngine.requestLocationUpdates(request, callback, getMainLooper());
          locationEngine.getLastLocation(callback);
      }
  
      @Override
      public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
          super.onRequestPermissionsResult(requestCode, permissions, grantResults);
          permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
      }
  
      @Override
      public void onExplanationNeeded(List<String> permissionsToExplain) {
          Toast.makeText(this, "Chup Chap Dede", Toast.LENGTH_LONG).show();
      }
  
      @Override
      public void onPermissionResult(boolean granted) {
          if (granted) {
              if (mapboxMap.getStyle() != null) {
                  enableLocationComponent(mapboxMap.getStyle());
              }
          } else {
              Toast.makeText(this, "Ye Baat", Toast.LENGTH_LONG).show();
              finish();
          }
      }
  
      @Override
      public void onMapReady(@NonNull GoogleMap googleMap) {
  
      }
  
      private class ChangeLocationCallback
              implements LocationEngineCallback<LocationEngineResult> {
  
          private final WeakReference<ChangeLocationActivity> activityWeakReference;
  
          ChangeLocationCallback(ChangeLocationActivity activity) {
              this.activityWeakReference = new WeakReference<>(activity);
          }
  
          /**
           * The LocationEngineCallback interface's method which fires when the device's location has changed.
           *
           * @param result the LocationEngineResult object which has the last known location within it.
           */
          @Override
          public void onSuccess(LocationEngineResult result) {
              ChangeLocationActivity activity = activityWeakReference.get();
  
              if (activity != null) {
                  Location location = result.getLastLocation();
  
                  if (location == null) {
                      return;
                  }
  
                  setLocation(result.getLastLocation().getLatitude(), result.getLastLocation().getLongitude());
  
                  // Pass the new location to the Maps SDK's LocationComponent
                  if (activity.mapboxMap != null && result.getLastLocation() != null) {
                      activity.mapboxMap.getLocationComponent().forceLocationUpdate(result.getLastLocation());
                  }
              }
          }
  
          /**
           * The LocationEngineCallback interface's method which fires when the device's location can not be captured
           *
           * @param exception the exception message
           */
          @Override
          public void onFailure(@NonNull Exception exception) {
              Log.d("LocationChangeActivity", exception.getLocalizedMessage());
              ChangeLocationActivity activity = activityWeakReference.get();
              if (activity != null) {
                  Toast.makeText(activity, exception.getLocalizedMessage(),
                          Toast.LENGTH_SHORT).show();
              }
          }
      }
  
      private  void setLocation(double latitude, double longitude){
          try {
              addresses = geocoder.getFromLocation(latitude,longitude,1);
          } catch (IOException e) {
              e.printStackTrace();
          }
  
          if (addresses != null && addresses.size() > 0){
              city = addresses.get(0).getLocality();
              postalCode = addresses.get(0).getPostalCode();
              knownName = addresses.get(0).getFeatureName();
              subLocality = addresses.get(0).getSubLocality();
              String finalAddress = knownName + ", " + subLocality + ", " + city + ", " + postalCode;
              mLocationText.setText(finalAddress);
          }
  
          mSaveLocationBtn.setOnClickListener(view -> {
              mProgressDialog.setMessage("Updating Address, Please wait...");
              mProgressDialog.show();
              Map<String, Object> updateLocMap = new HashMap<>();
              updateLocMap.put("latitude", latitude);
              updateLocMap.put("longitude",longitude);
              updateLocMap.put("address", mLocationText.getText().toString());
              updateLocMap.put("knownname", knownName);
              updateLocMap.put("sublocality", subLocality);
              updateLocMap.put("city", city);
              updateLocMap.put("postalcode", postalCode);
  
              db.collection("UserList").document(uid).update(updateLocMap).addOnSuccessListener(aVoid -> {
                  mProgressDialog.dismiss();
                  switch (mIntentKey) {
                      case "ONE": {
                          Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                          startActivity(intent);
                          finish();
                          break;
                      }
                      case "TWO": {
                          Intent intent = new Intent(getApplicationContext(), CartItemActivity.class);
                          startActivity(intent);
                          finish();
                          break;
                      }
                      case "THREE":
                          onBackPressed();
                          finish();
                          break;
                  }
  
              });
  
          });
  
      }
  
      @Override
      protected void onStart() {
          super.onStart();
          mapView.onStart();
      }
  
      @Override
      protected void onResume() {
          super.onResume();
          mapView.onResume();
      }
  
      @Override
      protected void onPause() {
          super.onPause();
          mapView.onPause();
      }
  
      @Override
      protected void onStop() {
          super.onStop();
          mapView.onStop();
      }
  
      @Override
      protected void onSaveInstanceState(@NonNull Bundle outState) {
          super.onSaveInstanceState(outState);
          mapView.onSaveInstanceState(outState);
      }
  
      @Override
      protected void onDestroy() {
          super.onDestroy();
          // Prevent leaks
          if (locationEngine != null) {
              locationEngine.removeLocationUpdates(callback);
          }
          mapView.onDestroy();
      }
  
      @Override
      public void onLowMemory() {
          super.onLowMemory();
          mapView.onLowMemory();
      }
  }
  