<commit_before>package com.frinder.frinder.dataaccess;

import android.content.Context;
import android.support.annotation.NonNull;
import android.util.Log;

import com.facebook.Profile;
import com.frinder.frinder.model.Message;
import com.frinder.frinder.model.MessageThread;
import com.frinder.frinder.utils.Constants;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QuerySnapshot;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MessageFirebaseDas {

    FirebaseFirestore db;
    private static final String TAG = "MessageFirebaseDas";
    private Context context;

    public MessageFirebaseDas(Context context) {
        this.context = context;
        FirebaseApp.initializeApp(context);
        db = FirebaseFirestore.getInstance();
    }

    public void getOrCreateThread(final String inUser1, final String inUser2, final OnCompletionListener listener) {
        getDocument(inUser1, inUser2).get()
                .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful() && task.getResult() != null) {
                    DocumentSnapshot document = task.getResult();
                    if (document != null && document.exists() && document.getData() != null) {
                        MessageThread thread = convertThreadFromFirebaseObject(document.getId(), document.getData());
                        listener.onThreadReceived(thread);
                        return;
                    } else {
                        Log.d(TAG, "GetThread: No such document");
                    }
                } else {
                    Log.d(TAG, "GetThread: get failed with ", task.getException());
                }
                createThread(inUser1, inUser2, listener);
            }
        });
    }

    private void createThread(String inUser1, String inUser2, final OnCompletionListener listener) {
        // TODO: This code can race between users (fix this)
        HashMap<String, String> map = new HashMap<>();
        final String user1, user2;
        if (inUser1.compareTo(inUser2) > 0) {
            user1 = inUser2;
            user2 = inUser1;
        } else {
            user1 = inUser1;
            user2 = inUser2;
        }
        map.put(Constants.THREAD_COLUMN_USER1, user1);
        map.put(Constants.THREAD_COLUMN_USER2, user2);
        final String threadId = getDocumentId(inUser1, inUser2);
        getDocument(threadId)
                .set(map)
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Log.d(TAG, "LocationUpdate: DocumentSnapshot successfully updated!");
                        MessageThread thread = new MessageThread();
                        thread.uid = threadId;
                        thread.userId = getThreadUserId(user1, user2);
                        listener.onThreadReceived(thread);
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "LocationUpdate: Error updating document", e);
                        listener.onThreadReceived(null);
                    }
                });
    }

    public void getThreads(final OnCompletionListener listener) {
        String loggedInUserId = Profile.getCurrentProfile().getId();
        OnCompletionListener inListener = new OnCompletionListener() {

            private boolean mFirstReceived = false;
            private ArrayList<MessageThread> mThreads;

            @Override
            public void onThreadsReceived(ArrayList<MessageThread> threads) {
                // TODO: Can this be called from different thread? If so, add synchronization logic
                if (!mFirstReceived) {
                    mThreads = new ArrayList<>(threads);
                    mFirstReceived = true;
                } else {
                    mThreads.addAll(threads);
                    Collections.sort(mThreads);
                    listener.onThreadsReceived(mThreads);
                }
            }
        };

        Query query1 = getCollection().whereEqualTo(Constants.THREAD_COLUMN_USER1, loggedInUserId);
        Query query2 = getCollection().whereEqualTo(Constants.THREAD_COLUMN_USER2, loggedInUserId);
        setupThreadCompletionListeners(query1, inListener);
        setupThreadCompletionListeners(query2, inListener);
    }

    public void getMessages(final MessageThread thread, final OnCompletionListener listener) {
        getDocument(thread.uid).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful()) {
                    DocumentSnapshot document = task.getResult();
                    if (document != null && document.exists()) {
                        Log.d(TAG, "GetUser: DocumentSnapshot data: " + task.getResult().getData());
                        if (task.getResult() != null && task.getResult().getData() != null) {
                            listener.onMessagesReceived(parseMessageList(document, thread));
                            return;
                        }
                    } else {
                        Log.d(TAG, "GetUser: No such document");
                    }
                } else {
                    Log.d(TAG, "GetUser: get failed with ", task.getException());
                }
                listener.onMessagesReceived(null);
            }
        });
    }

    public void addMessage(final MessageThread thread,
                           final Message message,
                           final OnMessageSendCompletionListener inListener) {
        getMessages(thread, new OnCompletionListener() {
            @Override
            public void onMessagesReceived(ArrayList<Message> inMessages) {
                ArrayList<Message> messages = new ArrayList<Message>();
                messages.addAll(inMessages);
                messages.add(message);
                List fMessages = convertMessageListToFirebaseObjectList(thread, messages);
                Map<String,Object> threadData = new HashMap<>();
                threadData.put(Constants.THREAD_COLUMN_MESSAGES, fMessages);
                threadData.put(Constants.THREAD_COLUMN_LAST_MESSAGE, message.text);
                threadData.put(Constants.THREAD_COLUMN_LAST_TIMESTAMP, message.timestamp);<commit_msg>Set unread counter for threads<commit_after>package com.frinder.frinder.dataaccess;

import android.content.Context;
import android.support.annotation.NonNull;
import android.util.Log;

import com.facebook.Profile;
import com.frinder.frinder.model.Message;
import com.frinder.frinder.model.MessageThread;
import com.frinder.frinder.utils.Constants;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QuerySnapshot;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MessageFirebaseDas {

    FirebaseFirestore db;
    private static final String TAG = "MessageFirebaseDas";
    private Context context;

    public MessageFirebaseDas(Context context) {
        this.context = context;
        FirebaseApp.initializeApp(context);
        db = FirebaseFirestore.getInstance();
    }

    public void getOrCreateThread(final String inUser1, final String inUser2, final OnCompletionListener listener) {
        getDocument(inUser1, inUser2).get()
                .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful() && task.getResult() != null) {
                    DocumentSnapshot document = task.getResult();
                    if (document != null && document.exists() && document.getData() != null) {
                        MessageThread thread = convertThreadFromFirebaseObject(document.getId(), document.getData());
                        listener.onThreadReceived(thread);
                        return;
                    } else {
                        Log.d(TAG, "GetThread: No such document");
                    }
                } else {
                    Log.d(TAG, "GetThread: get failed with ", task.getException());
                }
                createThread(inUser1, inUser2, listener);
            }
        });
    }

    private void createThread(String inUser1, String inUser2, final OnCompletionListener listener) {
        // TODO: This code can race between users (fix this)
        HashMap<String, String> map = new HashMap<>();
        final String user1, user2;
        if (inUser1.compareTo(inUser2) > 0) {
            user1 = inUser2;
            user2 = inUser1;
        } else {
            user1 = inUser1;
            user2 = inUser2;
        }
        map.put(Constants.THREAD_COLUMN_USER1, user1);
        map.put(Constants.THREAD_COLUMN_USER2, user2);
        final String threadId = getDocumentId(inUser1, inUser2);
        getDocument(threadId)
                .set(map)
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        Log.d(TAG, "LocationUpdate: DocumentSnapshot successfully updated!");
                        MessageThread thread = new MessageThread();
                        thread.uid = threadId;
                        thread.userId = getThreadUserId(user1, user2);
                        listener.onThreadReceived(thread);
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "LocationUpdate: Error updating document", e);
                        listener.onThreadReceived(null);
                    }
                });
    }

    public void getThreads(final OnCompletionListener listener) {
        String loggedInUserId = Profile.getCurrentProfile().getId();
        OnCompletionListener inListener = new OnCompletionListener() {

            private boolean mFirstReceived = false;
            private ArrayList<MessageThread> mThreads;

            @Override
            public void onThreadsReceived(ArrayList<MessageThread> threads) {
                // TODO: Can this be called from different thread? If so, add synchronization logic
                if (!mFirstReceived) {
                    mThreads = new ArrayList<>(threads);
                    mFirstReceived = true;
                } else {
                    mThreads.addAll(threads);
                    Collections.sort(mThreads);
                    listener.onThreadsReceived(mThreads);
                }
            }
        };

        Query query1 = getCollection().whereEqualTo(Constants.THREAD_COLUMN_USER1, loggedInUserId);
        Query query2 = getCollection().whereEqualTo(Constants.THREAD_COLUMN_USER2, loggedInUserId);
        setupThreadCompletionListeners(query1, inListener);
        setupThreadCompletionListeners(query2, inListener);
    }

    public void getMessages(final MessageThread thread, final OnCompletionListener listener) {
        getDocument(thread.uid).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful()) {
                    DocumentSnapshot document = task.getResult();
                    if (document != null && document.exists()) {
                        Log.d(TAG, "GetUser: DocumentSnapshot data: " + task.getResult().getData());
                        if (task.getResult() != null && task.getResult().getData() != null) {
                            listener.onMessagesReceived(parseMessageList(document, thread));
                            return;
                        }
                    } else {
                        Log.d(TAG, "GetUser: No such document");
                    }
                } else {
                    Log.d(TAG, "GetUser: get failed with ", task.getException());
                }
                listener.onMessagesReceived(null);
            }
        });
    }

    public void addMessage(final MessageThread thread,
                           final Message message,
                           final OnMessageSendCompletionListener inListener) {
        getMessages(thread, new OnCompletionListener() {
            @Override
            public void onMessagesReceived(ArrayList<Message> inMessages) {
                ArrayList<Message> messages = new ArrayList<Message>();
                messages.addAll(inMessages);
                messages.add(message);
                List fMessages = convertMessageListToFirebaseObjectList(thread, messages);
                Map<String,Object> threadData = new HashMap<>();
                threadData.put(Constants.THREAD_COLUMN_MESSAGES, fMessages);
                threadData.put(Constants.THREAD_COLUMN_LAST_MESSAGE, message.text);
                threadData.put(Constants.THREAD_COLUMN_LAST_TIMESTAMP, message.timestamp);
                threadData.put(Constants.THREAD_COLUMN_UNREAD, true);
{'fraction_non_alphanumeric': 0.08908534512070725, 'fraction_numerical': 0.0047602856171370285, 'mean_word_length': 2.0466128029832196, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '983747', 'n_tokens_mistral': 3602, 'n_tokens_neox': 3509, 'n_words': 737}