unit MainFrame;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  XMLDoc, Xml.XMLIntf,
  LogServer;

type
  TForm1 = class(TForm)
    logsList: TListBox;
    Label1: TLabel;
    portNumberText: TEdit;
    startButton: TButton;
    stopButton: TButton;
    clearButton: TButton;
    procedure FormCreate(Sender: TObject);
    procedure startButtonClick(Sender: TObject);
    procedure stopButtonClick(Sender: TObject);
    procedure clearButtonClick(Sender: TObject);
  private
    { Private declarations }
    var serverRunning: Boolean;
    procedure updateServerRunningStatus;
    var logServer: LogServer.TLogServer;
    procedure OnMessage(msg:PAnsiChar; msg_len:NativeUInt; reply:PAnsiChar; var reply_len:NativeUInt);
    class function GetXmlValueStr(xml: IXMLNode; tag: string): string;
    class function GetXmlValueInt(xml: IXMLNode; tag: string; def_val: Integer): Integer;
    class function GetXmlValueLong(xml: IXMLNode; tag: string; def_val: Int64): Int64;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.clearButtonClick(Sender: TObject);
begin
  logsList.Clear;
end;

procedure TForm1.FormCreate(Sender: TObject);
var x : IXMLDocument;
begin
  serverRunning := False;
  updateServerRunningStatus;

  logServer := TLogServer.Create;
  logServer.OnMessage := OnMessage;
end;

procedure TForm1.startButtonClick(Sender: TObject);
begin
  if logServer.Start(StrToInt(portNumberText.Text), false) then
  begin
    serverRunning := true;
    updateServerRunningStatus;
  end;
end;

procedure TForm1.stopButtonClick(Sender: TObject);
begin
  logServer.Stop;
  serverRunning := false;
  updateServerRunningStatus;
end;

procedure TForm1.updateServerRunningStatus;
begin
  startButton.Enabled := not serverRunning;
  stopButton.Enabled := serverRunning;
  portNumberText.ReadOnly := serverRunning;
end;

procedure TForm1.OnMessage(msg:PAnsiChar; msg_len:NativeUInt; reply:PAnsiChar; var reply_len:NativeUInt);
var
  msgXmlDoc : IXmlDocument;
  msgXml : IXMLNode;
  termType, serial, eventType, dispMessage : string;
  termID, transID : Integer;
  year, month, day, hour, minute, second : Integer;

	attendStat, verifMode, apStat, photo, action, alarmType : string;
	userID, adminID : Int64;
	actionStat, doorID, jobCode : Integer;

  msgReply: AnsiString;
