package projet;

import java.io.StringReader;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;

import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;


@ServerEndpoint("/ws/bloc")
public class BlocCollaborative {

	private static final Map<String, Set<Session>> sessionsParPage = new ConcurrentHashMap<>();
	private static final Map<String, Map<Session, String>> utilisateursParPage = new ConcurrentHashMap<>();


    @OnOpen
    public void onOpen(Session session) {
    	String query = session.getQueryString();
    	String pageId = extractPageId(query);
    	session.getUserProperties().put("pageId", pageId);
    	
    	sessionsParPage.computeIfAbsent(pageId, k -> ConcurrentHashMap.newKeySet()).add(session);
    }

    @OnMessage
    public void onMessage(String message, Session session) {
    	String pageId = (String) session.getUserProperties().get("pageId");
    	Set<Session> sessions = sessionsParPage.get(pageId);
    	Map<Session, String> utilisateurs = utilisateursParPage.computeIfAbsent(pageId, k -> new ConcurrentHashMap<>());
    	
    	JsonObject json = Json.createReader(new StringReader(message)).readObject();
    	
        if ("nouvelleConnexion".equals(json.getString("action", ""))) {
            String login = json.getString("utilisateur", "Anonyme");
            utilisateurs.put(session, login);

            envoiUtilisateursParPage(pageId);
            return;
        }
    	
    	synchronized (sessions) {
            for (Session s : sessions) {
                if (s.isOpen() && !s.equals(session)) {
                	s.getAsyncRemote().sendText(message);
                }
            }
        }
    }

    @OnClose
    public void onClose(Session session) {
        String pageId = (String) session.getUserProperties().get("pageId");
        if (pageId != null) {
            Set<Session> sessions = sessionsParPage.get(pageId);
            Map<Session, String> utilisateurs = utilisateursParPage.get(pageId);
            if (sessions != null) {
                sessions.remove(session);
                if (sessions.isEmpty()) {
                    sessionsParPage.remove(pageId);
                    utilisateursParPage.remove(pageId);
                }
            }
            if (utilisateurs != null) {
                utilisateurs.remove(session);
                envoiUtilisateursParPage(pageId);
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        throwable.printStackTrace();
    }
    
    private String extractPageId(String query) {
        for (String param : query.split("&")) {
            String[] kv = param.split("=");
            if (kv.length == 2 && kv[0].equals("pageId")) {
                return kv[1];
            }
        }
        return "default";
    }
    
    private void envoiUtilisateursParPage(String pageId) {
    	Set<Session> sessions = sessionsParPage.get(pageId);
    	Map<Session, String> utilisateurs = utilisateursParPage.get(pageId);
    	
    	if (utilisateurs == null || sessions == null) return;
    	
    	JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
    	for (String utilisateur : utilisateurs.values()) {
    	    arrayBuilder.add(utilisateur);
    	}

    	
        JsonObject json = Json.createObjectBuilder()
                .add("action", "users")
                .add("users", arrayBuilder)
                .build();
        
        for (Session s : sessions) {
            if (s.isOpen()) {
                s.getAsyncRemote().sendText(json.toString());
            }
        }
    }
}
