/*
* Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors

* 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 kvstore

import (
	"context"
	"time"
)

const (
	// Maximum channel buffer between publisher/subscriber goroutines
	maxClientChannelBufferSize = 10
)

// These constants represent the event types returned by the KV client
const (
	PUT = iota
	DELETE
	CONNECTIONDOWN
	UNKNOWN
)

// KVPair is a common wrapper for key-value pairs returned from the KV store
type KVPair struct {
	Key     string
	Value   interface{}
	Version int64
	Session string
	Lease   int64
}

// NewKVPair creates a new KVPair object
func NewKVPair(key string, value interface{}, session string, lease int64, version int64) *KVPair {
	kv := new(KVPair)
	kv.Key = key
	kv.Value = value
	kv.Session = session
	kv.Lease = lease
	kv.Version = version
	return kv
}

// Event is generated by the KV client when a key change is detected
type Event struct {
	EventType int
	Key       interface{}
	Value     interface{}
	Version   int64
}

// NewEvent creates a new Event object
func NewEvent(eventType int, key interface{}, value interface{}, version int64) *Event {
	evnt := new(Event)
	evnt.EventType = eventType
	evnt.Key = key
	evnt.Value = value
	evnt.Version = version

	return evnt
}

// Client represents the set of APIs a KV Client must implement
type Client interface {
	List(ctx context.Context, key string) (map[string]*KVPair, error)
	KeyExists(ctx context.Context, key string) (bool, error)
	Get(ctx context.Context, key string) (*KVPair, error)
	GetWithPrefix(ctx context.Context, prefixKey string) (map[string]*KVPair, error)
	GetWithPrefixKeysOnly(ctx context.Context, prefixKey string) ([]string, error)
	Put(ctx context.Context, key string, value interface{}) error
	Delete(ctx context.Context, key string) error
	DeleteWithPrefix(ctx context.Context, prefixKey string) error
	Watch(ctx context.Context, key string, withPrefix bool) chan *Event
	IsConnectionUp(ctx context.Context) bool // timeout in second
	CloseWatch(ctx context.Context, key string, ch chan *Event)
	Close(ctx context.Context)

	// These APIs are not used.  They will be cleaned up in release Voltha 2.9.
	// It's not cleaned now to limit changes in all components
	Reserve(ctx context.Context, key string, value interface{}, ttl time.Duration) (interface{}, error)
	ReleaseReservation(ctx context.Context, key string) error
	ReleaseAllReservations(ctx context.Context) error
	RenewReservation(ctx context.Context, key string) error
	AcquireLock(ctx context.Context, lockName string, timeout time.Duration) error
	ReleaseLock(lockName string) error
}
