package gltronic.voozik.business;

import java.io.IOException;
import java.util.Random;

import org.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import gltronic.voozik.model.BiMap;

@Service
public class RoomManager implements IRoomManager{
  private volatile BiMap<String, WebSocketSession> users = new BiMap<String, WebSocketSession>();
  private volatile BiMap<String, String> rooms = new BiMap<String, String>();

  public void login(WebSocketSession session, String name) throws InterruptedException, IOException {
    if (name == null) {
      sendMessage(session, "error", "bad command command");
      return;
    }
    if (users.containsKey(name)) {
      sendMessage(session, "login", "false");
      return;
    }

    users.put(name, session);
    sendMessage(session, "login", "true");
    sendServerInfos(session);

    System.err.println("[ROOM] Logged "+name);
  }

  public void leave(WebSocketSession session) {
    String name = users.getKey(session);
    users.removeValue(session);
    if(rooms.containsValue(name)) rooms.removeValue(name);
  }

  public void createRoom(WebSocketSession session) throws InterruptedException, IOException {
    if (!users.containsValue(session)) {
      sendMessage(session, "error", "need login");
      return;
    }
    String userName = users.getKey(session);
    if (rooms.containsKey(userName)) {
      sendMessage(session, "error", "no multiple room");
      return;
    }

    Random random = new Random();
    String roomName = Integer.toString(random.nextInt(9999));

    while (roomName.length() < 4) roomName += 0 + roomName;

    rooms.put(roomName, userName);
    sendMessage(session, "createRoom", roomName);

    System.err.println("[ROOM] Created room "+roomName+" by "+userName);
  }

  public void connectRoom(WebSocketSession session, String roomName) throws InterruptedException, IOException {
    if (roomName == null) {
      sendMessage(session, "error", "bad command command");
      return;
    }
    if (!users.containsValue(session)) {
      sendMessage(session, "error", "need login");
      return;
    }
    if (!rooms.containsKey(roomName)) {
      sendMessage(session, "error", "no room");
      return;
    }

    String roomAdmin = rooms.get(roomName);
    sendMessage(session, "connectRoom", roomAdmin);

    String userName = users.getKey(session);
    System.err.println("[ROOM] Connection to room "+roomName+" ("+roomAdmin+") by "+userName);
  }

  public void followRTC(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
    String payload = message.getPayload();
    JSONObject jsonObject = new JSONObject(payload);
    String target = (String) jsonObject.get("target");

    if (target == null) {
      sendMessage(session, "error", "no target");
      return;
    }

    WebSocketSession targetSession = users.get(target);

    if (targetSession == null) {
      sendMessage(session, "error", "unknow target");
      return;
    }

    System.err.println("[ROOM] Foward RTC message");
    followMessage(targetSession, message);
  }

  public void followMessage (WebSocketSession session, TextMessage message) throws IOException {
    session.sendMessage(message);
  }

  public void sendMessage(WebSocketSession session, String type, String message) throws InterruptedException, IOException {
    session.sendMessage(new TextMessage("{\"type\":\""+type+"\",\"message\":\""+message+"\"}"));
  }

  public void sendServerInfos(WebSocketSession session) throws InterruptedException, IOException {
    session.sendMessage(new TextMessage("{\"type\":\"serverInfos\",\"userCount\":\""+users.size()+"\",\"roomCount\":\""+rooms.size()+"\"}"));
  }

}