// Package rle implements the run-length encoding scheme discovered in Chaos
// Gate .obj files. It may be used for other data too - to be determined.
package rle

import (
	"bufio"
	"io"
	"io/ioutil"
)

// Expand converts the compressed input data into uncompressed output data. The
// output buffer should be of at least the expected size. We will read until
// io.EOF is encountered.
func Expand(in io.Reader, out []byte) error {
	buf := bufio.NewReader(in)
	idx := 0

	for {
		b, err := buf.ReadByte()
		if err != nil {
			if err == io.EOF {
				return nil
			}

			return err
		}

		if b == 0x00 { // NOP
			continue
		} else if b < 0x80 { // repeat the next byte this many times
			repeat := b
			value, err := buf.ReadByte()
			if err != nil {
				return err
			}

			for x := 0; x < int(repeat); x++ {
				out[idx+x] = value
			}
			idx = idx + int(repeat)
		} else if b == 0x80 { // skip forward in the output by the next byte's value
			skip, err := buf.ReadByte()
			if err != nil {
				return err
			}

			idx = idx + int(skip)
		} else { // Take the next b-0x80 bytes literally
			lr := io.LimitReader(buf, int64(b-0x80))
			literals, err := ioutil.ReadAll(lr)
			if err != nil {
				return err
			}
			copy(out[idx:], literals)
			idx = idx + len(literals)
		}
	}

	return nil
}
