package shared

import (
	"bytes"
	"fmt"
	"io"
	"time"

	log "github.com/sirupsen/logrus"
)

// receive at maximum the requested number of bytes from serial port and stop after the given timeout
func ReceiveBytes(port io.Reader, count int, timeout time.Duration) ([]byte, error) {
	readCh := make(chan []byte, 1)
	errCh := make(chan error, 1)

	go func() {
		buffer := bytes.NewBuffer([]byte{})

		for remainder := count; remainder > 0; {
			data := make([]byte, remainder)
			if readBytes, err := port.Read(data); err != nil {
				errCh <- err

				return
			} else if readBytes > 0 {
				buffer.Write(data[0:readBytes])
				remainder -= readBytes
				log.Tracef("%d bytes read, remaining %d", readBytes, remainder)
			}
		}

		readCh <- buffer.Bytes()
		close(readCh)
	}()

	buffer := bytes.NewBuffer([]byte{})
	select {
	case <-time.After(timeout):
		return nil, fmt.Errorf("timeout passed %v", timeout)
	case err := <-errCh:
		return nil, err
	case data := <-readCh:
		log.Tracef("received %d bytes from channel", len(data))

		if data == nil {
			break
		}

		buffer.Write(data)
	}

	return buffer.Bytes(), nil
}

func SendBytes(port io.Writer, data []byte) error {
	n, err := port.Write(data)
	if err != nil {
		return fmt.Errorf("could not send bytes: %w", err)
	}

	log.Tracef("wrote %d bytes", n)

	return nil
}