samuelchassot/SDP-SwissTeam

View on GitHub
app/src/main/java/ch/epfl/swissteam/services/view/fragments/ServicesFragment.java

Summary

Maintainability
B
4 hrs
Test Coverage
package ch.epfl.swissteam.services.view.fragments;

import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

import ch.epfl.swissteam.services.R;
import ch.epfl.swissteam.services.view.builders.UserAdapter;
import ch.epfl.swissteam.services.models.Categories;
import ch.epfl.swissteam.services.models.User;
import ch.epfl.swissteam.services.providers.DBUtility;
import ch.epfl.swissteam.services.providers.GoogleSignInSingleton;
import ch.epfl.swissteam.services.providers.LocationManager;
import ch.epfl.swissteam.services.utils.ActivityUtils;

/**
 * Fragment for displaying users in form of a list
 *
 * @author simonwicky
 */
public class ServicesFragment extends Fragment {

    private RecyclerView.Adapter mAdapter_;
    private ArrayList<User> users = new ArrayList<>();
    private ArrayList<String> keywords_;
    private Categories currentCategory_;
    private boolean sortByRating = true;

    public ServicesFragment() {
        // Required empty public constructor
    }

    /**
     * Create a new instance of Services fragment
     *
     * @return the created instance
     */
    public static ServicesFragment newInstance() {
        return new ServicesFragment();
    }

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

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_services, container, false);

        // Toolbar
        Toolbar toolbar = getActivity().findViewById(R.id.toolbar);
        toolbar.setTitle(R.string.toolbar_services);

        keywords_ = new ArrayList<>();

        RecyclerView mRecyclerView = view.findViewById(R.id.services_recycler);
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
        mAdapter_ = new UserAdapter(users, getContext());
        mRecyclerView.setAdapter(mAdapter_);
        mRecyclerView.setLayoutManager(mLayoutManager);

        Spinner filterSpinner = (Spinner) view.findViewById(R.id.services_spinner);
        ArrayAdapter<Categories> filterSpinnerAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, Categories.values());
        filterSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        filterSpinner.setAdapter(filterSpinnerAdapter);

        filterSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                currentCategory_ = (Categories) adapterView.getItemAtPosition(i);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });

        EditText keywordsInput = (EditText) view.findViewById(R.id.edittext_services_keywordsinput);
        keywordsInput.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                                          int after) {

            }

            @Override
            public void afterTextChanged(Editable s) {

                String inKeywords = s.toString();
                Log.i("KEYWORDS_LENGTH", "length = " + s.length());
                keywords_ = new ArrayList<>(Arrays.asList(inKeywords.split(" ")));
                Log.i("LIST_LENGTH", "list length = " + keywords_.size());
                keywords_.remove("");
                Log.i("LIST_LENGTH", "list length = " + keywords_.size());
            }
        });

        Button searchButton = (Button) view.findViewById(R.id.button_services_search);
        searchButton.setOnClickListener(v ->{
            Log.i("KEYWORDS", "list of keywords is empty ? " + keywords_.isEmpty());
            initDataSet(currentCategory_, keywords_);
        });

        String[] sortType = {getResources().getString(R.string.servicesfragment_proximity), getResources().getString(R.string.servicesfragment_rating)};
        ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item, sortType);
        spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // The drop down view
        ((Spinner)view.findViewById(R.id.spinner_services_sorttype)).setAdapter(spinnerArrayAdapter);
        ((Spinner)view.findViewById(R.id.spinner_services_sorttype)).setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                    sortByRating = i != 0;
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });

        initDataSet(Categories.ALL, keywords_);

        return view;
    }

    private void initDataSet(Categories category, ArrayList<String> keywords) {
        ActivityUtils.hideKeyboard(this.getActivity());
        View view = getView();
        if (category == Categories.ALL) {
            DBUtility.get().getAllUsers((usersdb -> {
                users.clear();
                mAdapter_.notifyDataSetChanged();
                for (User u : usersdb) {
                    if (userContainsKeywords(u, keywords, category)) {
                        if (!u.getGoogleId_().equals(GoogleSignInSingleton.get().getClientUniqueID())) {
                            //don't add current user to the list
                            users.add(u);
                        }
                    }
                }
                serviceProblemTextUpdate(view, users.isEmpty());
                sortUserList();
            }));
        } else {
            DBUtility.get().getUsersFromCategory(category, (googleIds) -> {
                users.clear();
                mAdapter_.notifyDataSetChanged();
                serviceProblemTextUpdate(view, googleIds.isEmpty());
                for (String googleId : googleIds) {
                    DBUtility.get().getUser(googleId, user -> {
                        if (user != null && !users.contains(user) && !user.getGoogleId_().equals(GoogleSignInSingleton.get().getClientUniqueID()) &&
                                userContainsKeywords(user, keywords, category)) {
                            users.add(user);
                            sortUserList();
                        }
                    });
                }
            });
        }
    }

    private void sortUserList() {
        if(sortByRating){
            Collections.sort(users, (a, b) -> b.getRating_() - a.getRating_());
        }
        else {
            Collections.sort(users, this::compareUsersUsingDistanceWithRef);
        }
        mAdapter_.notifyDataSetChanged();
    }

    private void serviceProblemTextUpdate(View view, boolean empty) {
        if (view != null) {
            if (empty) {
                view.findViewById(R.id.services_problem_text).setVisibility(View.VISIBLE);
            } else {
                view.findViewById(R.id.services_problem_text).setVisibility(View.INVISIBLE);
            }
        }
    }

    /**
     * return true if keywords of the user contains at least one of the list kw
     * for the given category
     * the list of keywords kw must contains ONLY LOWERCASE words
     * @param u the user
     * @param kw list of keywords to search for
     * @param cat the category for which want to search the keywords
     * @return boolean user has or not
     */
    private boolean userContainsKeywords(User u, ArrayList<String> kw, Categories cat){
        ArrayList<String> listForCat;
        if(cat.compareTo(Categories.ALL) == 0){
            listForCat = new ArrayList<>();
               for(Categories c : Categories.values()){
                   listForCat.addAll(u.getKeyWords(c));
               }

        }else{
            listForCat = u.getKeyWords(cat);
        }
        if(kw.isEmpty()){
            return true;
        }
        for (String k : kw){
            if(listForCat.contains(k.toLowerCase())){
                return true;
            }
        }
        return false;
    }

    private int compareUsersUsingDistanceWithRef(User u1, User u2){
        Location ref = LocationManager.get().getCurrentLocation_();
        int result = 0;
        Location u1Location = new Location("");
        u1Location.setLatitude(u1.getLatitude_());
        u1Location.setLongitude(u1.getLongitude_());

        Log.i("U1Latitude", u1.getLatitude_() + "");

        Location u2Location = new Location("");
        u2Location.setLatitude(u2.getLatitude_());
        u2Location.setLongitude(u2.getLongitude_());

        if(ref != null) {
            result = (int) u1Location.distanceTo(ref) - (int) u2Location.distanceTo(ref);
            Log.i("Ref", "not null");
        }
        return result;
    }
}