package mvcc

import (
	"context"
	"errors"
	"io"
)

// ErrManifestPointerConflict is returned by an ObjectStorage's Commit when the
// manifest pointer has diverged from the base hash that was resolved at the
// start of the RPC, i.e. another writer advanced the pointer concurrently.
// Conflict resolution (e.g. a three-way merge) is out of scope for now, so the
// RPC must fail; clients may retry against the new base.
var ErrManifestPointerConflict = errors.New("mvcc: manifest pointer conflict")

// ObjectStorage is the interface used for a component to communicate with object storage.
type ObjectStorage interface {
	// ReadManifestPointer reads the manifest pointer for the given repository ID
	ReadManifestPointer(ctx context.Context, repositoryID string) (string, error)

	// ReadManifest reads a specific manifest for the repository, keyed on the hash.
	ReadManifest(ctx context.Context, repositoryID string, hash string) (io.ReadCloser, error)

	// ReadArtifact ensures the artifact identified by `key` is fetched for the given repository.
	ReadArtifact(ctx context.Context, repositoryID, key string) (io.ReadCloser, error)

	// PutArtifact writes `content` at `key` for the given repository.
	PutArtifact(ctx context.Context, repositoryID, key string, content io.ReadCloser) error

	// Commit commits the new manifest pointer for the given repository. This operation
	// must be atomic, by comparing the baseHash (value of the current manifest pointer)
	// with the newHash. If a conflict occurs, some implementations can introduce a conflict
	// resolution mechanism (ex: three-way merge).
	Commit(ctx context.Context, repositoryID, baseHash string, newHash string) error
}
