// Binary pbankd is a simple implementation of the bank service.
// Binary bank clients can connect to this bank service to manage virtual bank
// accounts. Unlike bankd, pbankd uses the Veyron Store. It can recover user
// data after a crash, but it must always connect to the stored service.
// Unlike bankd, pbankd prevents race conditions with transactions.
package main

// ---------------------------------------------------------
// NOTE(kash): This file is commented out because we are making large changes
// to the Store API and we don't want to repeatedly update this example.
// Additionally, the server uses a common transaction across all requests,
// so there is a pretty bad race condition that we don't want people to
// copy.  The only reason we are keeping this file is because it demonstrates
// how to write a custom dispatcher.
// ---------------------------------------------------------

// import (
// 	"errors"
// 	"flag"
// 	"fmt"
// 	"math/rand"
// 	"os"
// 	"os/user"
// 	"path/filepath"
// 	"reflect"
// 	"regexp"
// 	"strings"
// 	"time"

// 	"veyron/examples/bank"
// 	"veyron/examples/bank/schema"
// 	"veyron/lib/signals"
// 	vsecurity "veyron/security"
// 	"veyron/security/caveat"
// 	idutil "veyron/services/identity/util"

// 	"veyron2"
// 	"veyron2/ipc"
// 	"veyron2/naming"
// 	"veyron2/rt"
// 	"veyron2/security"
// 	"veyron2/storage"
// 	"veyron2/storage/vstore"
// 	"veyron2/vlog"
// )

// // Duration of a bank account blessing, intended to be very long.
// const BLESS_DURATION = 24 * 10000 * time.Hour

// // Ensure that account numbers are all 6 digits long.
// const MIN_ACCOUNT_NUMBER = 100000
// const MAX_ACCOUNT_NUMBER = 999999
// const SUFFIX_REGEXP = "/[0-9]{6}"

// // Where we will store the bank in the store database.
// const BANK_ROOT string = "/Bank"

// var (
// 	storeName string
// 	ACCOUNTS  string
// 	runtime   veyron2.Runtime
// )

// func init() {
// 	username := "unknown"
// 	if u, err := user.Current(); err == nil {
// 		username = u.Username
// 	}
// 	hostname := "unknown"
// 	if h, err := os.Hostname(); err == nil {
// 		hostname = h
// 	}
// 	dir := "global/vstore/" + hostname + "/" + username

// 	// Parse the flags (variableName, flagName, defaultValue, description)
// 	flag.StringVar(&storeName, "store", dir, "Name of the Veyron store")

// 	// Set the random seed to the current time to increase psuedorandomness.
// 	rand.Seed(time.Now().Unix())

// 	// Set the name for the ACCOUNTS 'constant'. TODO(alexfandrianto): Is there a better way to know the field is named "Accounts"?
// 	ACCOUNTS = reflect.TypeOf(schema.Bank{}).Field(0).Name
// }

// // The following struct and functions handle construction of the persistent bank.
// type pbankd struct {
// 	// Pointer to the store
// 	store storage.Store

// 	// Current Transaction name; empty if there's no transaction
// 	tname string

// 	// The bank's private ID (used for blessing)
// 	ID security.PrivateID
// }

// // newPbankd creates a new persistent bank structure.
// func newPbankd(store storage.Store, identity security.PrivateID) *pbankd {
// 	b := &pbankd{
// 		store: store,
// 		ID:    identity,
// 	}
// 	return b
// }

// // InitializeBank bank details in the store; currently only initializes the root.
// func (b *pbankd) initializeBank() {
// 	if err := b.newTransaction(); err != nil {
// 		vlog.Fatal(err)
// 	}
// 	// NOTE(sadovsky): initializeBankRoot ought to return an error. Currently,
// 	// some errors (e.g. failed puts) could slip through unnoticed.
// 	b.initializeBankRoot()
// 	if err := b.commit(); err != nil {
// 		vlog.Fatal(err)
// 	}
// }

// // initializeBankRoot prepares the bank root as BANK_ROOT if it isn't yet in the Veyron store.
// func (b *pbankd) initializeBankRoot() {
// 	// Create parent directories for the bank root, if necessary
// 	l := strings.Split(BANK_ROOT, "/")
// 	fmt.Println(l)
// 	for i, _ := range l {
// 		fmt.Println(i)
// 		prefix := filepath.Join(l[:i]...)
// 		o := b.store.BindObject(naming.Join(b.tname, prefix))
// 		if exist, err := o.Exists(runtime.TODOContext()); err != nil {
// 			vlog.Infof("Error checking existence at %q: %s", prefix, err)
// 		} else if !exist {
// 			if _, err := o.Put(runtime.TODOContext(), &schema.Dir{}); err != nil {
// 				vlog.Infof("Error creating parent %q: %s", prefix, err)
// 			}
// 			fmt.Printf("%q was created!\n", prefix)
// 		} else {
// 			fmt.Printf("%q was already present in the store.\n", prefix)
// 		}
// 	}

