unit _FileTypes;

interface

uses
  TypeDefs, _TreeElement, Classes, Forms, _DataTypes;


type
  TFile = class(TTreeElement)
    protected
      FFileInfo: TFileInfo;
      FFileStream: TMemoryStream;
      FRawCaches: array of TMemoryStream;

      FCached: Boolean;
      FChanged: 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;
      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);

      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;


  TFileType = class of TFile;



implementation

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

{ TFileType }

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


procedure TFile.CacheRawFile(Offset: Integer);
var
  rawlist: TRawDataList;
  i: Integer;
begin
  rawlist := ConManager.Connection[ConnectionID].GetRawList(FFileInfo.ID);
  if Length(rawlist) > 0 then
  begin
    for i := 0 to High(rawlist) do
    begin
      if rawlist[i].SrcOffset = Offset then
      begin
        if not Assigned(FRawCaches[i]) then
        begin
          FRawCaches[i] := TMemoryStream.Create;
          ConManager.Connection[ConnectionID].LoadRawFile(FFileInfo.ID, Offset, TStream(FRawCaches[i]));
        end;
      end;
    end;
  end;
end;


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


constructor TFile.Create(ConnectionID, FileID: Integer);
begin
  FConnectionID := ConnectionID;
  FFileInfo := ConManager.Connection[ConnectionID].GetFileInfo(FileID);

  SetLength(FRawCaches, Length(ConManager.Connection[ConnectionID].GetRawList(FileID)));

  FCached := False;
  FChanged := False;

  FDataFields := nil;
  FEditor := nil;

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


procedure TFile.Free;
begin
  FDataFields.Free;
end;


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


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

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

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

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


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


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


procedure TFile.InitEditor;
begin
  Exit;
end;


//*********************************************************
//*********************************************************
//*********************************************************
procedure TFile.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.
