unit Ws.ServiceImpl;

interface

uses
  XData.Service.Common,
  XData.Server.Module,
  System.JSON,
  Ws.Service;

type
  [ServiceImplementation]
  TWebSocketService = class(TInterfacedObject, IWebSocketService)
  public
    function WebSockerConnectionHandler: TJSONObject;
  end;

implementation

uses
  System.SysUtils,
  Common.Logging,
  Sparkle.WebSocket,
  Sparkle.Sys.Timer,
  Sparkle.HttpServer.Context;

function TWebSocketService.WebSockerConnectionHandler: TJSONObject;
var
  Upgrader: IWebSocketUpgrader;
  WebSocket: IWebSocket;
  Timer: TSparkleTimer;
  Msg: IWebSocketMessage;
  MsgStr: string;
begin
  Result := nil;
  Logger.Log(1, 'websocket begin-------');

  Upgrader := THttpServerContext.Current.Item<IWebSocketUpgrader>;
  if Upgrader = nil then
  begin
    Logger.Log(1, 'websocket: no upgrader - not a websocket upgrade request');
    Exit;
  end;
  Logger.Log(1, 'websocket upgrading-------');

  WebSocket := Upgrader.Upgrade;
  Logger.Log(1, 'websocket upgraded-------');

  // First message must be the JWT token for authentication
  Msg := WebSocket.Receive;
  if Msg.MessageType <> TWebSocketMessageType.Text then
  begin
    Logger.Log(1, 'websocket auth failed - expected text token-------');
    Exit;
  end;
  MsgStr := TEncoding.Default.GetString(Msg.Data);
  //TODO: verify JWT in MsgStr against serverConfig.jwtTokenSecret
  Logger.Log(1, 'websocket auth ok (token received, verification pending)-------');

  Timer := TSparkleTimer.Create(
    procedure(Value: TObject)
    begin
      if WebSocket.State = TWebSocketState.Open then
        WebSocket.Send('Server message at ' + TimeToStr(Time));
    end,
    nil, 2000, TTimerType.Periodic
  );

  try
    while WebSocket.State = TWebSocketState.Open do
    begin
      Msg := WebSocket.Receive;
      case Msg.MessageType of
        TWebSocketMessageType.Text:
        begin
          MsgStr := TEncoding.Default.GetString(Msg.Data);
          Logger.Log(1, 'Web Socket Message: ' + MsgStr);
        end;
        TWebSocketMessageType.Close:
          Break;
      end;
    end;
  finally
    Timer.Free;
  end;
end;

initialization
  RegisterServiceType(TWebSocketService);

end.
