// Copyright 2016 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 syncbase

import (
	"v.io/v23/context"
	"v.io/v23/naming"
	wire "v.io/v23/services/syncbase"
	"v.io/v23/services/watch"
	"v.io/v23/syncbase/util"
	"v.io/v23/verror"
	"v.io/v23/vom"
)

func newDatabaseBatch(parentFullName string, id wire.Id, batchHandle wire.BatchHandle) *databaseBatch {
	fullName := naming.Join(parentFullName, util.EncodeId(id))
	return &databaseBatch{
		c:              wire.DatabaseClient(fullName),
		parentFullName: parentFullName,
		fullName:       fullName,
		id:             id,
		bh:             batchHandle,
	}
}

type databaseBatch struct {
	c              wire.DatabaseClientMethods
	parentFullName string
	fullName       string
	id             wire.Id
	bh             wire.BatchHandle
}

var _ DatabaseHandle = (*databaseBatch)(nil)

// Id implements DatabaseHandle.Id.
func (d *databaseBatch) Id() wire.Id {
	return d.id
}

// FullName implements DatabaseHandle.FullName.
func (d *databaseBatch) FullName() string {
	return d.fullName
}

// Collection implements DatabaseHandle.Collection.
func (d *databaseBatch) Collection(ctx *context.T, name string) Collection {
	blessing, err := util.UserBlessingFromContext(ctx)
	if err != nil {
		// TODO(sadovsky): Return invalid Collection handle.
		panic(err)
	}
	return newCollection(d.fullName, wire.Id{Blessing: blessing, Name: name}, d.bh)
}

// CollectionForId implements DatabaseHandle.CollectionForId.
func (d *databaseBatch) CollectionForId(id wire.Id) Collection {
	return newCollection(d.fullName, id, d.bh)
}

// ListCollections implements DatabaseHandle.ListCollections.
func (d *databaseBatch) ListCollections(ctx *context.T) ([]wire.Id, error) {
	// See comment in v.io/v23/services/syncbase/service.vdl for why we
	// can't implement ListCollections using Glob (via util.ListChildren).
	ids, err := d.c.ListCollections(ctx, d.bh)
	if err != nil {
		return nil, err
	}
	util.SortIds(ids)
	return ids, nil
}

// Exec implements DatabaseHandle.Exec.
// TODO(ivanpi): Parameterized Exec currently allows struct comparisons, which
// we wish to prevent. However, cases like JavaScript JSValue benefit from this.
func (d *databaseBatch) Exec(ctx *context.T, query string, params ...interface{}) ([]string, ResultStream, error) {
	paramsVom := make([]*vom.RawBytes, len(params))
	for i, p := range params {
		var err error
		if paramsVom[i], err = vom.RawBytesFromValue(p); err != nil {
			return nil, nil, err
		}
	}
	ctx, cancel := context.WithCancel(ctx)
	call, err := d.c.Exec(ctx, d.bh, query, paramsVom)
	if err != nil {
		return nil, nil, err
	}
	resultStream := newResultStream(cancel, call)
	// The first row contains column headers. Pull them off the stream
	// and return them separately.
	var headers []string
	if !resultStream.Advance() {
		if err = resultStream.Err(); err != nil {
			// Since there was an error, can't get headers.
			// Just return the error.
			return nil, nil, err
		}
	}
	for i, n := 0, resultStream.ResultCount(); i != n; i++ {
		var header string
		if err := resultStream.Result(i, &header); err == nil {
			headers = append(headers, header)
		} else {
			return nil, nil, verror.New(wire.ErrBadExecStreamHeader, ctx, query)
		}
	}
	return headers, resultStream, nil
}

// GetResumeMarker implements DatabaseHandle.GetResumeMarker.
func (d *databaseBatch) GetResumeMarker(ctx *context.T) (watch.ResumeMarker, error) {
	return d.c.GetResumeMarker(ctx, d.bh)
}
