unit fwResource;

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}

interface

uses SysUtils,

     ContNrs,
     fwObject,
	   fwObjectlist,
     fwCustomEngine;

type
  TfwResourceType       = (
                            rtUnknown,
                            rtImage,
                            rtFont,
                            rtSound,
                            rtMusic
                          );
                          
  TfwOnLoadResource     = function (const aName, aFilename : String; aParam : Cardinal) : TfwCEObject of Object;

  TfwResourceItem       = class(TfwCEObject)
  protected
    fResourceType         : TfwResourceType;
    fLoaded               : Boolean;
    fName                 : String;
    fFilename             : String;
    fParam                : Cardinal;
    fItem                 : TObject;
    fOnLoad               : TfwOnLoadResource;
  public
    constructor Create(const aName : String; aItem : TObject); overload;
    constructor Create(aType : TfwResourceType; const aName, aFilename : String; aParam : Cardinal; aLoader : TfwOnLoadResource = nil); overload;
    destructor Destroy; override;

    function Load() : Boolean; virtual;
    function Unload() : Boolean; virtual; 

    property Filename : String read fFilename;
    property Loaded : Boolean read fLoaded;
    property Name : String read fName;
    property Param : Cardinal read fParam;
    property ResourceType : TfwResourceType read fResourceType;
  end;

  TResourceIdleEvent    = procedure (aPosition, aMaxResources : Integer) of Object;

  TfwResourceManager    = class(TfwObject)
  protected
    fList                 : TfwObjectlist;
    function GetItem(aIndex : Integer) : TfwResourceItem;
    function GetCount : Integer;
  public
    constructor Create();
    destructor Destroy; override;

    function  Add(aItem : TObject) : Integer; overload;
    function  Add(const aName : String; aItem : TObject) : Integer; overload;
    function  Add(aType : TfwResourceType; const aName, aFilename : String; aParam : Cardinal; aLoader : TfwOnLoadResource = nil) : Integer; overload;
    procedure Load(aIdle :  TResourceIdleEvent = nil);

    function IndexOf(AObject : TfwResourceItem) : Integer; overload;
    function IndexOf(const aName : String) : TfwResourceItem; overload;

    property Items[aIndex : Integer] : TfwResourceItem read GetItem; default;
    property Count : Integer read GetCount;
  end;

implementation

// TfwResource -----------------------------------------------------------
constructor TfwResourceItem.Create(const aName : String; aItem : TObject);
begin
  inherited Create;

  fResourceType := rtUnknown;
  fParam        := 0;
  fOnLoad       := nil;
  fLoaded       := True;
  fName         := aName;
  fItem         := aItem;
end;

constructor TfwResourceItem.Create(aType : TfwResourceType; const aName, aFilename : String; aParam : Cardinal; aLoader : TfwOnLoadResource = nil);
begin
  inherited Create;

  fResourceType := aType;
  fParam        := aParam;
  fOnLoad       := aLoader;
  fLoaded       := False;
  fName         := aName;
  fItem         := nil;
end;

destructor TfwResourceItem.Destroy;
begin
  if Assigned(fItem) then begin
    FreeAndNil(fItem);
    fLoaded := False;
  end;

  inherited Destroy;
end;

function TfwResourceItem.Load() : Boolean;
begin
  Result := True;
  if not fLoaded then begin
    if Assigned(fOnLoad) then begin
// XXX      Result := LoadFromFile(Name, Filename);
      Result := False;
    end;
  end;
end;

function TfwResourceItem.Unload() : Boolean;
begin
  Result := False;
end;

// TfwResourceManager ----------------------------------------------------
function TfwResourceManager.GetItem(aIndex : Integer) : TfwResourceItem;
begin
  Result := (fList[aIndex] as TfwResourceItem);
end;

function TfwResourceManager.GetCount : Integer;
begin
  Result := fList.Count;
end;

constructor TfwResourceManager.Create();
begin
  inherited Create;

  fList := TfwObjectlist.Create(True);
end;

destructor TfwResourceManager.Destroy;
begin
  if fList.OwnsObjects then begin
    while (fList.Count > 0) do begin
      fList.Delete(Pred(fList.Count));
    end;
  end;

  inherited Destroy;
end;

function TfwResourceManager.Add(aItem : TObject) : Integer;
var
  sName            : String;
begin
  sName := '__' + aItem.ClassName + '__' + IntToStr(Count + 1);
  Add(sName, aItem); 
end;

function TfwResourceManager.Add(const aName : String; aItem : TObject) : Integer;
var
  RItem            : TfwResourceItem;
begin
  Result := -1;
  RItem  := TfwResourceItem.Create(aName, aItem);
  if (Result < 0) then begin
    Result := fList.Add(RItem);
  end;
end;

function TfwResourceManager.Add(aType : TfwResourceType; const aName, aFilename : String; aParam : Cardinal; aLoader : TfwOnLoadResource = nil) : Integer;
var
  RItem            : TfwResourceItem;
begin
  Result := -1;
  RItem  := TfwResourceItem.Create(aType, aName, aFilename, aParam, aLoader);
  if (Result < 0) then begin
    Result := fList.Add(RItem);
  end;
end;

procedure TfwResourceManager.Load(aIdle :  TResourceIdleEvent = nil);
var
  iLoop            : Integer;
begin
  for iLoop := 0 to Pred(Count) do begin
    Items[iLoop].Load;
    if Assigned(aIdle) then begin
      aIdle(iLoop + 1, Count);
    end;
  end;
end;

function TfwResourceManager.IndexOf(AObject : TfwResourceItem) : Integer;
begin
  Result := (fList.IndexOf(aObject));
end;

function TfwResourceManager.IndexOf(const aName : String): TfwResourceItem;
var
  iLoop            : Integer;
begin
  Result := nil;
  for iLoop := 0 to Pred(fList.Count) do begin
    if SameText(aName, Items[iLoop].Name) then begin
      Result := Items[iLoop];
      Exit;
    end;
  end;
end;

end.
