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

import (
	"os"
	"path/filepath"
	"strings"
	"sync"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/verror"

	"v.io/x/lib/vlog"
	"v.io/x/lock"
)

const (
	claimFileName        = "claimed_lock"
	keyBlessingExtension = "key"
)

type unclaimedLock struct {
	configDir string
	claimed   chan<- struct{} // GUARDED_BY(mu)

	// Mutex to ensure that a successful claim can happen at most once.
	mu sync.Mutex
}

func (ul *unclaimedLock) Claim(ctx *context.T, call rpc.ServerCall, name string) (security.Blessings, error) {
	vlog.Infof("Claim called by %q", call.Security().RemoteBlessings())
	if strings.ContainsAny(name, security.ChainSeparator) {
		// TODO(ataly, ashankar): We have to error out in this case because of the current
		// neighborhood setup wherein the neighborhood-name of a claimed lock's mounttable is
		// the same as the locks's name. Since neighborhood-names aren't allowed to contain
		// slashes, we have to disallow slashes in the lock name as well.
		return security.Blessings{}, NewErrInvalidLockName(ctx, name, security.ChainSeparator)
	}

	var (
		principal   = v23.GetPrincipal(ctx)
		origDefault = principal.BlessingStore().Default()
		restore     = func() error {
			// TODO(ataly): Remove roots of current default blessing if needed
			// (i.e., if current default != origDefault).
			if err := principal.BlessingStore().SetDefault(origDefault); err != nil {
				return verror.Convert(verror.ErrInternal, ctx, err)
			}
			return nil
		}
	)

	defer ul.mu.Unlock()
	ul.mu.Lock()

	if ul.claimed == nil {
		return security.Blessings{}, NewErrLockAlreadyClaimed(ctx)
	}

	keyBlessing, err := ul.makeKey(principal, name, call.Security().RemoteBlessings().PublicKey())
	if err != nil {
		restore()
		return security.Blessings{}, verror.Convert(verror.ErrInternal, ctx, err)
	}

	// Create a file in the config directory to indicate that lock has been claimed.
	f, err := os.Create(filepath.Join(ul.configDir, claimFileName))
	if err != nil {
		restore()
		return security.Blessings{}, verror.Convert(verror.ErrInternal, ctx, err)
	}
	f.Close()

	close(ul.claimed)
	ul.claimed = nil
	vlog.Infof("Lock successfullly claimed with name %q", name)
	return keyBlessing, nil
}

func (ul *unclaimedLock) makeKey(principal security.Principal, name string, remoteKey security.PublicKey) (security.Blessings, error) {
	lockBlessing, err := principal.BlessSelf(name)
	if err != nil {
		return security.Blessings{}, err
	}

	if err := principal.BlessingStore().SetDefault(lockBlessing); err != nil {
		return security.Blessings{}, err
	}
	if err := principal.AddToRoots(lockBlessing); err != nil {
		return security.Blessings{}, err
	}

	// Add a caveat to the "key" blessing so that it can only be used to talking
	// to this lock object.
	// TODO(ataly): Add a client-only caveat as well so that someone who obtains
	// this blessing or an extension of it cannot maliciously (or accidentally)
	// start a server with this blessing (such a server could impersonate this
	// lock object).
	peerPattern := security.BlessingPattern(name)
	onlyThisLockCav, err := security.NewCaveat(security.PeerBlessingsCaveat, []security.BlessingPattern{peerPattern})
	if err != nil {
		return security.Blessings{}, err
	}
	keyBlessing, err := principal.Bless(remoteKey, lockBlessing, keyBlessingExtension, onlyThisLockCav)
	if err != nil {
		return security.Blessings{}, err
	}
	return keyBlessing, nil
}

func isLockClaimed(configDir string) bool {
	if _, err := os.Stat(filepath.Join(configDir, claimFileName)); err == nil {
		return true
	}
	return false
}

func newUnclaimedLock(claimed chan<- struct{}, configDir string) lock.UnclaimedLockServerStub {
	return lock.UnclaimedLockServer(&unclaimedLock{configDir: configDir, claimed: claimed})
}
