{$MODE OBJFPC}
{$MODESWITCH AUTODEREF}
uses
  dtypes,
  dlog,
  dlog_stderr,
  dstrnum,
  dvector2i,
  dvector2f,
  dvector4f,
  drect2i,
  dstream,
  dstreamfile,
  dtexture2d,
  dtga_reader;

type
TTgaDumper = object
private
  TgaReader: PTgaReader;
public
  procedure Init(Reader: PTgaReader);
  procedure Done;
  procedure Dump;
end;

procedure TTgaDumper.Init(Reader: PTgaReader);
begin
  TgaReader := Reader;
end;

procedure TTgaDumper.Done;
begin
end;

procedure TTgaDumper.Dump;
var
  A: array of Byte;
  Curr: LongInt;
  B: Byte;
  Pixel: array[0..3] of Byte;
  S: AnsiString;
  BytesPerPixel: LongInt;
  I: LongInt;
begin
  Log('Tga: IdLength=' + IntToStr(TgaReader.Header.IdLength));
  Log('Tga: ColormapType=' + IntToStr(TgaReader.Header.ColormapType));
  case TgaReader.Header.ImageType of
    TGA_IMAGE_TYPE_NO: Log('Tga: ImageType=No data included');
    TGA_IMAGE_TYPE_COLOR_MAPPED: Log('Tga: ImageType=ColorMapped');
    TGA_IMAGE_TYPE_RGB: Log('Tga: ImageType=RGB');
    TGA_IMAGE_TYPE_BLACK_WHITE: Log('Tga: ImageType=BlackWhite');
    TGA_IMAGE_TYPE_RUNLENGTH_COLOR_MAPPED:
       Log('Tga: ImageType=RLE-ColorMapped');
    TGA_IMAGE_TYPE_RUNLENGTH_RGB:
       Log('Tga: ImageType=RLE-RGB');
    TGA_IMAGE_TYPE_COMPRESSED_BLACK_WHITE:
       Log('Tga: ImageType=CompressedBlackWhite');
    TGA_IMAGE_TYPE_COMPRESSED_COLOR_MAPPED:
       Log('Tga: ImageType=CompressedColorMapped');
    TGA_IMAGE_TYPE_QUADTREE_COLOR_MAPPED:
       Log('Tga: ImageType=QuadTreeColorMapped');
    else
       Log('Tga ERROR: ImageType has unexpected value=' + IntToStr(TgaReader.Header.ImageType));
  end;
  Log('Tga: ColormapIndex=' + IntToStr(TgaReader.Header.ColormapIndex));
  Log('Tga: ColormapLength=' + IntToStr(TgaReader.Header.ColormapLength));
  Log('Tga: ColormapEntrySize=' + IntToStr(TgaReader.Header.ColormapEntrySize));
  Log('Tga: XOrigin=' + IntToStr(TgaReader.Header.XOrigin));
  Log('Tga: YOrigin=' + IntToStr(TgaReader.Header.YOrigin));
  Log('Tga: Width=' + IntToStr(TgaReader.Header.Width));
  Log('Tga: Height=' + IntToStr(TgaReader.Header.Height));
  Log('Tga: PixelDepth=' + IntToStr(TgaReader.Header.PixelDepth));
  Log('Tga: ImageDesc=' + IntToStr(TgaReader.Header.ImageDesc));

  case TgaReader.Header.PixelDepth of
    16: BytesPerPixel := 2;
    24: BytesPerPixel := 3;
    32: BytesPerPixel := 4;
    else
      Log('Tga ERROR: invalid PixelDepth, must be 16, 24 or 32');
      Halt(1);
  end;

  if not TgaReader.SkipImageIdentificationField then begin
    Log('Tga ERROR: cannot skip image identification field');
    Halt(1);
  end;

  // TODO Color-map

  if TgaReader.Header.ImageType = TGA_IMAGE_TYPE_RUNLENGTH_RGB then begin
    SetLength(A, TgaReader.Header.Width * TgaReader.Header.Height * BytesPerPixel);
    Curr := 0;
    while Curr < Length(A) do begin
      B := TgaReader.Stream.ReadByte;
      if (B and TGA_RLE_MASK) <> 0 then begin
        TgaReader.Stream.Read(@Pixel[0], BytesPerPixel);
        S := 'RLE: ' + IntToStr(BytesPerPixel) + 'x(';
        for I := 0 to BytesPerPixel - 1 do
          S := S + IntToStr(Pixel[I]) + ',';
        S := S + ')';
        Log('Tga: ' + S);
        for I := 0 to B - TGA_RLE_MASK do begin
          Move(Pixel[0], A[Curr], BytesPerPixel);
          Inc(Curr, BytesPerPixel);
        end;
      end else begin
        S := 'RAW ' + IntToStr(B + 1) + ' pixels';
        Log('Tga: ' + S);
        for I := 0 to B do begin
          TgaReader.Stream.Read(@A[Curr], BytesPerPixel);
          Inc(Curr, BytesPerPixel);
        end;
      end;
    end;
  end;
end;

var
  TgaReader: TTgaReader;
  TgaDumper: TTgaDumper;
  Name: AnsiString;

begin
  Name := 'rle24.tga';
  if ParamStr(1) <> '' then
    Name := ParamStr(1);
  Log('Tag: reading from ' + Name);
  TgaReader.Init(Name);
  if not TgaReader.Valid then begin
    Log('TgaReader FAILED: Bad tga header');
    TgaReader.Done;
    Halt(1);
  end;
  TgaDumper.Init(@TgaReader);
  TgaDumper.Dump;
  TgaDumper.Done;
  TgaReader.Done;
end.
