unit Common.Logging;

interface

uses
  Generics.Collections;

type
  ILog = interface;
  ILogAppender = interface;

//  TLogLevel = (Unknown, Trace, Debug, Text, Info, Warn, Error, Fatal);

  ILogger = interface
    ['{4D667DD2-BE11-496B-B92A-C47E03520BD6}']
    procedure Log(Msg: string); overload;
    procedure Log(Log: ILog); overload;
    procedure AddAppender(ALogAppender: ILogAppender);
    function Appenders: TArray<ILogAppender>;
  end;

  ILogAppender = interface
    ['{A3B7D6FB-C75F-4BEF-8797-907B6FDAD5D2}']
    procedure Send(Log: ILog);
  end;

  ILog = interface
    ['{8E9C6580-C099-47C0-8B1B-6D7A28EC4FA3}']
    function GetMessage: string;
  end;

  TLogger = class( TInterfacedObject, ILogger )
  strict private
    FAppenders: TList<ILogAppender>;
  public
    constructor Create; overload;
    constructor Create(ALogger: ILogger); overload;
    destructor Destroy; override;
    procedure Log(Msg: string); overload;
    procedure Log(Log: ILog); overload;
    procedure AddAppender(ALogAppender: ILogAppender);
    function Appenders: TArray<ILogAppender>;
  end;

  TLogMessage = class( TInterfacedObject, ILog )
  private
    FMsg: string;
  public
    constructor Create(AMsg: string);
    function GetMessage: string;
  end;

  function Logger: ILogger;

implementation

var
  _Logger: ILogger;

function Logger: ILogger;
begin
  Result := _Logger;
end;

{ TLogMessage }

constructor TLogMessage.Create(AMsg: string);
begin
  FMsg := AMsg;
end;

function TLogMessage.GetMessage: string;
begin
  Result := FMsg;
end;

{ TLogger }

procedure TLogger.AddAppender(ALogAppender: ILogAppender);
begin
  FAppenders.Add(ALogAppender);
end;

function TLogger.Appenders: TArray<ILogAppender>;
var
  I: integer;
begin
  SetLength(Result, FAppenders.Count);
  for I := 0 to FAppenders.Count - 1 do
    Result[I] := FAppenders[I];
end;

constructor TLogger.Create(ALogger: ILogger);
var
  Appender: ILogAppender;
begin
  FAppenders := TList<ILogAppender>.Create;
  if ALogger <> nil then
    for Appender in ALogger.Appenders do
      AddAppender(Appender);
end;

constructor TLogger.Create;
begin
  Create(nil);
end;

destructor TLogger.Destroy;
begin
  FAppenders.Free;
  inherited;
end;

procedure TLogger.Log(Log: ILog);
var
  Appender: ILogAppender;
begin
  for Appender in FAppenders do
    Appender.Send(Log);
end;

procedure TLogger.Log(Msg: string);
begin
  Log(TLogMessage.Create(Msg));
end;

initialization
  _Logger := TLogger.Create;

end.
