unit _FileTypes;

interface

uses
  TypeDefs, _TreeElement, Classes, Forms, _DataTypes;


type
  TRawCache = record
    DatOffset: Integer;
    RawStream: TMemoryStream;
  end;

  TResource = class(TTreeElement)
    protected
      FFileInfo: TFileInfo;
      FFileStream: TMemoryStream;
      FRawCaches: array of TRawCache;

      FCached: Boolean;
      FChanged: Boolean;
      FReplaced: Boolean;

      FDataFields: TBlock;

      FEditor: TFrame;
      FOpened: Boolean;

      function GetChildCount: Integer; override;
      function GetChild(ID: Integer): TTreeElement; override;
      function GetCaption: String; override;
      function GetType: String; override;
      function GetEditor: TFrame;
      function GetFieldByOffset(Offset: Integer): TDataField;
      function GetRawCacheID(Offset: Integer): Integer;
      procedure SetOpened(Opened: Boolean); virtual;
    published
    public
      constructor Create(ConnectionID, FileID: Integer); virtual;
      procedure Free;

      procedure InitDataFields; virtual;
      procedure InitEditor; virtual;

      procedure ReCreateFile(fs: TStream);

      procedure CacheFile;
      procedure CacheRawFile(Offset: Integer);
      procedure CacheAllRawFiles;
      procedure DiscardFileCache;
      procedure DiscardRawCache(Offset: Integer);
      procedure DiscardAllRawCaches;
      procedure StoreFileCache;
      procedure StoreRawCache(Offset: Integer);
      procedure StoreAllRawCaches;

      property FileStream: TMemoryStream read FFileStream;
      property FileInfo: TFileInfo read FFileInfo;

      property Cached: Boolean read FCached;
      property Changed: Boolean read FChanged write FChanged;

      property Editor: TFrame read GetEditor;
      property Opened: Boolean read FOpened write SetOpened;

      property FieldByOffset[Offset: Integer]: TDataField read GetFieldByOffset;
  end;

type
  TFileType = class of TResource;



implementation

uses
  DatLinks, RawList, ConnectionManager, Dialogs, _MetaTypes, _MetaManager,
  SysUtils;

{ TFileType }

procedure TResource.CacheFile;
begin
  if not Assigned(FFileStream) then
  begin
    FFileStream := TMemoryStream.Create;
    ConManager.Connection[FConnectionID].LoadDatFile(FFileInfo.ID, TStream(FFileStream));
  end;
end;


procedure TResource.CacheRawFile(Offset: Integer);
var
  i: Integer;
begin
  for i := 0 to High(FRawCaches) do
  begin
    if FRawCaches[i].DatOffset = Offset then
    begin
      if not Assigned(FRawCaches[i].RawStream) then
      begin
        FRawCaches[i].RawStream := TMemoryStream.Create;
        ConManager.Connection[ConnectionID].LoadRawFile(FFileInfo.ID, Offset, TStream(FRawCaches[i].RawStream));
      end;
    end;
  end;
end;

procedure TResource.CacheAllRawFiles;
var
  i: Integer;
begin
  for i := 0 to High(FRawCaches) do
    CacheRawFile(FRawCaches[i].DatOffset);
end;



procedure TResource.DiscardFileCache;
begin
  if Assigned(FFileStream) then
    FFileStream.Free;
  FFileStream := nil;
end;

procedure TResource.DiscardRawCache(Offset: Integer);
var
  i: Integer;
begin
  for i := 0 to High(FRawCaches) do
  begin
    if FRawCaches[i].DatOffset = Offset then
    begin
      if Assigned(FRawCaches[i].RawStream) then
        FRawCaches[i].RawStream.Free;
      FRawCaches[i].RawStream := nil;
    end;
  end;
end;

procedure TResource.DiscardAllRawCaches;
var
  i: Integer;
begin
  for i := 0 to High(FRawCaches) do
    DiscardRawCache(FRawCaches[i].DatOffset);
end;

procedure TResource.StoreFileCache;
begin
  Exit;
end;

procedure TResource.StoreRawCache(Offset: Integer);
begin
  Exit;
end;

procedure TResource.StoreAllRawCaches;
var
  i: Integer;
begin
  for i := 0 to High(FRawCaches) do
    StoreRawCache(FRawCaches[i].DatOffset);
end;





procedure TResource.SetOpened(Opened: Boolean);
begin
  FOpened := Opened;
end;


constructor TResource.Create(ConnectionID, FileID: Integer);
var
  rawlist: TRawDataList;
  i: Integer;
begin
  FConnectionID := ConnectionID;
  FFileInfo := ConManager.Connection[ConnectionID].GetFileInfo(FileID);

  rawlist := ConManager.Connection[ConnectionID].GetRawList(FileID);
  SetLength(FRawCaches, Length(rawlist));
  for i := 0 to High(rawlist) do
    FRawCaches[i].DatOffset := rawlist[i].SrcOffset;

  FCached := False;
  FChanged := False;

  FDataFields := nil;
  FEditor := nil;

  if not (Self is TFile_Empty) then
    InitDataFields;
end;


procedure TResource.Free;
begin
  FDataFields.Free;
end;


function TResource.GetFieldByOffset(Offset: Integer): TDataField;
begin
  Result := FDataFields.FieldByOffset[Offset];
end;


function TResource.GetRawCacheID(Offset: Integer): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := 0 to High(FRawCaches) do
    if FRawCaches[i].DatOffset = Offset then
      Result := i;
end;

function TResource.GetType: String;
begin
  Result := FFileInfo.Extension;
end;

function TResource.GetCaption: String;
begin
  Result := FFileInfo.Name;
  if Result = '' then
    Result := 'Unnamed';
  Result := Result + ' (' + IntToStr(FFileInfo.ID) + ')';
end;

function TResource.GetChild(ID: Integer): TTreeElement;
begin
  Result := FDataFields.Child[ID];
end;

function TResource.GetChildCount: Integer;
begin
  if FDataFields <> nil then
    Result := FDataFields.ChildCount
  else
    Result := 0;
end;


function TResource.GetEditor: TFrame;
begin
  if not Assigned(FEditor) then
    InitEditor;
  Result := FEditor;
end;


procedure TResource.InitDataFields;
begin
  if Assigned(FDataFields) then
    Exit;
  FFileStream := TMemoryStream.Create;
  ConManager.Connection[FConnectionID].LoadDatFile(FFileInfo.ID, TStream(FFileStream));
end;


procedure TResource.InitEditor;
begin
  Exit;
end;


//*********************************************************
//*********************************************************
//*********************************************************
procedure TResource.ReCreateFile(fs: TStream);
const
  temp0: array[0..31] of Byte =
    ($AD,$DE,$AD,$DE,$AD,$DE,$AD,$DE,
     $AD,$DE,$AD,$DE,$AD,$DE,$AD,$DE,
     $AD,$DE,$AD,$DE,$AD,$DE,$AD,$DE,
     $AD,$DE,$AD,$DE,$AD,$DE,$AD,$DE);
var
  count: Integer;
begin
  FDataFields.WriteData(fs);
  count := fs.Size mod 32;
  if count > 0 then
    fs.Write(temp0[count], 32 - count);
end;
//*********************************************************
//*********************************************************
//*********************************************************

end.
