unit Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, Winapi.ShellApi,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls, Vcl.ExtCtrls, System.Generics.Collections, System.IniFiles,
  Auth.Service, Auth.Server.Module, Api.Server.Module, App.Server.Module,
  ExeInfo, Api.Service, Vcl.ComCtrls, WebSocket.Manager,
  VCL.TMSFNCWebSocketCommon, VCL.TMSFNCCustomComponent,
  VCL.TMSFNCWebSocketClient, WEBLib.WebSocketClient, FireDAC.Stan.Intf,
  FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS,
  FireDAC.Phys.Intf, FireDAC.DApt.Intf, Data.DB, Vcl.Grids, Vcl.DBGrids,
  FireDAC.Comp.DataSet, FireDAC.Comp.Client;

type
  TFMain = class(TForm)
    btnApiSwaggerUI: TButton;
    btnExit: TButton;
    initTimer: TTimer;
    btnAuthSwaggerUI: TButton;
    ExeInfo1: TExeInfo;
    pgcMain: TPageControl;
    tabServerLog: TTabSheet;
    tabConnectedClients: TTabSheet;
    memoInfo: TMemo;
    tblConnectedClients: TFDMemTable;
    dsConnectedClients: TDataSource;
    grdConnectedClients: TDBGrid;
    procedure btnApiSwaggerUIClick(Sender: TObject);
    procedure btnExitClick(Sender: TObject);
    procedure ContactFormData(AText: String);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure initTimerTimer(Sender: TObject);
    procedure btnAuthSwaggerUIClick(Sender: TObject);
  strict private
    FWebSocketManager: TWebSocketManager;
    procedure StartServers;
    function LogValue(const LabelName: string; const Value: string; FromIni: Boolean): string;
  private
    function LocalBrowserUrl(const Url: string): string;
  end;

var
  FMain: TFMain;

implementation

uses
  Common.Logging,
  Common.Config,
  Common.Ini,
  Sparkle.Utils,
  Api.Database,
  System.StrUtils;

{$R *.dfm}

{ --- Event Handlers --- }

procedure TFMain.btnExitClick(Sender: TObject);
begin
  Close;
end;

function TFMain.LocalBrowserUrl(const Url: string): string;
begin
  Result := StringReplace(Url, '://0.0.0.0:', '://localhost:', [rfIgnoreCase]);
end;

procedure TFMain.btnApiSwaggerUIClick(Sender: TObject);
var
  url: string;
begin
  url := TSparkleUtils.CombineUrlFast(ApiServerModule.XDataServer1.BaseUrl, 'swaggerui');
  ShellExecute(Handle, 'open', PChar(LocalBrowserUrl(url)), nil, nil, SW_SHOWNORMAL);
end;

procedure TFMain.btnAuthSwaggerUIClick(Sender: TObject);
var
  url: string;
begin
  url := TSparkleUtils.CombineUrlFast(AuthServerModule.XDataServer.BaseUrl, 'swaggerui');
  ShellExecute(Handle, 'open', PChar(LocalBrowserUrl(url)), nil, nil, SW_SHOWNORMAL);
end;

procedure TFMain.ContactFormData(AText: String);
begin
  if memoInfo.CanFocus then
    TThread.Queue(nil, procedure begin memoInfo.Lines.Add(AText); end)
  else
    TThread.Synchronize(nil, procedure begin memoInfo.Lines.Add(AText); end);
end;

procedure TFMain.initTimerTimer(Sender: TObject);
begin
  initTimer.Enabled := False;
  Caption := Caption + ' ver ' + ExeInfo1.FileVersion;
  ServerConfig := TServerConfig.Create;
  LoadIniEntries;
  LoadServerConfig;
  StartServers;
end;

procedure TFMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FWebSocketManager.OnClientsChanged := nil;
  FWebSocketManager.Free;

  ServerConfig.Free;
  IniEntries.Free;
  AuthServerModule.Free;
  ApiServerModule.Free;
  AppServerModule.Free;
end;

{ --- Helpers --- }

function TFMain.LogValue(const LabelName: string; const Value: string; FromIni: Boolean): string;
begin
  Result := LabelName + ': ' + Value + IfThen(FromIni, ' [from ini]', ' [default]');
end;

procedure TFMain.StartServers;
begin
  Logger.Log(1, '');
  Logger.Log(1, '*******************************************************');
  Logger.Log(1, '*                  emiMobile Server                   *');
  Logger.Log(1, Format('*               Version: %s', [FMain.ExeInfo1.FileVersion]));
  Logger.Log(1, '*            Developed by EM Systems, Inc.            *');
  Logger.Log(1, '*******************************************************');
  Logger.Log(1, '');

  Logger.Log(1, '--- Settings ---');
  Logger.Log(1, LogValue('--Settings->LogFileNum', IniEntries.LogFileNum.ToString, IniEntries.LogFileNumFromIni));
  Logger.Log(1, LogValue('--Settings->webClientVersion', IniEntries.WebClientVersion, IniEntries.WebClientVersionFromIni));

//  Logger.Log(1, '--- Database ---');
//  Logger.Log(1, LogValue('--Database->Server', IniEntries.DatabaseServer, IniEntries.DatabaseServerFromIni));
//  Logger.Log(1, LogValue('--Database->Database', IniEntries.DatabaseName, IniEntries.DatabaseNameFromIni));
//  Logger.Log(1, LogValue('--Database->Username', IniEntries.DatabaseUsername, IniEntries.DatabaseUsernameFromIni));
//  Logger.Log(1, LogValue('--Database->Password', IniEntries.DatabasePassword, IniEntries.DatabasePasswordFromIni));

  Logger.Log(1, '');
  Logger.Log(1, '--- URLs ---');
  try
    AuthServerModule := TAuthServerModule.Create(Self);
    AuthServerModule.StartAuthServer(ServerConfig.url, AUTH_MODEL);

    ApiServerModule := TApiServerModule.Create(Self);
    ApiServerModule.StartApiServer(ServerConfig.url, API_MODEL);

    AppServerModule := TAppServerModule.Create(Self);
    AppServerModule.StartAppServer(ServerConfig.url);

    FWebSocketManager := TWebSocketManager.Create;
    FWebSocketManager.Start;
    Logger.Log(1, 'WebSocket server started on port 8091');
  except
    on E: Exception do
      Logger.Log(2, 'Failed to start server modules: ' + E.Message);
  end;
end;


end.

