package encryption

import (
	"bytes"
	"encoding/binary"
	"io/ioutil"
	"math"

	"github.com/pkg/errors"
)

func (c *AuthorizedFieldClient) DecryptString(blob []byte) (string, error) {
	if blob == nil {
		return "", nil
	}

	plaintext, err := c.decrypt(blob)
	if err != nil {
		return "", errors.Wrap(err, "could not decrypt authorized field")
	}

	return string(plaintext), nil
}

func (c *AuthorizedFieldClient) DecryptFloat32(blob []byte) (float32, error) {
	if blob == nil {
		return 0, nil
	}

	float32Decrypted, err := c.decrypt(blob)
	if err != nil {
		return 0, errors.Wrap(err, "could not decrypt authorized field")
	}

	bits := binary.LittleEndian.Uint32(float32Decrypted)

	return math.Float32frombits(bits), nil
}

func (c *AuthorizedFieldClient) DecryptFloat64(blob []byte) (float64, error) {
	if blob == nil {
		return 0, nil
	}

	float64Decrypted, err := c.decrypt(blob)
	if err != nil {
		return 0, errors.Wrap(err, "could not decrypt authorized field")
	}

	bits := binary.LittleEndian.Uint64(float64Decrypted)

	return math.Float64frombits(bits), nil
}

func (c *AuthorizedFieldClient) DecryptInt32(blob []byte) (int32, error) {
	if blob == nil {
		return 0, nil
	}

	int32Decrypted, err := c.decrypt(blob)
	if err != nil {
		return 0, errors.Wrap(err, "could not decrypt authorized field")
	}

	bits := binary.LittleEndian.Uint32(int32Decrypted)

	return int32(bits), nil
}

func (c *AuthorizedFieldClient) DecryptInt64(blob []byte) (int64, error) {
	if blob == nil {
		return 0, nil
	}

	int64Decrypted, err := c.decrypt(blob)
	if err != nil {
		return 0, errors.Wrap(err, "could not decrypt authorized field")
	}

	bits := binary.LittleEndian.Uint64(int64Decrypted)

	return int64(bits), nil
}

func (c *AuthorizedFieldClient) decrypt(olePayload []byte) ([]byte, error) {
	if olePayload == nil {
		return nil, ErrNilOLEPayload
	}

	decryptedBuf := c.ole.NewDecryptor(bytes.NewReader(olePayload))
	bs, err := ioutil.ReadAll(decryptedBuf)
	if err != nil {
		return nil, err
	}

	return bs, nil
}
