package server;

import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
import java.util.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
// import interfaces
import common.ClientInterface;
import common.ServerInterface;

public class Server extends UnicastRemoteObject implements ServerInterface {
    private Map<String, ClientInterface> onlineClients = new HashMap<>();
    private Map<String, List<String>> offlineMessages = new HashMap<>();
    private Map<String, Set<String>> blockedClients = new HashMap<>();

    protected Server() throws RemoteException {
        super();
    }

    @Override
    public synchronized void registerClient(String clientId, ClientInterface client) throws RemoteException {
        onlineClients.put(clientId, client);
        blockedClients.putIfAbsent(clientId, new HashSet<>());

        // Send any offline messages
        List<String> messages = offlineMessages.getOrDefault(clientId, new ArrayList<>());
        for (String msg : messages) {
            client.receiveMessage("Offline", msg);
        }
        offlineMessages.remove(clientId);
    }

    @Override
    public synchronized void sendMessage(String fromId, String toId, String message) throws RemoteException {
        // Check if recipient blocked sender
        Set<String> blocked = blockedClients.getOrDefault(toId, Collections.emptySet());
        if (blocked.contains(fromId))
            return;

        ClientInterface recipient = onlineClients.get(toId);
        if (recipient != null) {
            recipient.receiveMessage(fromId, message);
        } else {
            // Store message for offline delivery
            offlineMessages.putIfAbsent(toId, new ArrayList<>());
            offlineMessages.get(toId).add(fromId + ": " + message);
        }
    }

    @Override
    public synchronized void blockClient(String clientId, String blockedId) throws RemoteException {
        blockedClients.putIfAbsent(clientId, new HashSet<>());
        blockedClients.get(clientId).add(blockedId);
    }

    @Override
    public synchronized List<String> getOfflineMessages(String clientId) throws RemoteException {
        return offlineMessages.getOrDefault(clientId, Collections.emptyList());
    }

    // entry point
    public static void main(String[] args) throws Exception {
        Server server = new Server();
        Registry registry = LocateRegistry.createRegistry(1099);
        registry.rebind("ChatServer", server);
        System.out.println("Chat server running...");
    }
}
