unit uoddface_table_nid;

{$mode delphi}

interface

uses
  Classes, SysUtils, ubtree;

type

    { TRec_key }

    TRec_key = class
      procedure WriteToBin( f: TStream ); virtual; abstract;
      constructor LoadFromBin( f: TStream ); virtual; abstract;
      function KeyCompare( a, b : TRec_key ): integer; virtual; abstract;
      procedure CopyRec( a: TRec_Key );virtual; abstract;
    end;

    TypeOfRec_key = class of TRec_key;


    { TRec_nid }

    TRec_nid = class( TRec_key )
      nid: integer;
      constructor Create( nid: integer );
      destructor destroy; override;
      procedure WriteToBin( f: TStream ); override;
      constructor LoadFromBin( f: TStream ); override;
      function KeyCompare( a, b : TRec_key ): integer; override;
      procedure CopyRec( a: TRec_Key ); override;
    end;


      { TOddFace_Individuos }

  { TTable_key }
  TTable_key = class
    version: integer;
    recs: TBTree;
    recClassID: TypeOfRec_key;
    constructor Create( recClassId: TypeOfRec_key );
    function Compare( a, b: TItemBTree ): integer; virtual;
    procedure ReadHeader( f: TStream ); virtual;
    procedure WriteHeader( f: TStream ); virtual;
    procedure ReadRecs( f: TStream ); virtual;
    procedure WriteRecs( f: TStream ); virtual;
    procedure ReadFooter( f: TStream ); virtual;
    procedure WriteFooter( f: TStream ); virtual;

    procedure WriteToBin(f: TStream); virtual;

    constructor LoadFromBin( f: TStream; recClassId: TypeOfRec_key );
    // si lo logra insertar (no existía ni el nid ni el ADN) retorna el Nodo
    // si ya existía el individuo, retorna nil y no lo inserta
    function AddRec( aRec: TRec_key ): TNodoBtree; virtual;
    function LocateByKey( aRec: TRec_key ): TRec_key; virtual;
    function UpdateRec( aRec: TRec_key): boolean; virtual;
    function DeleteRec( aRec: TRec_key): boolean; virtual;
    destructor destroy; override;
  end;

  { TTable_nid }
  TTable_nid = class( TTable_key )
    nextNid: integer;
    function getNextNid: integer;
    function locateByNID( nid: integer ): TRec_nid;
    constructor Create(recClassId: TypeOfRec_key);
    procedure ReadHeader( f: TStream ); override;
    procedure WriteHeader( f: TStream ); override;
  end;




implementation

{ TTable_key }

constructor TTable_key.Create(recClassId: TypeOfRec_key);
begin
  inherited Create;
  recs:= TBTree.Create( false, Compare );
  self.recClassID:= recClassId;
end;

function TTable_key.Compare(a, b: TItemBTree): integer;
begin
  result:= TRec_key(a).KeyCompare( a, b );
end;

procedure TTable_key.ReadHeader(f: TStream);
begin

end;

procedure TTable_key.WriteHeader(f: TStream);
begin

end;

procedure TTable_key.ReadRecs(f: TStream);
var
  k, n: integer;
  aIndividuo: TRec_key;
  rescod: integer;
begin
  f.Read( n, sizeOf( n ) );
  for k:= 1 to n do
  begin
    aIndividuo:= recClassID.LoadFromBin( f );
    recs.insert( aIndividuo, rescod );
  end;
end;

procedure TTable_key.WriteRecs(f: TStream);
var
  k, n: integer;
  aIndividuo: TRec_nid;
  cursor: TCursorBTree;
begin
  n:= recs.count;
  f.Write( n, sizeOf( n ) );
  cursor:= TCursorBTree.Create( recs );
  aIndividuo:= cursor.FirstItem;
  while not cursor.EndOfItems do
  begin
    aIndividuo.WriteToBin( f );
    aIndividuo:= cursor.NextItem;
  end;
  cursor.Free;
end;

procedure TTable_key.ReadFooter(f: TStream);
begin


end;

procedure TTable_key.WriteFooter(f: TStream);
begin

end;




constructor TTable_key.LoadFromBin(f: TStream; recClassId: TypeOfRec_key);
begin
  inherited Create;
  recs:= TBTree.Create( false, Compare );
  f.Read( version, sizeOf( version ) );
  readHeader( f );
  readRecs( f );
  readFooter( f );
end;

procedure TTable_key.WriteToBin(f: TStream);
begin
  f.Write( version, sizeOf( version ) );
  writeHeader( f );
  writeRecs( f );
  writeFooter( f );
end;

function TTable_key.AddRec(aRec: TRec_key): TNodoBtree;
var
  ResCod: integer;
begin
  result:= recs.insert( aRec, ResCod );
end;

function TTable_key.LocateByKey(aRec: TRec_key): TRec_key;
var
  nodo: TNodoBtree;
begin
  nodo:= recs.locate_key( aRec );
  if nodo <> nil then
    result:= nodo.item
  else
    result:= nil;
end;


function TTable_key.UpdateRec( aRec: TRec_key ): boolean;
var
  bRec: TRec_key;
begin
  bRec:= locateByKey( aRec );
  if ( bRec <> nil ) then
  begin
    if ( bRec <> aRec ) then
        bRec.CopyRec( aRec );
  end
  else
    raise Exception.Create( 'Error, TTable_key.UpdateRec .. key no encontrada!' );
end;

function TTable_key.DeleteRec(aRec: TRec_key ): boolean;
var
  nodo: TNodoBtree;
begin
  nodo:= recs.locate_key( aRec );
  if nodo <> nil then
    recs.Delete( nodo );
end;



destructor TTable_key.destroy;
begin
  inherited destroy;
end;



{ TTable_nid }

constructor TTable_nid.Create(recClassId: TypeOfRec_key);
begin
  Inherited Create( recClassId );
  nextNid:= 1;
end;

procedure TTable_nid.ReadHeader(f: TStream);
begin
  inherited ReadHeader(f);
  f.Read( nextNid, sizeOf( nextNid ) );
end;

procedure TTable_nid.WriteHeader(f: TStream);
begin
  inherited WriteHeader(f);
  f.Write( nextNid, sizeOf( nextNid ) );
end;




function TTable_nid.getNextNid: integer;
begin
  result:= nextNid;
  inc( nextNid );
end;





function TTable_nid.locateByNID(nid: integer): TRec_nid;
var
  a: TRec_nid;
  nodo: TNodoBtree;
begin
  a:= TRec_nid.Create( nid );
  nodo:= recs.locate_key( a );
  a.free;
  if nodo <> nil then
    result:= nodo.item
  else
    result:= nil;
end;






{ TRec_nid }

constructor TRec_nid.Create(nid: integer);
begin
  inherited Create;
  self.nid:= nid;
end;

destructor TRec_nid.destroy;
begin
  inherited destroy;
end;

procedure TRec_nid.WriteToBin(f: TStream);
begin
   f.Write( nid, SizeOf( nid ));
end;

constructor TRec_nid.LoadFromBin(f: TStream);
begin
   inherited Create;
   f.Read( nid, SizeOf( nid ));
end;


function TRec_nid.KeyCompare(a, b: TRec_key ): integer;
var
  dif: Int64;
begin
  dif := (a as TRec_nid).nid - (b as TRec_nid).nid;
  if dif < 0 then
    Result := -1
  else if dif = 0 then
    Result := 0
  else
    Result := 1;
end;

procedure TRec_nid.CopyRec(a: TRec_Key);
begin
  nid:= (a as TRec_nid).nid;
end;


end.

