package com.example.test.websocket;

import java.io.IOException;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

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

import parser.Parser;
import parser.Parser.TokenStream;
import simulator.interfaces.html.IWebSocketMessageSender;


@Component
public class WebSocketHandler extends TextWebSocketHandler implements IWebSocketMessageSender{
	
	private Map<WebSocketSession, String> sessions = new HashMap<>();
	private Map<String, WebSocketSession> sessionManager = new HashMap<>();
	private Map<String, List<String>> buffer = new HashMap<>();
	private List<IMessageReceiveListener> messageListeners;
	private TokenStream stream;
	private Parser parser; 
	
	
	public WebSocketHandler() {
		messageListeners = new ArrayList<>();
		stream = new Parser.TokenStream();
		parser = new Parser(stream);
	}
	
	public void addMessageListener(IMessageReceiveListener listener) {
		messageListeners.add(listener);
	}
	
	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
		System.out.println("add new session " + session.getId());
		sessions.put(session, null);
	}

	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
		System.out.println("colse session " + session.getId());
		String sessionId = sessions.get(session);
		sessions.remove(session);
		sessionManager.remove(sessionId);
	}
	
	@Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
		for(var listener : messageListeners) {
			listener.onReceivedMessage(message.getPayload(), session);
		}
    }
	
	public void sendMessageToAll(String message) throws Exception {
		for(var session : sessions.keySet()) {
			if(session.isOpen()) {
				session.sendMessage(new TextMessage(message));
			}
		}
	}
	
	public void connectIdToSession(String id, WebSocketSession session) {
		System.out.println("receive " + id);
		sessions.put(session, id);
		sessionManager.put(id, session);
		if(!buffer.containsKey(id)) {
			return;
		}
		for(String mes: buffer.get(id)) {
			try {
				session.sendMessage(new TextMessage(mes));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		buffer.remove(id);
	}
	
	@Override
	public void send(String message, String sessionId) {
		System.out.println("send " + message + "to " + sessionId);
		try {
			if(sessionManager.containsKey(sessionId)) {
				sessionManager.get(sessionId).sendMessage(new TextMessage(message));
			} else {
				if(!buffer.containsKey(sessionId)) {
					buffer.put(sessionId, new ArrayList<>());
				}
				buffer.get(sessionId).add(message);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
