2018-SWENG/2018-SWENG-Radius

View on GitHub
app/src/main/java/ch/epfl/sweng/radius/database/OthersInfo.java

Summary

Maintainability
A
3 hrs
Test Coverage
package ch.epfl.sweng.radius.database;

import android.util.Log;

import com.google.firebase.database.DatabaseError;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import ch.epfl.sweng.radius.utils.MapUtility;

public class OthersInfo extends DBObservable{
    public Timer timer = new Timer(true);
    private final int REFRESH_PERIOD = 5; // in seconds

    private static OthersInfo othersInfo = null;
    private static final Database database = Database.getInstance();
    private static final MapUtility mapUtility = MapUtility.getMapInstance();

    private static final HashMap<String, MLocation> usersPos = new HashMap<>();
    private static final HashMap<String, MLocation> newUsersPos = new HashMap<>();
    private static final HashMap<String, MLocation> allUserPos = new HashMap<>();
    private static final HashMap<String, MLocation> convUsers = new HashMap<>();
    private static final HashMap<String, MLocation> groupsPos = new HashMap<>();
    private static final HashMap<String, MLocation> topicsPos = new HashMap<>();
    private static final HashMap<String, User> users = new HashMap<>();
    private static final HashMap<String, MLocation> friendList = new HashMap<>();
    private static final HashMap<String, MLocation> requestList = new HashMap<>();

    /**
     * Static singleton method to return the instance of OthersInfo
     * @return othersInfo: the singleton instance of OthersInfo
     */
    public static OthersInfo getInstance() {
        if (othersInfo == null)
            othersInfo = new OthersInfo();
        return othersInfo;
    }

