// 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/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 collections.
func CreateOrOpenDB(ctx *context.T, sbService string, collections []sbmodel.CollectionSpec) (syncbase.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.Database(config.DBName, nil)
	if err := createIfMissing(ctx, db, aclFull); err != nil {
		return nil, err
	}

	// TODO(ivanpi): Add schemas when available.
	for _, ts := range collections {
		tb := db.Collection(ts.Prototype.Collection())
		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, collection)
// 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))
	}
}
