// 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 cgozlib wraps the C "zlib" library.
//
// Unlike some other wrappers, this one supports dictionaries.
package cgozlib

/*
#cgo pkg-config: zlib
#include "zlib.h"

typedef struct {
	uInt ndst;
	uInt nsrc;
} advances;

int cgozlib_inflateInit(z_stream* z) {
	return inflateInit(z);
}

int cgozlib_inflateSetDictionary(z_stream* z,
		Bytef* dict_ptr,
		uInt dict_len) {
	return inflateSetDictionary(z, dict_ptr, dict_len);
}

int cgozlib_inflate(z_stream* z,
		advances* a,
		Bytef* next_out,
		uInt avail_out,
		Bytef* next_in,
		uInt avail_in) {
	z->next_out = next_out;
	z->avail_out = avail_out;
	z->next_in = next_in;
	z->avail_in = avail_in;

	int ret = inflate(z, Z_NO_FLUSH);

	a->ndst = avail_out - z->avail_out;
	a->nsrc = avail_in - z->avail_in;

	z->next_out = NULL;
	z->avail_out = 0;
	z->next_in = NULL;
	z->avail_in = 0;

	return ret;
}

int cgozlib_inflateEnd(z_stream* z) {
	return inflateEnd(z);
}
*/
import "C"

import (
	"errors"
	"io"
	"unsafe"
)

const cgoEnabled = true

var (
	errMissingResetCall = errors.New("cgozlib: missing Reset call")
	errNilIOReader      = errors.New("cgozlib: nil io.Reader")
	errNilReceiver      = errors.New("cgozlib: nil receiver")
)

const (
	errCodeStreamEnd = 1
	errCodeNeedDict  = 2
)

type errCode int32

func (e errCode) Error() string {
	switch e {
	case +1:
		return "cgozlib: Z_STREAM_END"
	case +2:
		return "cgozlib: Z_NEED_DICT"
	case -1:
		return "cgozlib: Z_ERRNO"
	case -2:
		return "cgozlib: Z_STREAM_ERROR"
	case -3:
		return "cgozlib: Z_DATA_ERROR"
	case -4:
		return "cgozlib: Z_MEM_ERROR"
	case -5:
		return "cgozlib: Z_BUF_ERROR"
	case -6:
		return "cgozlib: Z_VERSION_ERROR"
	}
	return "cgozlib: unknown zlib error"
}

// Reader is both a zlib.Resetter and an io.ReadCloser. Call Reset before
// calling Read.
//
// It is analogous to the value returned by zlib.NewReader in the Go standard
// library.
type Reader struct {
	buf  [4096]byte
	i, j uint32
	r    io.Reader
	dict []byte

	readErr error
	zlibErr error

	z C.z_stream
	a C.advances
}

// Reset implements compression.Reader.
func (r *Reader) Reset(reader io.Reader, dictionary []byte) error {
	if r == nil {
		return errNilReceiver
	}
	if err := r.Close(); err != nil {
		return err
	}
	if reader == nil {
		return errNilIOReader
	}

	if e := C.cgozlib_inflateInit(&r.z); e != 0 {
		return errCode(e)
	}

	r.r = reader
	r.dict = dictionary
	if n := len(r.dict); n > 32768 {
		r.dict = r.dict[n-32768:]
	}
	return nil
}

// Close implements compression.Reader.
func (r *Reader) Close() error {
	if r == nil {
		return errNilReceiver
	}
	if r.r == nil {
		return nil
	}
	r.i = 0
	r.j = 0
	r.r = nil
	r.dict = nil
	r.readErr = nil
	r.zlibErr = nil
	if e := C.cgozlib_inflateEnd(&r.z); e != 0 {
		return errCode(e)
	}
	return nil
}

// Read implements compression.Reader.
func (r *Reader) Read(p []byte) (int, error) {
	if r == nil {
		return 0, errNilReceiver
	}
	if r.r == nil {
		return 0, errMissingResetCall
	}

	const maxLen = 1 << 30
	if len(p) > maxLen {
		p = p[:maxLen]
	}

	for numRead := 0; ; {
		if r.zlibErr != nil {
			return numRead, r.zlibErr
		}
		if len(p) == 0 {
			return numRead, nil
		}

		if r.i >= r.j {
			if r.readErr != nil {
				return numRead, r.readErr
			}

			n, err := r.r.Read(r.buf[:])
			if err == io.EOF {
				err = io.ErrUnexpectedEOF
			}
			r.i, r.j, r.readErr = 0, uint32(n), err
			continue
		}

		e := C.cgozlib_inflate(&r.z, &r.a,
			(*C.Bytef)(unsafe.Pointer(&p[0])),
			(C.uInt)(len(p)),
			(*C.Bytef)(unsafe.Pointer(&r.buf[r.i])),
			(C.uInt)(r.j-r.i),
		)

		numRead += int(r.a.ndst)
		p = p[int(r.a.ndst):]

		r.i += uint32(r.a.nsrc)

		if e == 0 {
			continue
		} else if e == errCodeStreamEnd {
			r.zlibErr = io.EOF
		} else if (e == errCodeNeedDict) && (len(r.dict) > 0) {
			e = C.cgozlib_inflateSetDictionary(&r.z,
				(*C.Bytef)(unsafe.Pointer(&r.dict[0])),
				(C.uInt)(len(r.dict)),
			)
			if e == 0 {
				continue
			}
			r.zlibErr = errCode(e)
		} else {
			r.zlibErr = errCode(e)
		}
		return numRead, r.zlibErr
	}
}
