package lz4_test

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"
	"testing"

	"github.com/pierrec/lz4/v4"
)

func TestCompressingReader(t *testing.T) {
	goldenFiles := []string{
		"testdata/e.txt.gz",
		"testdata/gettysburg.txt.gz",
		"testdata/Mark.Twain-Tom.Sawyer.txt.gz",
		"testdata/Mark.Twain-Tom.Sawyer_long.txt.gz",
		"testdata/pg1661.txt.gz",
		"testdata/pi.txt.gz",
		"testdata/random.data.gz",
		"testdata/repeat.txt.gz",
		"testdata/issue102.data.gz",
	}

	for _, fname := range goldenFiles {
		for _, option := range []lz4.Option{
			lz4.BlockChecksumOption(true),
			lz4.SizeOption(123),
		} {
			label := fmt.Sprintf("%s/%s", fname, option)
			t.Run(label, func(t *testing.T) {
				fname := fname
				option := option
				t.Parallel()

				raw, err := os.ReadFile(fname)
				if err != nil {
					t.Fatal(err)
				}
				r := io.NopCloser(bytes.NewReader(raw))

				// Compress.
				zcomp := lz4.NewCompressingReader(r)
				if err := zcomp.Apply(option, lz4.CompressionLevelOption(lz4.Level1)); err != nil {
					t.Fatal(err)
				}

				zout, err := io.ReadAll(zcomp)
				if err != nil {
					t.Fatal(err)
				}

				// Uncompress.
				zr := lz4.NewReader(bytes.NewReader(zout))
				out, err := io.ReadAll(zr)
				if err != nil {
					t.Fatal(err)
				}

				// The uncompressed data must be the same as the initial input.
				if got, want := len(out), len(raw); got != want {
					t.Errorf("invalid sizes: got %d; want %d", got, want)
				}

				if !bytes.Equal(out, raw) {
					t.Fatal("uncompressed data does not match original")
				}

				if strings.Contains(option.String(), "SizeOption") {
					if got, want := zr.Size(), 123; got != want {
						t.Errorf("invalid sizes: got %d; want %d", got, want)
					}
				}
			})
		}
	}
}
