// 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 datasource defines the interfaces a system must implement to support
// querying.
//
// The Database interface is used to get Table interfaces (by name).
// The Table interface is used to get a KeyValueStream (by key prefixes).
// The KeyValueStream interface is used to iterate over key-value pairs from a
// table.
// Note: Order, Index, GetIndexFields and the indexRanges arg to Scan
//       are being provided in beta form for use by discovery.  Currently only
//       indexes of type string are supported and an index must comprise exactly
//       one column.  This API will change when secondary indexes are fully supported.
package datasource

import (
	"fmt"
	"v.io/v23/context"
	"v.io/v23/vdl"
)

type Database interface {
	// GetContext returns a context (used for creating error messages).
	GetContext() *context.T

	// GetTable returns an instance of the Table inteface for the table
	// specified by name.  If writeAccessReq is true, the Table needs
	// to support the Delete function.  If it cannot, the syncql.NotWritable
	// error should be returned.
	GetTable(name string, writeAccessReq bool) (Table, error)
}

type Table interface {

	// Return the fields on which there exist secondary indexes.
	// The possible ranges for these fields will be passed to Scan.
	// Example:
	// return []datasource.Index{
	//                datasource.Index{FieldName: "v.InterfaceName", Kind: vdl.String},
	//                datasource.Index{FieldName: "v.Address", Kind: vdl.String},
	// }
	// At present, the Kind MUST BE vdl.String
	GetIndexFields() []Index

	// Return a KeyValueStream where all k/v pairs fall within the range
	// of the index ranges passed in (the first of which is for the key).
	// Note: an empty string prefix (""), matches all keys.
	// The index ranges will be sorted (low to high).  The first index range
	// will be for the key.  After that will be ranges for any index returned
	// from GetIndexFields.  These will be returned in the same order as was
	// present in the return value for GetIndexFields.  Currently, only string indexes are
	// supported. Index ranges include the index field name (in order to differentiate among
	// multiple secondary indexes).  Again, the first will always be the "k" field.
	// If NilAllowed is true, nil values for the index field should be included in the
	// return k/v pairs from Scan.  If false, they should not be included.
	// It's best to honor all index ranges.  The datasource should honor the
	// the ranges by not passing in k/v pairs that the ranges exclude.  Future
	// optimzation may cause incorrect answers if this contract is not kept.
	Scan(indexRanges ...IndexRanges) (KeyValueStream, error)

	// Delete deletes the k/v pair for key k.
	// This will only be called if GetTable was called with writeAccessReq == true.
	// If Delete is not supported, GetTable should have returned an error.  If
	// Delete is called anyway (logic error), the syncql.OperationNotSupported error
	// should be returned.
	Delete(k string) (bool, error)
}

type KeyValueStream interface {
	// Advance stages an element so the client can retrieve it
	// with KeyValue.  Advance returns true iff there is an
	// element to retrieve.  The client must call Advance before
	// calling KeyValue.  The client must call Cancel if it does
	// not iterate through all elements (i.e. until Advance
	// returns false).  Advance may block if an element is not
	// immediately available.
	Advance() bool

	// KeyValue returns the element that was staged by Advance.
	// KeyValue may panic if Advance returned false or was not
	// called at all.  KeyValue does not block.
	KeyValue() (string, *vdl.Value)

	// Err returns a non-nil error iff the stream encountered
	// any errors.  Err does not block.
	Err() error

	// Cancel notifies the stream provider that it can stop
	// producing elements.  The client must call Cancel if it does
	// not iterate through all elements (i.e. until Advance
	// returns false).  Cancel is idempotent and can be called
	// concurrently with a goroutine that is iterating via
	// Advance/Value.  Cancel causes Advance to subsequently
	// return  false.  Cancel does not block.
	Cancel()
}

// Implement sort interface for StringFieldRanges.
func (stringFieldRanges StringFieldRanges) Len() int {
	return len(stringFieldRanges)
}

func (stringFieldRanges StringFieldRanges) Less(i, j int) bool {
	return stringFieldRanges[i].Start < stringFieldRanges[j].Start
}

func (stringFieldRanges StringFieldRanges) Swap(i, j int) {
	saveStart := stringFieldRanges[i].Start
	saveLimit := stringFieldRanges[i].Limit
	stringFieldRanges[i].Start = stringFieldRanges[j].Start
	stringFieldRanges[i].Limit = stringFieldRanges[j].Limit
	stringFieldRanges[j].Start = saveStart
	stringFieldRanges[j].Limit = saveLimit
}

type StringFieldRange struct {
	Start string
	Limit string
}

type Index struct {
	FieldName string
	Kind      vdl.Kind
}

type StringFieldRanges []StringFieldRange
type IndexRanges struct {
	FieldName    string
	Kind         vdl.Kind
	NilAllowed   bool // true if query could be true for a nil index value
	StringRanges *StringFieldRanges
	// TODO(jkline): add fields for other types of indexes.
}

// String() used in tests.
func (ir *IndexRanges) String() string {
	str := fmt.Sprintf("IndexRanges{FieldName: %s, Kind: %v, NilAllowed: %v, ", ir.FieldName, ir.Kind, ir.NilAllowed)
	for _, r := range *ir.StringRanges {
		str += fmt.Sprintf("{%s,%s}", r.Start, r.Limit)
	}
	str += "}"
	return str
}
