// Copyright 2022 Northern.tech AS
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

package crypto

import (
	"github.com/pkg/errors"
	"go.mongodb.org/mongo-driver/bson"
)

type String string

type stringBSON struct {
	Algorithm string `bson:"algorithm"`
	KeyID     string `bson:"keyID,omitempty"`
	Data      []byte `bson:"data"`
}

const (
	algorithmAES_256_CFB_HMAC_SHA512 = "AES_256_CFB_HMAC_SHA512"
	omitted                          = "<omitted>"
)

var (
	ErrUnknownAlgorithm = errors.New("unknown algorithm")
)

func (c *String) MarshalText() ([]byte, error) {
	return []byte(omitted), nil
}

func (s *String) MarshalBSON() ([]byte, error) {
	out, err := AESEncrypt(string(*s))
	if err != nil {
		return nil, err
	}
	return bson.Marshal(&stringBSON{
		Algorithm: algorithmAES_256_CFB_HMAC_SHA512,
		Data:      out,
	})
}

func (s *String) UnmarshalBSON(data []byte) error {
	out := &stringBSON{}
	err := bson.Unmarshal(data, out)
	if err != nil {
		return err
	} else if out.Algorithm != algorithmAES_256_CFB_HMAC_SHA512 {
		return ErrUnknownAlgorithm
	}
	value, err := AESDecrypt(out.Data)
	if err == nil {
		*s = String(value)
	}
	return err
}