// 	// Add the bank schema to the store at BANK_ROOT, if necessary
// 	o := b.store.BindObject(naming.Join(b.tname, BANK_ROOT))
// 	if exist, err := o.Exists(runtime.TODOContext()); err != nil {
// 		vlog.Infof("Error checking existence at %q: %s", BANK_ROOT, err)
// 	} else if !exist {
// 		_, err := o.Put(runtime.TODOContext(), &schema.Bank{})
// 		if err != nil {
// 			vlog.Infof("Error creating bank at %q: %s", BANK_ROOT, err)
// 		}
// 	}
// }

// // Register creates an account for a new user with the given bankName.
// func (b *pbankd) Connect(context ipc.ServerContext) (string, int64, error) {
// 	// Check if the RemoteID() has been blessed by the bank
// 	if num := getBankAccountNumber(context); num != 0 {
// 		// Look up the user and return their bank account number
// 		fmt.Println("This client is blessed!")
// 		fmt.Printf("ID: %d\n", num)
// 		return "", num, nil
// 	} else {
// 		fmt.Println("This client isn't blessed. Let's bless them!")
// 		// Use the store
// 		if err := b.newTransaction(); err != nil {
// 			vlog.Fatal(err)
// 		}

// 		// Keep rolling until we get an unseen number
// 		randID := rand.Int63n(MAX_ACCOUNT_NUMBER-MIN_ACCOUNT_NUMBER) + MIN_ACCOUNT_NUMBER
// 		for b.isUser(randID) {
// 			randID = rand.Int63n(MAX_ACCOUNT_NUMBER-MIN_ACCOUNT_NUMBER) + MIN_ACCOUNT_NUMBER
// 		}
// 		fmt.Printf("ID: %d\n", randID)

// 		// Bless the user
// 		pp := security.PrincipalPattern(context.LocalID().Names()[0])
// 		pID, err := b.ID.Bless(
// 			context.RemoteID(),
// 			fmt.Sprintf("%d", randID),
// 			BLESS_DURATION,
// 			[]security.ServiceCaveat{security.UniversalCaveat(caveat.PeerIdentity{pp})},
// 		)
// 		if err != nil {
// 			vlog.Fatal(err)
// 		}

// 		// Encode the public ID
// 		enc, err := idutil.Base64VomEncode(pID)
// 		if err != nil {
// 			vlog.Fatal(err)
// 		}

// 		// Store the user into the database
// 		b.registerNewUser(randID)
// 		err = b.commit()
// 		if err != nil {
// 			vlog.Fatal(err)
// 		}

// 		// Ensure the new user is a user before returning the blessing and ID
// 		if b.isUser(randID) {
// 			return enc, randID, nil
// 		}
// 		return "", 0, fmt.Errorf("failed to register user")
// 	}
// }

// // Deposit adds the amount given to this account.
// func (b *pbankd) Deposit(context ipc.ServerContext, amount int64) error {
// 	user := getBankAccountNumber(context)
// 	if user == 0 {
// 		return fmt.Errorf("couldn't retrieve account number")
// 	}
// 	if err := b.newTransaction(); err != nil {
// 		return err
// 	}
// 	if !b.isUser(user) {
// 		return fmt.Errorf("user isn't registered")
// 	} else if amount < 0 {
// 		return fmt.Errorf("deposit amount %d is negative", amount)
// 	}
// 	b.changeBalance(user, amount)
// 	return b.commit()
// }

// // Withdraw reduces the amount given from this account.
// func (b *pbankd) Withdraw(context ipc.ServerContext, amount int64) error {
// 	user := getBankAccountNumber(context)
// 	if user == 0 {
// 		return fmt.Errorf("couldn't retrieve account number")
// 	}
// 	if err := b.newTransaction(); err != nil {
// 		return err
// 	}
// 	if !b.isUser(user) {
// 		return fmt.Errorf("user isn't registered")
// 	} else if amount < 0 {
// 		return fmt.Errorf("withdraw amount %d is negative", amount)
// 	} else if balance := b.checkBalance(user); amount > balance {
// 		return fmt.Errorf("withdraw amount %d exceeds balance %d", amount, balance)
// 	}
// 	b.changeBalance(user, -amount)
// 	return b.commit()
// }

