package encryption

import (
	"bytes"
	"encoding/binary"

	"github.com/pkg/errors"
)

func (c *AuthorizedFieldClient) EncryptString(encCtx map[string]string, plaintext string) ([]byte, error) {
	olePayload, err := c.encrypt(encCtx, []byte(plaintext))
	if err != nil {
		return nil, errors.Wrap(err, "could not encrypt authorized field")
	}

	return olePayload, nil
}

func (c *AuthorizedFieldClient) EncryptFloat32(encCtx map[string]string, float32ToEnc float32) ([]byte, error) {
	var buf bytes.Buffer
	err := binary.Write(&buf, binary.LittleEndian, float32ToEnc)
	if err != nil {
		return nil, errors.Wrap(err, "could not write float32 to binary format")
	}

	olePayload, err := c.encrypt(encCtx, buf.Bytes())
	if err != nil {
		return nil, errors.Wrap(err, "could not encrypt authorized field")
	}

	return olePayload, nil
}

func (c *AuthorizedFieldClient) EncryptFloat64(encCtx map[string]string, float64ToEnc float64) ([]byte, error) {
	var buf bytes.Buffer
	err := binary.Write(&buf, binary.LittleEndian, float64ToEnc)
	if err != nil {
		return nil, errors.Wrap(err, "could not write float64 to binary format")
	}

	olePayload, err := c.encrypt(encCtx, buf.Bytes())
	if err != nil {
		return nil, errors.Wrap(err, "could not encrypt authorized field")
	}

	return olePayload, nil
}

func (c *AuthorizedFieldClient) EncryptInt32(encCtx map[string]string, int32ToEnc int32) ([]byte, error) {
	var buf bytes.Buffer
	err := binary.Write(&buf, binary.LittleEndian, int32ToEnc)
	if err != nil {
		return nil, errors.Wrap(err, "could not write int32 to binary format")
	}

	olePayload, err := c.encrypt(encCtx, buf.Bytes())
	if err != nil {
		return nil, errors.Wrap(err, "could not encrypt authorized field")
	}

	return olePayload, nil
}

func (c *AuthorizedFieldClient) EncryptInt64(encCtx map[string]string, int64ToEnc int64) ([]byte, error) {
	var buf bytes.Buffer
	err := binary.Write(&buf, binary.LittleEndian, int64ToEnc)
	if err != nil {
		return nil, errors.Wrap(err, "could not write int64 to binary format")
	}

	olePayload, err := c.encrypt(encCtx, buf.Bytes())
	if err != nil {
		return nil, errors.Wrap(err, "could not encrypt authorized field")
	}

	return olePayload, nil
}

func (c *AuthorizedFieldClient) encrypt(encCtx map[string]string, bytesToEnc []byte) ([]byte, error) {
	var buf bytes.Buffer
	encryptedBuf := c.ole.NewEncryptor(encCtx, &buf)

	_, err := encryptedBuf.Write(bytesToEnc)
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}
