// 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
}
