unit Game.Registry;

interface
uses
  System.Generics.Collections,

  Game.Base;

type
  TGameRegistryEnumerable = class(TObject)
  public
    function GetEnumerator: TEnumerator<TCustomGameClass>;
  end;


  TGameRegistry = class(TObject)
  protected
    class var SRegisteredGames: TList<TCustomGameClass>;
    class var SEnumerable: TGameRegistryEnumerable;

    class procedure Initialize;
    class procedure Finalize;
  public
    class function RegisteredGames: TGameRegistryEnumerable;
    class function ByClassName(const AClassName: string): TCustomGameClass;

    class procedure Register(AGameClass: TCustomGameClass);
    class procedure Unregister(AGameClass: TCustomGameClass);
  end;


implementation
uses
  System.SysUtils;


{ TGameRegistry }
class procedure TGameRegistry.Initialize;
begin
  SRegisteredGames := TList<TCustomGameClass>.Create;
  SEnumerable := TGameRegistryEnumerable.Create;
end;


class procedure TGameRegistry.Finalize;
begin
  FreeAndNil(SEnumerable);
  FreeAndNil(SRegisteredGames);
end;


class function TGameRegistry.RegisteredGames: TGameRegistryEnumerable;
begin
  Result := SEnumerable;
end;


class function TGameRegistry.ByClassName(const AClassName: string): TCustomGameClass;
var
  gameClass: TCustomGameClass;

begin
  Result := nil;

  for gameClass in RegisteredGames do
    if SameText(gameClass.ClassName, AClassName) then
    begin
      Result := gameClass;
      break;
    end;
end;


class procedure TGameRegistry.Register(AGameClass: TCustomGameClass);
begin
  if not SRegisteredGames.Contains(AGameClass) then
    SRegisteredGames.Add(AGameClass);
end;

class procedure TGameRegistry.Unregister(AGameClass: TCustomGameClass);
begin
  SRegisteredGames.Remove(AGameClass);
end;


{ TGameRegistryEnumerable }
function TGameRegistryEnumerable.GetEnumerator: TEnumerator<TCustomGameClass>;
begin
  Result := TGameRegistry.SRegisteredGames.GetEnumerator;
end;

initialization
  TGameRegistry.Initialize;

finalization
  TGameRegistry.Finalize;

end.
