unit History;

interface

uses
  Classes, SysUtils, RegistryEx, Generics.Collections, Board;

type
  { THistoryMove }

  THistoryMove = class
    Direction: TMoveDirection;
    NewItemPos: TPoint;
    NewItemValue: Integer;
    procedure SaveToRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
    procedure LoadFromRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
    procedure Assign(Source: THistoryMove);
  end;

  { THistoryMoves }

  THistoryMoves = class(TObjectList<THistoryMove>)
    procedure SaveToRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
    procedure LoadFromRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
    procedure Assign(Source: THistoryMoves);
  end;

  TTilePosValue = record
    Pos: TPoint;
    Value: Integer;
    Unmergable: Boolean;
  end;

  { THistory }

  THistory = class
    Moves: THistoryMoves;
    InitialTiles: array of TTilePosValue;
    DisabledTiles: array of TPoint;
    procedure Clear;
    constructor Create;
    destructor Destroy; override;
    procedure SaveToRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
    procedure LoadFromRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
    procedure Assign(Source: THistory);
  end;


implementation

{ THistoryMoves }

procedure THistoryMoves.SaveToRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
var
  I: Integer;
begin
  with Reg do begin
    CurrentContext := RegContext;
    WriteInteger('Count', Count);
    for I := 0 to Count - 1 do begin
      Items[I].SaveToRegistry(Reg, TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\' + IntToStr(I)));
    end;
  end;
end;

procedure THistoryMoves.LoadFromRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
var
  I: Integer;
begin
  with Reg do begin
    CurrentContext := RegContext;
    Count := ReadIntegerWithDefault('Count', 0);
    for I := 0 to Count - 1 do begin
      Items[I] := THistoryMove.Create;
      THistoryMove(Items[I]).LoadFromRegistry(Reg, TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\' + IntToStr(I)));
    end;
  end;
end;

procedure THistoryMoves.Assign(Source: THistoryMoves);
var
  I: Integer;
  NewMove: THistoryMove;
begin
  Clear;
  for I := 0 to Source.Count - 1 do begin
    NewMove := THistoryMove.Create;
    NewMove.Assign(Source[I]);
    Add(NewMove);
  end;
end;

{ THistoryMove }

procedure THistoryMove.SaveToRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
begin
  with Reg do begin
    CurrentContext := RegContext;
    WriteInteger('Direction', Integer(Direction));
    WriteInteger('NewItemPosX', NewItemPos.X);
    WriteInteger('NewItemPosY', NewItemPos.Y);
    WriteInteger('NewItemValue', NewItemValue);
  end;
end;

procedure THistoryMove.LoadFromRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
begin
  with Reg do begin
    CurrentContext := RegContext;
    Direction := TMoveDirection(ReadIntegerWithDefault('Direction', Integer(drNone)));
    NewItemPos := Point(ReadIntegerWithDefault('NewItemPosX', 0),
      ReadIntegerWithDefault('NewItemPosY', 0));
    NewItemValue := ReadIntegerWithDefault('NewItemValue', 0);
  end;
end;

procedure THistoryMove.Assign(Source: THistoryMove);
begin
  Direction := Source.Direction;
  NewItemPos := Source.NewItemPos;
  NewItemValue := Source.NewItemValue;
end;

procedure THistory.Clear;
begin
  Moves.Clear;
  SetLength(InitialTiles, 0);
end;

constructor THistory.Create;
begin
  Moves := THistoryMoves.Create;
end;

destructor THistory.Destroy;
begin
  FreeAndNil(Moves);
  inherited;
end;

procedure THistory.SaveToRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
var
  I: Integer;
begin
  with Reg do begin
    CurrentContext := TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\InitialTilesPos');
    WriteInteger('Count', Length(InitialTiles));
    for I := 0 to Length(InitialTiles) - 1 do begin
      WriteInteger('X' + IntToStr(I), InitialTiles[I].Pos.X);
      WriteInteger('Y' + IntToStr(I), InitialTiles[I].Pos.Y);
      WriteInteger('Value' + IntToStr(I), InitialTiles[I].Value);
      WriteBool('Unmergable' + IntToStr(I), InitialTiles[I].Unmergable);
    end;

    CurrentContext := TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\DisabledTilesPos');
    for I := 0 to Length(DisabledTiles) - 1 do begin
      WriteInteger('X' + IntToStr(I), DisabledTiles[I].X);
      WriteInteger('Y' + IntToStr(I), DisabledTiles[I].Y);
    end;

    Moves.SaveToRegistry(Reg, RegContext);
  end;
end;

procedure THistory.LoadFromRegistry(Reg: TRegistryEx; RegContext: TRegistryContext);
var
  I: Integer;
begin
  with Reg do begin
    CurrentContext := TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\InitialTilesPos');
    SetLength(InitialTiles, ReadIntegerWithDefault('Count', 0));
    for I := 0 to Length(InitialTiles) - 1 do begin
      InitialTiles[I].Pos := Point(ReadIntegerWithDefault('X' + IntToStr(I), 0),
        ReadIntegerWithDefault('Y' + IntToStr(I), 0));
      InitialTiles[I].Value := ReadIntegerWithDefault('Value' + IntToStr(I), 0);
      InitialTiles[I].Unmergable := ReadBoolWithDefault('Unmergable' + IntToStr(I), False);
    end;

    CurrentContext := TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\DisabledTilesPos');
    SetLength(DisabledTiles, ReadIntegerWithDefault('Count', 0));
    for I := 0 to Length(DisabledTiles) - 1 do begin
      DisabledTiles[I] := Point(ReadIntegerWithDefault('X' + IntToStr(I), 0),
        ReadIntegerWithDefault('Y' + IntToStr(I), 0));
    end;

    Moves.LoadFromRegistry(Reg, RegContext);
  end;
end;

procedure THistory.Assign(Source: THistory);
var
  I: Integer;
begin
  SetLength(InitialTiles, Length(Source.InitialTiles));
  for I := 0 to Length(Source.InitialTiles) - 1 do
    InitialTiles[I] := Source.InitialTiles[I];
  Moves.Assign(Source.Moves);
end;

end.

