// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package app

import (
	"signature"

	"v.io/v23/security"
	"v.io/x/ref/services/wspr/internal/principal"
)

type Controller interface {
	// Serve instructs WSPR to start listening for calls on behalf
	// of a javascript server.
	Serve(name string, serverId uint32, serverOpts []RpcServerOption) error
	// Stop instructs WSPR to stop listening for calls for the
	// given javascript server.
	Stop(serverId uint32) error
	// AddName adds a published name to an existing server.
	AddName(serverId uint32, name string) error
	// RemoveName removes a published name from an existing server.
	RemoveName(serverId uint32, name string) error

	// UnlinkBlessings removes the given blessings from the blessings store.
	UnlinkBlessings(handle principal.BlessingsHandle) error
	// BlessingsDebugString gets a string useful for debugging blessings.
	BlessingsDebugString(handle principal.BlessingsHandle) (string | error)
	// Bless binds extensions of blessings held by this principal to
	// another principal (represented by its public key).
	Bless(publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (principal.BlessingsId | error)
	// BlessSelf creates a blessing with the provided name for this principal.
	BlessSelf(name string, caveats []security.Caveat) (principal.BlessingsId | error)
	// AddToRoots adds the provided blessing as a root.
	AddToRoots(handle principal.BlessingsHandle) error

	// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
	BlessingStoreSet(blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (principal.BlessingsId | error)
	// BlessingStoreForPeer retrieves the blessings marked for the given peers.
	BlessingStoreForPeer(peerBlessings []string) (principal.BlessingsId | error)
	// BlessingStoreSetDefault sets the default blessings.
	BlessingStoreSetDefault(blessingsHandle principal.BlessingsHandle) error
	// BlessingStoreDefault fetches the default blessings for the principal of the controller.
	BlessingStoreDefault() (principal.BlessingsId | error)
	// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
	BlessingStorePublicKey() (string | error)
	// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
	BlessingStorePeerBlessings() (map[security.BlessingPattern]principal.BlessingsId | error)
	// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
	BlessingStoreDebugString() (string | error)


	// RemoteBlessings fetches the remote blessings for a given name and method.
	RemoteBlessings(name, method string) ([]string | error)
	// Signature fetches the signature for a given name.
	Signature(name string) ([]signature.Interface | error)

  // UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
	UnionOfBlessings(toJoin []principal.BlessingsHandle) (principal.BlessingsId | error)
}
