package tscipher

import (
	"crypto/aes"
	"crypto/cipher"
	crtrand "crypto/rand"
	//	"errors"
	"io"
	"log"
)

type AES struct {
	key []byte
}

func (this *AES) aesEncrypt(key, text []byte) (ciphertext []byte) {
	ciphertext = make([]byte, aes.BlockSize+len(string(text)))
	// iv =  initialization vector
	iv := ciphertext[:aes.BlockSize]

	io.ReadFull(crtrand.Reader, iv)

	//	var block cipher.Block
	block, err := aes.NewCipher(key)
	if err != nil {
		ciphertext = nil
		log.Println("encrypt err", err)
	}

	cfb := cipher.NewCFBEncrypter(block, iv)
	cfb.XORKeyStream(ciphertext[aes.BlockSize:], text)
	return
}

func (this *AES) aesDecrypt(key, ciphertext []byte) (plaintext []byte) {

	//	var block cipher.Block
	//	if len(ciphertext) < aes.BlockSize {
	//		err := errors.New("ciphertext too short")
	//		plaintext = nil
	//		log.Println("decrypt err", err)
	//	}

	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]
	block, err := aes.NewCipher(key)
	if err != nil {
		plaintext = nil
		log.Println("decrypt err", err)
	}
	cfb := cipher.NewCFBDecrypter(block, iv)
	cfb.XORKeyStream(ciphertext, ciphertext)

	plaintext = ciphertext

	return
}

func (this *AES) Decrypt(data []byte) (decrypted []byte, err error) {
	data = this.aesDecrypt(this.key, data)
	decrypted = data
	err = nil
	return
}

func (this *AES) Encrypt(data []byte) (encryped []byte, err error) {
	this.aesEncrypt(this.key, data)
	encryped = data
	err = nil
	return
}

func NewAES() (cipher Cipher) {
	key := make([]byte, 32)
	io.ReadFull(crtrand.Reader, key)
	return &AES{
		key: key,
	}
}
