package com.guidewire.pl.system.websocket;

import com.guidewire.pl.system.logging.PLLoggerCategory;
import com.guidewire.pl.system.websocket.WebSocketServletRequestListener.UpgradeRequest;
import java.io.IOException;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/websocket", configurator = RequestDataServerEndpointConfigurator.class)
public class WebSocketServer {
   public static final String HTTP_ID_KEY = "wshttplink";
   private static volatile boolean _registered;

   static void setRegistered() {
      _registered = true;
   }

   static boolean isRegistered() {
      return _registered;
   }

   private void forceCloseSession(Session wsSession) {
      try {
         PLLoggerCategory.UI_REQUEST.warn("Forcing WebSocket closed. id: " + wsSession.getId());
         wsSession.close();
      } catch (IOException e) {
         this.closeSocket(wsSession);
      }
   }

   @OnOpen
   public void openSocket(Session newWsSession, EndpointConfig config) {
      UpgradeRequest upgradeRequest = WebSocketServletRequestListener.getAndClearUpgradeRequest();
      if (upgradeRequest != null) {
         HttpSession httpSession = upgradeRequest.getHttpSession();
         if (httpSession == null) {
            this.forceCloseSession(newWsSession);
            return;
         }

         newWsSession.getUserProperties().put("wshttplink", httpSession.getId());
         if (PLLoggerCategory.UI_REQUEST.isDebugEnabled()) {
            PLLoggerCategory.UI_REQUEST.debug("Adding Web Socket Session. id: " + newWsSession.getId());
         }

         WebSocketSessionManager.addSession(httpSession, upgradeRequest.getServiceToken(), newWsSession);
      } else {
         this.forceCloseSession(newWsSession);
      }
   }

   @OnClose
   public void closeSocket(Session wsSession) {
      if (PLLoggerCategory.UI_REQUEST.isDebugEnabled()) {
         PLLoggerCategory.UI_REQUEST.debug("Closing Web Socket Session. id: " + wsSession.getId());
      }

      WebSocketSessionManager.removeSession(wsSession);
   }

   @OnError
   public void onSocketError(Throwable error) {
      if (PLLoggerCategory.UI_REQUEST.isDebugEnabled()) {
         PLLoggerCategory.UI_REQUEST.debug("Websocket error", error);
      }
   }

   @OnMessage
   public void onDataFromSocket(String dataStr, Session wsSession) {
      WebSocketSessionManager.onData(wsSession, dataStr);
   }
}
