// 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 primitiveset provides a container for a set of cryptographic primitives.
//
// It provides also additional properties for the primitives it holds. In particular, one of the primitives in the set can be distinguished as "the primary" one.
package primitiveset

import (
	"fmt"

	"github.com/google/tink/go/core/cryptofmt"
	tinkpb "github.com/google/tink/proto/tink_go_proto"
)

// Entry represents a single entry in the keyset. In addition to the actual primitive,
// it holds the identifier and status of the primitive.
type Entry struct {
	Primitive  interface{}
	Prefix     string
	PrefixType tinkpb.OutputPrefixType
	Status     tinkpb.KeyStatusType
}

func newEntry(p interface{}, prefix string, prefixType tinkpb.OutputPrefixType, status tinkpb.KeyStatusType) *Entry {
	return &Entry{
		Primitive:  p,
		Prefix:     prefix,
		Status:     status,
		PrefixType: prefixType,
	}
}

// PrimitiveSet is used for supporting key rotation: primitives in a set correspond to keys in a
// keyset. Users will usually work with primitive instances, which essentially wrap primitive
// sets. For example an instance of an AEAD-primitive for a given keyset holds a set of
// AEAD-primitives corresponding to the keys in the keyset, and uses the set members to do the
// actual crypto operations: to encrypt data the primary AEAD-primitive from the set is used, and
// upon decryption the ciphertext's prefix determines the id of the primitive from the set.

// PrimitiveSet is a public to allow its use in implementations of custom primitives.
type PrimitiveSet struct {
	// Primary entry.
	Primary *Entry

	// The primitives are stored in a map of (ciphertext prefix, list of primitives sharing the
	// prefix). This allows quickly retrieving the primitives sharing some particular prefix.
	Entries map[string][]*Entry
}

// New returns an empty instance of PrimitiveSet.
func New() *PrimitiveSet {
	return &PrimitiveSet{
		Primary: nil,
		Entries: make(map[string][]*Entry),
	}
}

// RawEntries returns all primitives in the set that have RAW prefix.
func (ps *PrimitiveSet) RawEntries() ([]*Entry, error) {
	return ps.EntriesForPrefix(cryptofmt.RawPrefix)
}

// EntriesForPrefix returns all primitives in the set that have the given prefix.
func (ps *PrimitiveSet) EntriesForPrefix(prefix string) ([]*Entry, error) {
	result, found := ps.Entries[prefix]
	if !found {
		return []*Entry{}, nil
	}
	return result, nil
}

// Add creates a new entry in the primitive set and returns the added entry.
func (ps *PrimitiveSet) Add(p interface{}, key *tinkpb.Keyset_Key) (*Entry, error) {
	if key == nil || p == nil {
		return nil, fmt.Errorf("primitive_set: key and primitive must not be nil")
	}
	if key.Status != tinkpb.KeyStatusType_ENABLED {
		return nil, fmt.Errorf("The key must be ENABLED")
	}
	prefix, err := cryptofmt.OutputPrefix(key)
	if err != nil {
		return nil, fmt.Errorf("primitive_set: %s", err)
	}
	e := newEntry(p, prefix, key.OutputPrefixType, key.Status)
	ps.Entries[prefix] = append(ps.Entries[prefix], e)
	return e, nil
}