    /**
     * Private constructor for OthersInfo
     */
    private OthersInfo(){
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                fetchUsersInMyRadius();
                fetchUserObjects();
                fetchConvUsers();
                fetchFriends();
                fetchRequest();
            }
        }, 0, REFRESH_PERIOD*1000);
    }

    /**
     * Set the instance of OthersInfo to null
     */
    public void clearInstance(){
        othersInfo = null;
    }

    /**
     * Getter for usersPos
     * @return: users in radius
     */
    public HashMap<String, MLocation> getUsersInRadius(){
        return usersPos;
    }

    /**
     * Getter for allUserPos
     * @return: all user locations
     */
    public HashMap<String, MLocation> getAllUserLocations(){
        return allUserPos;
    }

    /**
     * Getter for groupsPos
     * @return: groups positions
     */
    public HashMap<String, MLocation> getGroupsPos(){
        return groupsPos;
    }

    /**
     * Getter for topicsPos
     * @return: topics positions
     */
    public HashMap<String, MLocation> getTopicsPos(){
        return topicsPos;
    }

    /**
     * Getter for newUsersPos
     * @return: new users positions
     */
    public HashMap<String, MLocation> getNewUsersPos() {
        return newUsersPos;
    }

    /**
     * Getter for users
     * @return: users
     */
    public HashMap<String, User> getUsers(){
        return users;
    }

    /**
     * Getter for convUsers
     * @return: convUsers
     */
    public HashMap<String, MLocation> getConvUsers() {
        return convUsers;
    }

    /**
     * Fetch the users according to the new location and radius value for the current user
     */
    public void fetchUsersInMyRadius(){
        database.readAllTableOnce(Database.Tables.LOCATIONS, new CallBackDatabase() {
            @Override
            public void onFinish(Object value) {
                newUsersPos.clear();
                for (MLocation loc : (ArrayList<MLocation>) value) {
                    if(mapUtility.contains(loc.getLatitude(), loc.getLongitude())) {
                        putInTable(loc);
                    }
                    else
                        removeFromTable(loc);
                    if (loc.getLocationType() == 0) {
                        allUserPos.put(loc.getID(), loc);
                    }
                }
                notifyLocationObservers(Database.Tables.LOCATIONS.toString());
            }

            @Override
            public void onError(DatabaseError error) {
                Log.e("FetchUserRadius", error.getMessage());
            }
        });
    }

    /**
     * Fetch the users that the current user has a conversation with
     */
    private void fetchConvUsers(){
        List<String> ids = new ArrayList<>(UserInfo.getInstance().getCurrentUser().getChatList().keySet());
        database.readListObjOnce(ids, Database.Tables.LOCATIONS, new CallBackDatabase() {
            @Override
            public void onFinish(Object value) {
                for(MLocation loc : (ArrayList<MLocation>) value){
                    if(!usersPos.containsKey(loc.getID()));
                        convUsers.put(loc.getID(), loc);
                }
            }

            @Override
            public void onError(DatabaseError error) {

            }
        });
    }

    /**
     * Fetch all user objects from the USERS table of the database
     */
    public void fetchUserObjects(){
        database.readAllTableOnce(Database.Tables.USERS, new CallBackDatabase() {
            @Override
            public void onFinish(Object value) {
                for (User user : (ArrayList<User>) value) {
                    users.put(user.getID(), user);
                }
                notifyLocationObservers(Database.Tables.LOCATIONS.toString());
            }

            @Override
            public void onError(DatabaseError error) {
                Log.e("FetchUser", error.getMessage());
            }
        });
    }

    /**
     * Fetch the friends for the current user
     */
    public void fetchFriends(){
        List<String> ids = new ArrayList<>(UserInfo.getInstance().getCurrentUser().getFriends().values());
        database.readListObjOnce(ids, Database.Tables.LOCATIONS, new CallBackDatabase() {
            @Override
            public void onFinish(Object value) {
                editList(friendList, value);
            }

            @Override
            public void onError(DatabaseError error) {
                Log.e("FetchFriend", error.getMessage());
            }
        });
    }

    /**
     * Fetch the friends requests
     */
    public void fetchRequest(){
        List<String> ids = new ArrayList<>(UserInfo.getInstance().getCurrentUser().getFriendsInvitations().values());
        database.readListObjOnce(ids, Database.Tables.LOCATIONS, new CallBackDatabase() {
            @Override
            public void onFinish(Object value) {
                editList(requestList, value);
            }

            @Override
            public void onError(DatabaseError error) {
                Log.e("FetchRequests", error.getMessage());
            }
        });
    }

    /**
     * Change the locations list
     * @param list: list to change
     * @param value: the MLocation parameter
     */
    private void editList(HashMap<String, MLocation> list, Object value) {
        list.clear();
        for(MLocation loc : (ArrayList<MLocation>) value){
            list.put(loc.getID(), loc);
            notifyUserObservers("");
        }
    }

    /**
     * Save the given MLocation to a table according to type
     * @param loc: MLocation to put
     */
    public void putInTable(MLocation loc){
        switch (loc.getLocationType()){
            case 0:
                if(loc.getID().equals(UserInfo.getInstance().getCurrentPosition().getID()))
                    break;
                // For near friend notifications
                if(friendList.containsKey(loc.getID())) toggledVisibility(loc);
                usersPos.put(loc.getID(), loc);
                break;
            case 1:
                groupsPos.put(loc.getID(), loc);
                break;
            case 2:
                topicsPos.put(loc.getID(), loc);
                break;
        }
    }

    /**
     * Put the new users position to the locations when visibility changes
     * @param loc: MLocation
     */
    private void toggledVisibility(MLocation loc) {
            if(!usersPos.containsKey(loc.getID())
                    || (!friendList.get(loc.getID()).getVisible()
                    && loc.getVisible()))
                newUsersPos.put(loc.getID(), loc);
    }

    /**
     * Remove MLocation from table according to type
     * @param loc: MLocation to put
     */
    public void removeFromTable(MLocation loc){
        if(loc == null) return;
        switch (loc.getLocationType()){
            case 0:
                if(loc.getID().equals(UserInfo.getInstance().getCurrentPosition().getID()))
                    break;
                // For near friend notifications
                usersPos.remove(loc.getID());
                break;
            case 1:
                groupsPos.remove(loc.getID());
                break;
            case 2:
                topicsPos.remove(loc.getID());
                break;
        }
    }

    /**
     * Getter for values of friend list
     * @return: Values of friendList
     */
    public Collection<MLocation> getFriendList() {
        return friendList.values();
    }

    /**
     * Getter for values of requests list
     * @return: Values of requestList
     */
    public Collection<MLocation> getRequestList() {
        return requestList.values();
    }
}