package utils

import (
	"otaupdate/services"

	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/security"
	"github.com/fiskerinc/cloud-services/pkg/utils/randomvalues"
)

type FileEncryptor struct {
	FileID    string
	encrypter security.IEncryptor
	streamer  security.IEncryptedStream
	fileKey *common.FileKey
}

func NewEncryptor() (*FileEncryptor, error) {
	instance := FileEncryptor{}
	err := instance.init()
	return &instance, err
}

func (fe *FileEncryptor) SaveFileKey()(err error){
	err = fe.saveData(fe.fileKey)
	return
}

func (fe *FileEncryptor) init() error {
	filekey, err := fe.getKey()
	if err != nil {
		return err
	}

	fe.fileKey = filekey
	/* err = fe.saveData(filekey)
	if err != nil {
		return err
	} */

	encrypter, _, err := security.NewEncryptor(filekey.Key, filekey.Auth, filekey.Nonce)
	if err != nil {
		return err
	}

	streamer, err := security.NewEncryptedStream(encrypter, security.WithUniqueId([]byte(filekey.FileID)))
	if err != nil {
		return err
	}

	fe.FileID = filekey.FileID
	fe.encrypter = encrypter
	fe.streamer = streamer

	return nil
}

func (fe *FileEncryptor) saveData(filekey *common.FileKey) error {
	_, err := services.GetDB().GetFileKeys().Insert(*filekey)
	return err
}

func (fe *FileEncryptor) getKey() (*common.FileKey, error) {
	var err error
	generator := randomvalues.NewGenerator("")
	filekey := common.FileKey{}

	filekey.FileID, err = generator.GetUniformDistHex()
	if err != nil {
		return nil, err
	}

	value, err := generator.GetBytes(32)
	if err != nil {
		return nil, err
	}
	filekey.Key = value

	value, err = generator.GetBytes(16)
	if err != nil {
		return nil, err
	}
	filekey.Auth = value

	value, err = generator.GetBytes(12)
	if err != nil {
		return nil, err
	}
	filekey.Nonce = value

	return &filekey, nil

}

func (fe *FileEncryptor) Encrypt(input []byte) []byte {
	return fe.streamer.Write(input)
}

func (fe *FileEncryptor) Close() {
	fe.FileID = ""
	fe.encrypter.Close()
	fe.encrypter = nil
	fe.streamer = nil
}
