// Copyright 2019 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package flatecut

import (
	"bytes"
	"compress/flate"
	"io"
	"io/ioutil"
	"testing"

	"github.com/google/wuffs/internal/testcut"
)

func TestCut(tt *testing.T) {
	testcut.Test(tt, SmallestValidMaxEncodedLen, Cut, newReader, []string{
		"artificial/deflate-backref-crosses-blocks.deflate",
		"artificial/deflate-distance-32768.deflate",
		"romeo.txt.deflate",
		"romeo.txt.fixed-huff.deflate",
	})
}

func BenchmarkCut(b *testing.B) {
	testcut.Benchmark(b, SmallestValidMaxEncodedLen, Cut, newReader,
		"pi.txt.zlib", 2, 4, 100003)
}

func newReader(r io.Reader) (io.ReadCloser, error) {
	return flate.NewReader(r), nil
}

func decodeFlate(src []byte) string {
	dst, err := ioutil.ReadAll(flate.NewReader(bytes.NewReader(src)))
	if err != nil {
		return err.Error()
	}
	return string(dst)
}

func TestHuffmanDecode(tt *testing.T) {
	// This exercises the "ABCDEFGH" example from RFC 1951 section 3.2.2,
	// discussed in the "type huffman" doc comment.

	const src = "HEADFACE"
	codes := []string{
		'A': " 010",
		'B': " 011",
		'C': " 100",
		'D': " 101",
		'E': " 110",
		'F': "  00",
		'G': "1110",
		'H': "1111",
	}

	encoded := []byte(nil)
	encBits := uint32(0)
	encNBits := uint32(0)
	for _, s := range src {
		for _, c := range codes[s] {
			if c == ' ' {
				continue
			}

			if c == '1' {
				encBits |= 1 << encNBits
			}
			encNBits++

			if encNBits == 8 {
				encoded = append(encoded, uint8(encBits))
				encBits = 0
				encNBits = 0
			}
		}
	}
	if encNBits > 0 {
		encoded = append(encoded, uint8(encBits))
	}

	h := huffman{
		counts: [maxCodeBits + 1]uint32{
			2: 1, 3: 5, 4: 2,
		},
		symbols: [maxNumCodes]int32{
			0: 'F', 1: 'A', 2: 'B', 3: 'C', 4: 'D', 5: 'E', 6: 'G', 7: 'H',
		},
	}
	h.constructLookUpTable()

	b := &bitstream{
		bytes: encoded,
	}

	decoded := []byte(nil)
	for _ = range src {
		c := h.decode(b)
		if c < 0 {
			decoded = append(decoded, '!')
			break
		}
		decoded = append(decoded, uint8(c))
	}

	if got, want := string(decoded), src; got != want {
		tt.Fatalf("got %q, want %q", got, want)
	}
}

// A DEFLATE encoding of the first 64 bytes of the AUTHORS file in the
// repository root directory.
//
// The encoding uses a Dynamic Huffman block, but one whose H-D Huffman
// distance tree is degenerate (there's a mapping for the "0" code but no
// mapping for the "1" code) and unused.
//
// The first 25-30 bytes contain the encoded H-L and H-D Huffman trees. The
// last 30-35 bytes contain the actual payload, encoded with H-L.
//
// The high 7 bits of the final byte is unused padding.
const (
	degenerateHuffmanDec = "# This is the official list of Wuffs authors for copyright purpo"
	degenerateHuffmanEnc = "" +
		"\x05\xc0\xc1\x09\xc5\x30\x0c\x03\xd0\x55\x04\x7f\xa5\x0f\x3d\x87" +
		"\x50\xd5\x82\x80\x82\xed\x1c\xba\x7d\xdf\x0f\xff\x50\x41\x85\x8e" +
		"\x1b\x26\x35\x35\x16\x96\xaa\x61\xe2\x3a\x64\x61\x9c\x0e\x67\x81" +
		"\x4e\x4c\xef\x37\xf5\x44\x63\x9f\xdc\xfe\x00"
)

func TestReplaceHuffmanWithStored(tt *testing.T) {
	const dec = degenerateHuffmanDec
	const enc = degenerateHuffmanEnc
	if (len(dec) != 64) || (len(enc) != 59) {
		panic("inconsistent const string lengths")
	}
	if got, want := decodeFlate([]byte(enc)), dec; got != want {
		tt.Fatalf("before Cut: got %q, want %q", got, want)
	}

	for i := 4; i <= 59; i += 5 {
		b := []byte(enc)
		encLen, decLen, err := Cut(nil, b, i)
		if err != nil {
			tt.Errorf("i=%d: %v", i, err)
			continue
		}
		if encLen < 1 {
			tt.Errorf("i=%d: encLen: got %d, want >= 1", i, encLen)
			continue
		} else if encLen > len(enc) {
			tt.Errorf("i=%d: encLen: got %d, want <= %d", i, encLen, len(enc))
			continue
		}
		// If we can make some progress (decLen > 0), even if the input uses a
		// Huffman block, one option is to re-encode to a single Stored block
		// (for 5 bytes of overhead). It's single because len(dec) < 0xFFFF.
		// Regardless of whether the cut form uses a Huffman or Stored block,
		// we should be able to produce at least i-5 bytes of decoded output.
		if (decLen > 0) && (i > 5) && (decLen < i-5) {
			tt.Errorf("i=%d: decLen: got %d, want >= %d", i, decLen, i-5)
			continue
		} else if decLen > len(dec) {
			tt.Errorf("i=%d: decLen: got %d, want <= %d", i, decLen, len(dec))
			continue
		}

		if got, want := decodeFlate(b[:encLen]), dec[:decLen]; got != want {
			tt.Errorf("i=%d: after Cut: got %q, want %q", i, got, want)
			continue
		}

		// Check that we are using a space-efficient block type.
		{
			got := (b[0] >> 1) & 3
			want := uint8(0xFF)

			switch i {
			case 4:
				want = 1 // Static Huffman, for a decLen of 0.
			case 9:
				want = 0 // Stored.
			case 59:
				want = 2 // Dynamic Huffman.
			default:
				continue
			}

			if got != want {
				tt.Errorf("i=%d: block type: got %d, want %d", i, got, want)
			}
		}
	}
}

func TestDegenerateHuffmanUnused(tt *testing.T) {
	const dec = degenerateHuffmanDec
	const enc = degenerateHuffmanEnc

	// Cutting 1 byte off the end of the encoded form will lead to cutting n
	// bytes off the decoded form. Coincidentally, n equals 1, even though each
	// decoded byte (8 bits) is packed into smaller number of bits, as most of
	// the final encoded byte's bits are unused padding.
	const n = 1

	b := []byte(enc)
	encLen, decLen, err := Cut(nil, b, len(enc)-1)
	if err != nil {
		tt.Fatalf("Cut: %v", err)
	} else if encLen != len(enc)-1 {
		tt.Fatalf("encLen: got %d, want %d", encLen, len(enc)-1)
	} else if decLen != len(dec)-n {
		tt.Fatalf("decLen: got %d, want %d", decLen, len(dec)-n)
	}

	if got, want := decodeFlate(b[:encLen]), dec[:decLen]; got != want {
		tt.Fatalf("after Cut: got %q, want %q", got, want)
	}
}
