basbeu/theSofties

View on GitHub
app/src/main/java/ch/epfl/sweng/favors/favors/FavorsMap.java

Summary

Maintainability
A
0 mins
Test Coverage
package ch.epfl.sweng.favors.favors;

import android.arch.lifecycle.ViewModelProviders;
import android.content.res.Resources;
import android.databinding.DataBindingUtil;
import android.databinding.Observable;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.firebase.firestore.GeoPoint;

import java.util.HashMap;

import ch.epfl.sweng.favors.R;
import ch.epfl.sweng.favors.authentication.Authentication;
import ch.epfl.sweng.favors.database.Favor;
import ch.epfl.sweng.favors.database.FavorRequest;
import ch.epfl.sweng.favors.database.ObservableArrayList;
import ch.epfl.sweng.favors.databinding.FavorsMapBinding;
import ch.epfl.sweng.favors.location.LocationHandler;
import ch.epfl.sweng.favors.utils.ExecutionMode;
import static ch.epfl.sweng.favors.utils.Utils.getIconNameFromCategory;

/**
 * Fragment that displays the list of favor and allows User to sort it and to search in it
 */
public class FavorsMap extends android.support.v4.app.Fragment implements OnMapReadyCallback {
    private static final String TAG = "FAVORS_MAP";

    FavorsMapBinding binding;
    ObservableArrayList<Favor> favorList = new ObservableArrayList<>();

    private HashMap<String,Favor> favorsMap = new HashMap<>();

    /**
     * Action that is executed when click is perfomed on a marker
     */
    private GoogleMap.OnMarkerClickListener markerClickListener = marker -> {
        Favor favor = favorsMap.get(marker.getId());
        ViewModelProviders.of(FavorsMap.this.getActivity()).get(SharedViewFavor.class).select(favor);
        if(favor.get(Favor.StringFields.ownerID).equals(Authentication.getInstance().getUid()))
            getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new FavorDetailView()).addToBackStack(null).commit();
        else
            getActivity().getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, new FavorDetailView()).addToBackStack(null).commit();

        return true;
    };

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        binding = DataBindingUtil.inflate(inflater, R.layout.favors_map,container,false);
        binding.setElements(this);

        binding.mapView.onCreate(savedInstanceState);
        binding.mapView.onResume();
        try {
            MapsInitializer.initialize(getActivity().getApplicationContext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        binding.mapView.getMapAsync(this);

        return binding.getRoot();
    }

    private GoogleMap mMap;

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

    }


    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        if(!ExecutionMode.getInstance().isTest() && LocationHandler.getHandler().locationPoint.get() != null){
            mMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(
                    LocationHandler.getHandler().locationPoint.get().getLatitude(),
                    LocationHandler.getHandler().locationPoint.get().getLongitude())));
            mMap.moveCamera(CameraUpdateFactory.zoomTo(12f));
        }

        mMap.setOnMarkerClickListener(markerClickListener);
        Log.d(TAG, "Map ready");

        FavorRequest.all(favorList, null,null);

        favorList.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(Observable sender, int propertyId) {
                if(propertyId != ObservableArrayList.ContentChangeType.Update.ordinal()){
                    return;
                }
                for(Favor favor:favorList){
                    GeoPoint point = (GeoPoint) favor.get(Favor.ObjectFields.location);
                    LatLng location = new LatLng(point.getLatitude(),point.getLongitude());

                    //TODO : try to do it in a more clean way
                    if (!ExecutionMode.getInstance().isTest()) {
                        Resources r = getResources();
                        int drawableId = r.getIdentifier(getIconNameFromCategory(favor.get(Favor.StringFields.category)), "drawable", "ch.epfl.sweng.favors");

                        BitmapDescriptor icon = BitmapDescriptorFactory.fromBitmap(getMarkerBitmapFromView(drawableId));

                        Marker marker = mMap.addMarker(new MarkerOptions().position(location).title(favor.get(Favor.StringFields.title)).icon(icon));
                        favorsMap.put(marker.getId(), favor);
                        Log.d(TAG, "new Marker : " + marker.getId());
                    }
                }
            }
        });
    }

    /**
     * Build a custom bitmap from a ressource id, found this solution in stackoverflow
     * https://stackoverflow.com/questions/14811579/how-to-create-a-custom-shaped-bitmap-marker-with-android-map-api-v2
     * @param resId  @DrawableRes int id of the ressource (image), reference to an image that is in the drawable folder
     * @return Bitmap representing the ressource integrated in a custom layout
     */
    protected Bitmap getMarkerBitmapFromView(@DrawableRes int resId) {

        View customMarkerView = getLayoutInflater().inflate(R.layout.custom_marker_map, null);

        ImageView markerImageView = (ImageView) customMarkerView.findViewById(R.id.profile_image);
        markerImageView.setImageResource(resId);
        customMarkerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        customMarkerView.layout(0, 0, customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight());
        customMarkerView.buildDrawingCache();

        Bitmap returnedBitmap = Bitmap.createBitmap(customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight(),Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(returnedBitmap);
        canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);

        Drawable drawable = customMarkerView.getBackground();
        if (drawable != null)
            drawable.draw(canvas);

        customMarkerView.draw(canvas);

        return returnedBitmap;
    }

}