// // Transfer moves the amount given to the receiver.
// func (b *pbankd) Transfer(context ipc.ServerContext, accountNumber int64, amount int64) error {
// 	user := getBankAccountNumber(context)
// 	if user == 0 {
// 		return fmt.Errorf("couldn't retrieve account number")
// 	}
// 	if err := b.newTransaction(); err != nil {
// 		return err
// 	}
// 	if !b.isUser(user) {
// 		return fmt.Errorf("user isn't registered")
// 	} else if !b.isUser(accountNumber) {
// 		return fmt.Errorf("%d isn't registered", accountNumber)
// 	} else if amount < 0 {
// 		return fmt.Errorf("transfer amount %d is negative", amount)
// 	} else if balance := b.checkBalance(user); amount > balance {
// 		return fmt.Errorf("transfer amount %d exceeds balance %d", amount, balance)
// 	}
// 	b.changeBalance(user, -amount)
// 	b.changeBalance(accountNumber, amount)
// 	return b.commit()
// }

// // Balance returns the amount stored by the given user.
// // Throws an error if the user is invalid.
// func (b *pbankd) Balance(context ipc.ServerContext) (int64, error) {
// 	user := getBankAccountNumber(context)
// 	if user == 0 {
// 		return 0, fmt.Errorf("couldn't retrieve account number")
// 	}
// 	if !b.isUser(user) {
// 		return 0, fmt.Errorf("user isn't registered")
// 	}
// 	return b.checkBalance(user), nil
// }

// /*
//  Helper functions for the persistent bank service that deal with store access.
// */

// // newTransaction starts a new transaction.
// func (b *pbankd) newTransaction() error {
// 	tid, err := b.store.BindTransactionRoot("").CreateTransaction(runtime.TODOContext())
// 	if err != nil {
// 		b.tname = ""
// 		return err
// 	}
// 	b.tname = tid // Transaction is rooted at "", so tname == tid.
// 	return nil
// }

// // commit commits the current transaction.
// func (b *pbankd) commit() error {
// 	if b.tname == "" {
// 		return errors.New("No transaction to commit")
// 	}
// 	err := b.store.BindTransaction(b.tname).Commit(runtime.TODOContext())
// 	b.tname = ""
// 	if err != nil {
// 		return fmt.Errorf("Failed to commit transaction: %s", err)
// 	}
// 	return nil
// }

// // isUser helps determine if the given user is part of the system or not.
// func (b *pbankd) isUser(accountNumber int64) bool {
// 	// If this is a user, their location in the store should exist.
// 	prefix := filepath.Join(BANK_ROOT, ACCOUNTS, fmt.Sprintf("%d", accountNumber))
// 	o := b.store.BindObject(naming.Join(b.tname, prefix))
// 	exist, err := o.Exists(runtime.TODOContext())
// 	if err != nil {
// 		vlog.Infof("Error checking existence at %s: %s", prefix, err)
// 		return false
// 	}
// 	return exist
// }

// // Obtains the bank account number of the user. Returns 0 if it could not be found.
// func getBankAccountNumber(context ipc.ServerContext) int64 {
// 	bankName := context.LocalID().Names()[0]

// 	// Untrusted clients have no names.
// 	if len(context.RemoteID().Names()) == 0 {
// 		return 0
// 	}

// 	// Otherwise, extract the account number from the name.
// 	name := context.RemoteID().Names()[0]
// 	if match, err := regexp.MatchString(bankName+SUFFIX_REGEXP, name); err != nil {
// 		vlog.Infof("MatchString error: %s", err)
// 		return 0
// 	} else if !match {
// 		vlog.Infof("No matching name found")
// 		return 0
// 	}
// 	var v int64
// 	_, err := fmt.Sscanf(name, bankName+"/%d", &v)
// 	if err != nil {
// 		vlog.Infof("Failure to parse ID from %s: %s", name, err)
// 		return 0
// 	}
// 	return v
// }

// // registerNewUser adds the user to the system under the specified name and returns success.
// func (b *pbankd) registerNewUser(user int64) {
// 	// Create the user's account
// 	prefix := filepath.Join(BANK_ROOT, ACCOUNTS, fmt.Sprintf("%d", user))
// 	o := b.store.BindObject(naming.Join(b.tname, prefix))
// 	if _, err := o.Put(runtime.TODOContext(), int64(0)); err != nil {
// 		vlog.Infof("Error creating %s: %s", prefix, err)
// 	}
// }

// // checkBalance gets the user's balance from the store
// func (b *pbankd) checkBalance(user int64) int64 {
// 	prefix := filepath.Join(BANK_ROOT, ACCOUNTS, fmt.Sprintf("%d", user))
// 	o := b.store.BindObject(naming.Join(b.tname, prefix))
// 	e, err := o.Get(runtime.TODOContext())
// 	if err != nil {
// 		vlog.Infof("Error getting %s: %s", prefix, err)
// 	}
// 	value, _ := e.Value.(int64)
// 	return value
// }

