unit Module.Websocket;

interface

uses
  System.SysUtils, System.Classes, WEBLib.WebSocketClient, Web, WEBLib.Controls, WEBLib.Modules,
  Auth.Service;

type
  TdmWebsocket = class(TWebDataModule)

  private
    procedure EMiMobileWebSocketClientConnect(Sender: TObject);
    procedure EMiMobileWebSocketClientDataReceived(Sender: TObject;
      Origin: string; SocketData: TJSObjectRecord);
    procedure EMiMobileWebSocketClientDisconnect(Sender: TObject);
    procedure EMiMobileWebSocketClientMessageReceived(Sender: TObject;
      AMessage: string);
    procedure EMiMobileWebSocketClientBinaryDataReceived(Sender: TObject;
      AData: TBytes);

  public
    EMiMobileWebSocketClient: TWebSocketClient;
    procedure DataModuleCreate(Sender: TObject);
    procedure Connect(const AWsUrl: string);

  end;

var
  dmWebsocket: TdmWebsocket;

implementation

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}

procedure TdmWebsocket.DataModuleCreate(Sender: TObject);
begin

end;

procedure TdmWebsocket.Connect(const AWsUrl: string);
var
  Rest, HostPort, Scheme, Path, Token: string;
  ColonSlashSlash, SlashPos, ColonPos: Integer;
begin
  if AWsUrl = '' then
    Exit;

  // Parse  ws://host:port/path  or  wss://host:port/path
  ColonSlashSlash := Pos('://', AWsUrl);
  if ColonSlashSlash = 0 then
    Exit;

  Scheme := LowerCase(Copy(AWsUrl, 1, ColonSlashSlash - 1));
  Rest   := Copy(AWsUrl, ColonSlashSlash + 3, MaxInt);

  SlashPos := Pos('/', Rest);
  if SlashPos > 0 then
  begin
    HostPort := Copy(Rest, 1, SlashPos - 1);
    Path := Copy(Rest, SlashPos, MaxInt);
  end
  else
  begin
    HostPort := Rest;
    Path := '/';
  end;

  // Append JWT token as query param — browsers can't set Authorization headers on WebSocket.
  Token := AuthService.GetToken;
  if Token <> '' then
  begin
    if Pos('?', Path) > 0 then
      Path := Path + '&token=' + Token
    else
      Path := Path + '?token=' + Token;
  end;

  EMiMobileWebSocketClient.PathName := Path;

  ColonPos := Pos(':', HostPort);
  if ColonPos > 0 then
  begin
    EMiMobileWebSocketClient.HostName := Copy(HostPort, 1, ColonPos - 1);
    if Scheme = 'wss' then
      EMiMobileWebSocketClient.Port := StrToIntDef(Copy(HostPort, ColonPos + 1, MaxInt), 443)
    else
      EMiMobileWebSocketClient.Port := StrToIntDef(Copy(HostPort, ColonPos + 1, MaxInt), 80);
  end
  else
  begin
    EMiMobileWebSocketClient.HostName := HostPort;
    if Scheme = 'wss' then
      EMiMobileWebSocketClient.Port := 443
    else
      EMiMobileWebSocketClient.Port := 80;
  end;

  EMiMobileWebSocketClient.UseSSL := (Scheme = 'wss');
  EMiMobileWebSocketClient.Active := True;
end;

procedure TdmWebsocket.EMiMobileWebSocketClientBinaryDataReceived(
  Sender: TObject; AData: TBytes);
begin
  console.log('EMiMobileWebSocketClientBinaryDataReceived');
end;

procedure TdmWebsocket.EMiMobileWebSocketClientConnect(Sender: TObject);
begin
  console.log('EMiMobileWebSocketClientConnect');
end;

procedure TdmWebsocket.EMiMobileWebSocketClientDataReceived(Sender: TObject;
  Origin: string; SocketData: TJSObjectRecord);
begin
  console.log('EMiMobileWebSocketClientDataReceived');
end;

procedure TdmWebsocket.EMiMobileWebSocketClientDisconnect(Sender: TObject);
begin
  console.log('EMiMobileWebSocketClientDisconnect');
end;

procedure TdmWebsocket.EMiMobileWebSocketClientMessageReceived(Sender: TObject;
  AMessage: string);
begin
  console.log('EMiMobileWebSocketClientMessageReceived');
end;

end.
