
// peerConnection provides a function to send data through a net.Conn connection
// We need this package because we cannot send raw data through a connection object.
// Data must be sent with a prefix that describes the amount of data being sent

package peerConnection

//TODO: Catch any errors from connectionObject.Read and connectionObject.Write that 
///		would be returned if something has gone wrong on our end

//TODO: Replace this with either gRPC or Websockets.

import "encoding/binary"
import "net"
import "errors"

//Outputs:
//	-bool: Request successful
//	-[]byte: Response received
//	-error
func SendRequestThroughConnection(connectionObject net.Conn, requestToSend []byte, maxResponseSize int)(bool, []byte, error){

	requestSize := len(requestToSend)

	if (requestSize > 4294967295){
		return false, nil, errors.New("SendRequestThroughConnectionObject called with request that is too large.")
	}

	requestSizeUint32 := uint32(requestSize)

	headerBytes := make([]byte, 4)

	binary.LittleEndian.PutUint32(headerBytes, requestSizeUint32)

	_, err := connectionObject.Write(headerBytes)
	if (err != nil) {
		return false, nil, nil
	}

	_, err = connectionObject.Write(requestToSend)
	if (err != nil) {
		return false, nil, nil
	}

	responseHeader := make([]byte, 4)

	_, err = connectionObject.Read(responseHeader)
	if (err != nil) {
		return false, nil, nil
	}

	responseSizeUint32 := binary.LittleEndian.Uint32(responseHeader[:])

	responseSizeInt := int(responseSizeUint32)

	responseBytes := make([]byte, responseSizeInt)

	_, err = connectionObject.Read(responseBytes)
	if (err != nil) {
		return false, nil, nil
	}

	if (len(responseBytes) > maxResponseSize){
		return false, nil, nil
	}

	return true, responseBytes, nil
}


//Outputs:
//	-bool: Request received successfully
//	-[]byte: Request bytes 
//	-error
func GetRequestThroughConnection(connectionObject net.Conn)(bool, []byte, error){

	requestHeader := make([]byte, 4)

	_, err := connectionObject.Read(requestHeader)
	if (err != nil){
		return false, nil, nil
	}

	requestSizeUint32 := binary.LittleEndian.Uint32(requestHeader[:])

	requestSizeInt := int(requestSizeUint32)

	requestBytes := make([]byte, requestSizeInt)

	_, err = connectionObject.Read(requestBytes)
	if (err != nil) {
		return false, nil, nil
	}

	return true, requestBytes, nil
}


//Outputs:
//	-bool: Response sent successfully
//	-error
func SendResponseThroughConnection(connectionObject net.Conn, responseToSend []byte)(bool, error){

	responseSize := len(responseToSend)
	responseSizeUint32 := uint32(responseSize)

	headerBytes := make([]byte, 4)

	binary.LittleEndian.PutUint32(headerBytes, responseSizeUint32)

	_, err := connectionObject.Write(headerBytes)
	if (err != nil) {
		return false, nil
	}

	_, err = connectionObject.Write(responseToSend)
	if (err != nil) {
		return false, nil
	}
	
	return true, nil
}