// // changeBalance modifies the user's balance in the store
// func (b *pbankd) changeBalance(user int64, amount int64) {
// 	prefix := filepath.Join(BANK_ROOT, ACCOUNTS, fmt.Sprintf("%d", user))
// 	o := b.store.BindObject(naming.Join(b.tname, prefix))
// 	e, err := o.Get(runtime.TODOContext())
// 	if err != nil {
// 		vlog.Infof("Error getting %s: %s", prefix, err)
// 	}
// 	if _, err := o.Put(runtime.TODOContext(), e.Value.(int64)+amount); err != nil {
// 		vlog.Infof("Error changing %s: %s", prefix, err)
// 	}
// }

// // This custom bank dispatcher has two interfaces with distinct authorizers.
// func newBankDispatcher(bankServer interface{}, bankAccountServer interface{}, authBank security.Authorizer, authBankAccount security.Authorizer) ipc.Dispatcher {
// 	return BankDispatcher{ipc.ReflectInvoker(bankServer), ipc.ReflectInvoker(bankAccountServer), authBank, authBankAccount}
// }

// type BankDispatcher struct {
// 	invokerBank        ipc.Invoker
// 	invokerBankAccount ipc.Invoker
// 	authBank           security.Authorizer
// 	authBankAccount    security.Authorizer
// }

// func (d BankDispatcher) Lookup(suffix string) (ipc.Invoker, security.Authorizer, error) {
// 	fmt.Println("Dispatcher Lookup Suffix:", suffix)
// 	if suffix != "" {
// 		return d.invokerBankAccount, d.authBankAccount, nil
// 	}
// 	return d.invokerBank, d.authBank, nil
// }

// // The custom account authorizer checks if the RemoteID matches a regexp pattern and allows only Reads and Writes.
// type AccountAuthorizer string

// func (aa AccountAuthorizer) Authorize(ctx security.Context) error {
// 	name := ctx.RemoteID().Names()[0]
// 	match, err := regexp.MatchString(string(aa), name)
// 	fmt.Printf("Authorizing for Account %s %t\n", name, match)
// 	if err != nil {
// 		return err
// 	}
// 	if match {
// 		if ctx.Label() != security.ReadLabel && ctx.Label() != security.WriteLabel {
// 			return errors.New("unauthorized; may only read or write")
// 		}
// 		return nil
// 	}
// 	return errors.New("unauthorized to access account")
// }

func main() {
	// 	// Create a new server instance.
	// 	runtime = rt.Init()
	// 	s, err := runtime.NewServer()
	// 	if err != nil {
	// 		vlog.Fatal("failure creating server: ", err)
	// 	}

	// 	// Connect to the Veyron Store
	// 	vlog.Infof("Binding to store on %s", storeName)
	// 	st, err := vstore.New(storeName)
	// 	if err != nil {
	// 		vlog.Fatalf("Can't connect to store: %s: %s", storeName, err)
	// 	}

	// 	// Create the bank server and bank account server stubs, using the store connection
	// 	pbankd := newPbankd(st, runtime.Identity())
	// 	pbankd.initializeBank()
	// 	bankServer := bank.NewServerBank(pbankd)
	// 	bankAccountServer := bank.NewServerBankAccount(pbankd)

	// 	// Setup bank and account authorizers.
	//  bankAuth := vsecurity.NewACLAuthorizer(security.NewWhitelistACL(
	// 		map[security.PrincipalPattern]security.LabelSet{
	// 			security.AllPrincipals: security.LabelSet(security.ReadLabel | security.WriteLabel),
	// 		}))
	// 	bankAccountAuth := AccountAuthorizer(runtime.Identity().PublicID().Names()[0] + SUFFIX_REGEXP)

	// 	dispatcher := newBankDispatcher(bankServer, bankAccountServer, bankAuth, bankAccountAuth)

	// 	// Create an endpoint and begin listening.
	// 	endpoint, err := s.Listen("tcp", "127.0.0.1:0")
	// 	if err == nil {
	// 		fmt.Printf("Listening at: %v\n", endpoint)
	// 	} else {
	// 		vlog.Fatal("error listening to service: ", err)
	// 	}

	// 	// Publish the service in the mount table.
	// 	mountName := "veyron/bank"
	// 	fmt.Printf("Mounting bank on %s, endpoint /%s\n", mountName, endpoint)
	// 	if err := s.Serve(mountName, dispatcher); err != nil {
	// 		vlog.Fatal("s.Serve() failed: ", err)
	// 	}

	// 	// Wait forever.
	// 	<-signals.ShutdownOnSignals()
}
