// 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.

// Utilities for creating and opening the database in Syncbase.
package sbutil

import (
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/security"
	"v.io/v23/security/access"
	"v.io/v23/syncbase"
	"v.io/v23/syncbase/nosql"
	"v.io/v23/verror"
	"v.io/x/sensorlog/internal/config"
	"v.io/x/sensorlog/internal/sbmodel"
)

// CreateOrOpenDB opens the Sensor Log database hosted on specified Syncbase
// instance, creating it if missing, initializing specified tables.
func CreateOrOpenDB(ctx *context.T, sbService string, tables []sbmodel.TableSpec) (nosql.Database, error) {
	aclFull := access.Permissions{}
	// Allow everyone to resolve to allow joining syncgroups.
	AddPermsForPattern(&aclFull, string(security.AllPrincipals), access.Resolve)
	// Restrict other permissions to self.
	AddPermsForPrincipal(&aclFull, v23.GetPrincipal(ctx), access.Read, access.Write, access.Admin)

	aclReadOnly := access.Permissions{}
	// Allow everyone to resolve to allow joining syncgroups.
	AddPermsForPattern(&aclReadOnly, string(security.AllPrincipals), access.Resolve)
	// Restrict other permissions to self, except Write.
	AddPermsForPrincipal(&aclReadOnly, v23.GetPrincipal(ctx), access.Read, access.Admin)

	sbs := syncbase.NewService(sbService)
	app := sbs.App(config.AppName)
	if err := createIfMissing(ctx, app, aclFull); err != nil {
		return nil, err
	}

	// TODO(ivanpi): Add schema version.
	db := app.NoSQLDatabase(config.DBName, nil)
	if err := createIfMissing(ctx, db, aclFull); err != nil {
		return nil, err
	}

	// TODO(ivanpi): Add table schemas when available.
	for _, ts := range tables {
		tb := db.Table(ts.Prototype.Table())
		acl := aclReadOnly
		if !ts.ReadOnly {
			acl = aclFull
		}
		if err := createIfMissing(ctx, tb, acl); err != nil {
			return nil, err
		}
	}

	return db, nil
}

// creatable is satisfied by Syncbase hierarchy layers (app, db, table) that
// can be created and tested for existence.
type creatable interface {
	Create(ctx *context.T, acl access.Permissions) error
	Exists(ctx *context.T) (bool, error)
}

// createIfMissing checks if the given creatable layer exists and, if not,
// creates it.
// TODO(ivanpi): Syncbase client helpers for MustExist / CreateIfMissing.
func createIfMissing(ctx *context.T, target creatable, acl access.Permissions) error {
	if exists, err := target.Exists(ctx); err != nil {
		return err
	} else if exists {
		return nil
	}
	if err := target.Create(ctx, acl); err != nil && verror.ErrorID(err) != verror.ErrExist.ID {
		return err
	}
	return nil
}

// AddPermsForPrincipal adds to the ACL all specified permissions for all
// default blessings of the provided principal.
func AddPermsForPrincipal(acl *access.Permissions, principal security.Principal, tags ...access.Tag) {
	for _, pattern := range security.DefaultBlessingPatterns(principal) {
		AddPermsForPattern(acl, string(pattern), tags...)
	}
}

// AddPermsForPattern adds to the ACL all specified permissions for the
// specified pattern.
func AddPermsForPattern(acl *access.Permissions, pattern string, tags ...access.Tag) {
	for _, tag := range tags {
		acl.Add(security.BlessingPattern(pattern), string(tag))
	}
}
