package Encryption

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"errors"
	"io"
	"io/ioutil"
	"os"
)

func DecryptData(password string, ciphertext []byte) ([]byte, error) {
	var (
		hashedKey []byte
		iv        []byte
		encKey    []byte
		block     cipher.Block
		stream    cipher.Stream
		e         error
	)
	hashedKey = CreateHash(password)
	if len(ciphertext) == 0 {
		return []byte{}, errors.New("Invalid length")
	}
	iv = ciphertext[:aes.BlockSize]
	encKey = ciphertext[:32+aes.BlockSize][aes.BlockSize:]
	ciphertext = ciphertext[aes.BlockSize+32:]

	block, e = CreateKey(hashedKey)
	if e != nil {
		return []byte{}, e
	}

	stream = cipher.NewCFBDecrypter(block, iv)
	stream.XORKeyStream(encKey, encKey)

	for i := range encKey {
		if encKey[i] != hashedKey[i] {
			return []byte{}, errors.New("Incorrect Password")
		}
	}

	stream.XORKeyStream(ciphertext, ciphertext)
	return ciphertext, nil
}

func DecryptFile(password string, FilePath string) error {
	var (
		OldFilePath   string
		ciphertext    []byte
		plaintext     []byte
		plaintextFile *os.File
		e             error
	)
	OldFilePath = FilePath[:(len(FilePath) - 4)]
	ciphertext, e = ioutil.ReadFile(FilePath)
	if e != nil {
		return e
	}
	if len(ciphertext) < aes.BlockSize {
		return errors.New("ciphertext too short")
	}

	plaintext, e = DecryptData(password, ciphertext)
	if e != nil {
		return e
	}

	plaintextFile, e = os.Create(OldFilePath)
	if e != nil {
		return e
	}
	_, e = io.Copy(plaintextFile, bytes.NewReader(plaintext))
	if e != nil {
		return e
	}
	os.Remove(FilePath)
	return nil
}

func DecryptAndReadFile(password string, FilePath string) (string, error) {
	var (
		ciphertext []byte
		plaintext  []byte
		e          error
	)
	ciphertext, e = ioutil.ReadFile(FilePath)
	if e != nil {
		return "", e
	}
	if len(ciphertext) < aes.BlockSize {
		return "", errors.New("ciphertext too short")
	}

	plaintext, e = DecryptData(password, ciphertext)
	if e != nil {
		return "", e
	}
	return string(plaintext), nil
}