begin
  {Parse XML}
  msgXmlDoc := XMLDoc.LoadXMLData(msg);
  msgXml := msgXmlDoc.ChildNodes.FindNode('Message');
  if msgXml = nil then
  begin
    reply_len := 0;
    exit;
  end;

	termType := GetXmlValueStr(msgXml, 'TerminalType');
	termID := GetXmlValueInt(msgXml, 'TerminalID', -1);
	serial := GetXmlValueStr(msgXml, 'DeviceSerialNo');
	transID := GetXmlValueInt(msgXml, 'TransID', -1);
	eventType := GetXmlValueStr(msgXml, 'Event');

  {Build display string}
  dispMessage := '[' + termType + ':';

  // Terminal ID
  if (termID <> -1) then
    dispMessage := dispMessage + IntToStr(termID);

  // Serial Number
  if (serial <> '') then
    dispMessage := dispMessage + ' SN=' + serial + '] '
  else
    dispMessage := dispMessage + '] ';

  // Event Type
  if (eventType <> '') then
    dispMessage := dispMessage + eventType;

	msgReply := '<?xml version="1.0"?><Message>';
	if eventType = 'TimeLog' then
  begin
    // Date and time of log
    year := GetXmlValueInt(msgXml, 'Year', -1);
    month := GetXmlValueInt(msgXml, 'Month', -1);
    day := GetXmlValueInt(msgXml, 'Day', -1);
    hour := GetXmlValueInt(msgXml, 'Hour', -1);
    minute := GetXmlValueInt(msgXml, 'Minute', -1);
    second := GetXmlValueInt(msgXml, 'Second', -1);

    userID := GetXmlValueLong(msgXml, 'UserID', -1);
    doorID := GetXmlValueInt(msgXml, 'DoorID', -1);
    attendStat := GetXmlValueStr(msgXml, 'AttendStat');
    verifMode := GetXmlValueStr(msgXml, 'VerifMode');
    jobCode := GetXmlValueInt(msgXml, 'JobCode', -1);
    apStat := GetXmlValueStr(msgXml, 'APStat');
    photo := GetXmlValueStr(msgXml, 'Photo');

    if (transID <> -1) then
      dispMessage := dispMessage + '(' + IntToStr(transID) + ') ';
    if (year <> -1) and (month <> -1) and (day <> -1) and
        (hour <> -1) and (minute <> -1) and (second <> -1) then
      dispMessage := dispMessage + ' AT ' + IntToStr(year) + '/'
        + IntToStr(month) + '/' + IntToStr(day) + ' '
        + IntToStr(hour) + ':' + IntToStr(minute) + ':'
        + IntToStr(second) + ', ';
    if (userID <> -1) then
      dispMessage := dispMessage + 'UserID=' + IntToStr(userID) + ', ';
    if (doorID <> -1) then
      dispMessage := dispMessage + 'DoorID=' + IntToStr(doorID) + ', ';
    if (attendStat <> '') then
      dispMessage := dispMessage + 'AttendStat=' + attendStat + ', ';
    if (verifMode <> '') then
      dispMessage := dispMessage + 'VerifMode=' + verifMode + ', ';
    if (jobCode <> -1) then
      dispMessage := dispMessage + 'JobCode=' + IntToStr(jobCode) + ', ';
    if (apStat <> '') then
      dispMessage := dispMessage + 'APStatus=' + apStat + ', ';
    if (photo <> '') then
      dispMessage := dispMessage + 'PhotoTaken=' + photo;

    // Concatenate a message to send back
    msgReply := msgReply + '<Request>UploadedLog</Request><TransID>'
      + IntToStr(transID) + '</TransID>';
  end
  else if eventType = 'AdminLog' then
  begin
    // Date and time of log
    year := GetXmlValueInt(msgXml, 'Year', -1);
    month := GetXmlValueInt(msgXml, 'Month', -1);
    day := GetXmlValueInt(msgXml, 'Day', -1);
    hour := GetXmlValueInt(msgXml, 'Hour', -1);
    minute := GetXmlValueInt(msgXml, 'Minute', -1);
    second := GetXmlValueInt(msgXml, 'Second', -1);

    adminID := GetXmlValueLong(msgXml, 'AdminID', -1);
    userID := GetXmlValueLong(msgXml, 'UserID', -1);
    action := GetXmlValueStr(msgXml, 'Action');
    actionStat := GetXmlValueInt(msgXml, 'Stat', -1);

    if (transID <> -1) then
      dispMessage := dispMessage + '(' + IntToStr(transID) + ') ';
    if (year <> -1) and (month <> -1) and (day <> -1) and
        (hour <> -1) and (minute <> -1) and (second <> -1) then
      dispMessage := dispMessage + ' AT ' + IntToStr(year) + '/'
        + IntToStr(month) + '/' + IntToStr(day) + ' '
        + IntToStr(hour) + ':' + IntToStr(minute) + ':'
        + IntToStr(second) + ', ';
    if (adminID <> -1) then
      dispMessage := dispMessage + 'AdminID=' + IntToStr(adminID) + ', ';
    if (userID <> -1) then
      dispMessage := dispMessage + 'UserID=' + IntToStr(userID) + ', ';
    if (action <> '') then
      dispMessage := dispMessage + 'Action=' + action + ', ';
    if (actionStat <> -1) then
      dispMessage := dispMessage + 'Status=' + IntToStr(actionStat);

    // Concatenate a message to send back
    msgReply := msgReply + '<Request>UploadedLog</Request><TransID>' +
      IntToStr(transID) + '</TransID>';
  end
  else if eventType = 'Alarm' then
  begin
    // Date and time of log
    year := GetXmlValueInt(msgXml, 'Year', -1);
    month := GetXmlValueInt(msgXml, 'Month', -1);
    day := GetXmlValueInt(msgXml, 'Day', -1);
    hour := GetXmlValueInt(msgXml, 'Hour', -1);
    minute := GetXmlValueInt(msgXml, 'Minute', -1);
    second := GetXmlValueInt(msgXml, 'Second', -1);

    userID := GetXmlValueLong(msgXml, 'UserID', -1);
    doorID := GetXmlValueInt(msgXml, 'DoorID', -1);
    alarmType := GetXmlValueStr(msgXml, 'Type');

    if (transID <> -1) then
      dispMessage := dispMessage + '(' + IntToStr(transID) + ') ';
    if (year <> -1) and (month <> -1) and (day <> -1) and
        (hour <> -1) and (minute <> -1) and (second <> -1) then
      dispMessage := dispMessage + ' AT ' + IntToStr(year) + '/'
        + IntToStr(month) + '/' + IntToStr(day) + ' '
        + IntToStr(hour) + ':' + IntToStr(minute) + ':'
        + IntToStr(second) + ', ';
    if (userID <> -1) then
      dispMessage := dispMessage + 'UserID=' + IntToStr(userID) + ', ';
    if (doorID <> -1) then
      dispMessage := dispMessage + 'DoorID=' + IntToStr(doorID) + ', ';
    if (alarmType <> '') then
      dispMessage := dispMessage + 'Type=' + alarmType;

    // Concatenate a message to send back
    msgReply := msgReply + '<Request>UploadedLog</Request><TransID>' +
      IntToStr(transID) + '</TransID>';
  end
  else if eventType = 'KeepAlive' then
  begin
    msgReply := msgReply + '<Request>KeptAlive</Request><TransID>' +
      IntToStr(transID) + '</TransID>';
  end;

  logsList.AddItem(string(dispMessage), nil);

  msgReply := msgReply + '</Message>';

  if Length(msgReply) > reply_len then
  begin
    reply_len := 0;
    exit;
  end;

  reply_len := Length(msgReply);
  CopyMemory(reply, PAnsiChar(msgReply), reply_len);
end;

class function TForm1.GetXmlValueStr(xml: IXMLNode; tag: string): string;
var
  node: IXMLNode;
begin
  node := xml.ChildNodes.FindNode(tag);
  if node = nil then
    Result := ''
  else
    Result := node.Text;
end;

class function TForm1.GetXmlValueInt(xml: IXMLNode; tag: string; def_val: Integer): Integer;
var
  node: IXMLNode;
begin
  node := xml.ChildNodes.FindNode(tag);
  if node = nil then
    Result := def_val
  else
    Result := StrToIntDef(node.Text, def_val);
end;

class function TForm1.GetXmlValueLong(xml: IXMLNode; tag: string; def_val: Int64): Int64;
var
  node: IXMLNode;
begin
  node := xml.ChildNodes.FindNode(tag);
  if node = nil then
    Result := def_val
  else
    Result := StrToInt64Def(node.Text, def_val);
end;

end.
