package com.insa.app.database;

import com.insa.app.controller.Controller;
import com.insa.app.model.User;
import com.insa.app.network.NetworkMessage;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.WriteResult;
import org.jongo.Jongo;
import org.jongo.MongoCollection;

import java.util.*;

public class Database implements DatabaseInterface {
    DB db = new MongoClient().getDB("test");

    Jongo jongo = new Jongo(db);
    MongoCollection users = jongo.getCollection("users");
    MongoCollection messages = jongo.getCollection("messages");
    MongoCollection me = jongo.getCollection("me");

    private Controller controller;

    public Database(Controller controller) {
        this.controller = controller;
    }

    @Override
    public void storeMessage(NetworkMessage mess) {
        messages.save(mess);
    }

    public void storeMe(User user) {
        WriteResult res = me.update("{id: #}", user.getId()).upsert().with(user);
    }

    public void storeUser(User user) {
        WriteResult res = users.update("{id: #}", user.getId()).upsert().with(user);
    }

    @Override
    public List<NetworkMessage> getMessages(User user) {
        User me = getMe();
        UUID myId = me.getId();
        UUID userId = user.getId();
        Iterable<NetworkMessage> netMessages = messages
            .find("{ $or: [{recipient: #, emitter: #}, {recipient: #, emitter: #}] }", myId, userId, userId, myId)
            .as(NetworkMessage.class);
        List<NetworkMessage> messagesList = new ArrayList<>();
        netMessages.iterator().forEachRemaining(messagesList::add);
        return messagesList;
    }

    @Override
    public Map<User, List<NetworkMessage>> getAllConversations() {
        Map<User, List<NetworkMessage>> map = new HashMap<>();
        List<User> users = getUsers();
        for (User user : users) {
            map.put(user, getMessages(user));
        }
        return map;
    }

    @Override
    public User getMe() {
        User myUser = me.findOne().as(User.class);
        return myUser;
    }

    private List<User> getUsers() {
        List<User> list = new ArrayList<>();
        users.find().as(User.class).iterator().forEachRemaining(list::add);
        return list;
    }

    @Override
    public void setUserName(String newName) {
        me.update("{}").with("{$set: {name: #}}", newName);
    }

    public void closeDatabase() {
        db.getMongo().close();
    }
}
