package media

import (
	"bytes"
	"io"
)

// ModuloReader reads from a reader in block sizes that are exactly modulo
// modSize, with any remainder buffered until the next read.
type ModuloReader struct {
	io.ReadCloser

	buf     bytes.Buffer
	modSize int
}

func NewModuloReader(r io.ReadCloser, modSize int) *ModuloReader {
	return &ModuloReader{ReadCloser: r, modSize: modSize}
}

func (r *ModuloReader) Read(p []byte) (int, error) {
	// err is always io.EOF or nil
	nr1, _ := r.buf.Read(p)
	nr2, err := r.ReadCloser.Read(p[nr1:])

	nr := nr1 + nr2
	rem := nr % r.modSize

	// if there was an error, return immediately.
	if err == io.EOF {
		return nr, err
	} else if err != nil {
		return nr - rem, err
	}

	// write any remainder to the buffer
	if rem != 0 {
		// err is always nil
		_, _ = r.buf.Write(p[nr-rem : nr])
	}

	return nr - rem, err
}
