/*
 *
 * Copyright 2020 gRPC authors.
 *
 * 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 certprovider

import (
	"context"
	"sync"

	"google.golang.org/grpc/internal/grpcsync"
)

// Distributor makes it easy for provider implementations to furnish new key
// materials by handling synchronization between the producer and consumers of
// the key material.
//
// Provider implementations which choose to use a Distributor should do the
// following:
// - create a new Distributor using the NewDistributor() function.
// - invoke the Set() method whenever they have new key material or errors to
//   report.
// - delegate to the distributor when handing calls to KeyMaterial().
// - invoke the Stop() method when they are done using the distributor.
type Distributor struct {
	// mu protects the underlying key material.
	mu   sync.Mutex
	km   *KeyMaterial
	pErr error

	ready  *grpcsync.Event
	closed *grpcsync.Event
}

// NewDistributor returns a new Distributor.
func NewDistributor() *Distributor {
	return &Distributor{
		ready:  grpcsync.NewEvent(),
		closed: grpcsync.NewEvent(),
	}
}

// Set updates the key material in the distributor with km.
//
// Provider implementations which use the distributor must not modify the
// contents of the KeyMaterial struct pointed to by km.
//
// A non-nil err value indicates the error that the provider implementation ran
// into when trying to fetch key material, and makes it possible to surface the
// error to the user. A non-nil error value passed here causes distributor's
// KeyMaterial() method to return nil key material.
func (d *Distributor) Set(km *KeyMaterial, err error) {
	d.mu.Lock()
	d.km = km
	d.pErr = err
	if err != nil {
		// If a non-nil err is passed, we ignore the key material being passed.
		d.km = nil
	}
	d.ready.Fire()
	d.mu.Unlock()
}

// KeyMaterial returns the most recent key material provided to the distributor.
// If no key material was provided at the time of this call, it will block until
// the deadline on the context expires or fresh key material arrives.
func (d *Distributor) KeyMaterial(ctx context.Context) (*KeyMaterial, error) {
	if d.closed.HasFired() {
		return nil, errProviderClosed
	}

	if d.ready.HasFired() {
		return d.keyMaterial()
	}

	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case <-d.closed.Done():
		return nil, errProviderClosed
	case <-d.ready.Done():
		return d.keyMaterial()
	}
}

func (d *Distributor) keyMaterial() (*KeyMaterial, error) {
	d.mu.Lock()
	defer d.mu.Unlock()
	return d.km, d.pErr
}

// Stop turns down the distributor, releases allocated resources and fails any
// active KeyMaterial() call waiting for new key material.
func (d *Distributor) Stop() {
	d.closed.Fire()
}
