// Package agent provides a client for communicating with an "Agent"
// process holding the private key for an identity.
package agent

import (
	"fmt"
	"net"
	"os"

	"veyron.io/veyron/veyron/lib/unixfd"
	"veyron.io/veyron/veyron2/context"
	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/naming"
	"veyron.io/veyron/veyron2/security"
	"veyron.io/veyron/veyron2/vdl/vdlutil"
	"veyron.io/veyron/veyron2/vlog"
)

// FdVarName is the name of the environment variable containing
// the file descriptor for talking to the agent.
const FdVarName = "VEYRON_AGENT_FD"

type client struct {
	caller caller
	key    security.PublicKey
}

type caller struct {
	client ipc.Client
	name   string
	ctx    context.T
}

func (c *caller) call(name string, results []interface{}, args ...interface{}) (err error) {
	var call ipc.Call
	results = append(results, &err)
	if call, err = c.client.StartCall(c.ctx, c.name, name, args); err == nil {
		if ierr := call.Finish(results...); ierr != nil {
			err = ierr
		}
	}
	return
}

func results(inputs ...interface{}) []interface{} {
	if len(inputs) > 0 {
		return inputs
	}
	return make([]interface{}, 0)
}

// NewAgentPrincipal returns a security.Pricipal using the PrivateKey held in a remote agent process.
// 'fd' is the socket for connecting to the agent, typically obtained from
// os.GetEnv(agent.FdVarName).
// 'ctx' should not have a deadline, and should never be cancelled.
func NewAgentPrincipal(c ipc.Client, fd int, ctx context.T) (security.Principal, error) {
	f := os.NewFile(uintptr(fd), "agent_client")
	defer f.Close()
	conn, err := net.FileConn(f)
	if err != nil {
		return nil, err
	}
	// This is just an arbitrary 1 byte string. The value is ignored.
	data := make([]byte, 1)
	addr, err := unixfd.SendConnection(conn.(*net.UnixConn), data, true)
	if err != nil {
		return nil, err
	}
	caller := caller{
		client: c,
		name:   naming.JoinAddressName(naming.FormatEndpoint(addr.Network(), addr.String()), ""),
		ctx:    ctx,
	}

	agent := &client{caller: caller}
	if err := agent.fetchPublicKey(); err != nil {
		return nil, err
	}
	return agent, nil
}

func (c *client) fetchPublicKey() (err error) {
	var b []byte
	if err = c.caller.call("PublicKey", results(&b)); err != nil {
		return
	}
	c.key, err = security.UnmarshalPublicKey(b)
	return
}

func (c *client) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) {
	var blessings security.WireBlessings
	marshalledKey, err := key.MarshalBinary()
	if err != nil {
		return nil, err
	}
	err = c.caller.call("Bless", results(&blessings), marshalledKey, security.MarshalBlessings(with), extension, caveat, additionalCaveats)
	if err != nil {
		return nil, err
	}
	return security.NewBlessings(blessings)
}

func (c *client) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) {
	var blessings security.WireBlessings
	err := c.caller.call("BlessSelf", results(&blessings), name, caveats)
	if err != nil {
		return nil, err
	}
	return security.NewBlessings(blessings)
}

func (c *client) Sign(message []byte) (sig security.Signature, err error) {
	err = c.caller.call("Sign", results(&sig), message)
	return
}

func (c *client) MintDischarge(tp security.ThirdPartyCaveat, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Discharge, error) {
	var discharge security.Discharge
	err := c.caller.call("MintDischarge", results(&discharge), vdlutil.Any(tp), caveat, additionalCaveats)
	if err != nil {
		return nil, err
	}
	return discharge, nil
}

func (c *client) PublicKey() security.PublicKey {
	return c.key
}

func (c *client) BlessingStore() security.BlessingStore {
	return &blessingStore{c.caller, c.key}
}

func (c *client) Roots() security.BlessingRoots {
	return &blessingRoots{c.caller}
}

func (c *client) AddToRoots(blessings security.Blessings) error {
	return c.caller.call("AddToRoots", results(), security.MarshalBlessings(blessings))
}

type blessingStore struct {
	caller caller
	key    security.PublicKey
}

func (b *blessingStore) Set(blessings security.Blessings, forPeers security.BlessingPattern) (security.Blessings, error) {
	var resultBlessings security.WireBlessings
	err := b.caller.call("BlessingStoreSet", results(&resultBlessings), security.MarshalBlessings(blessings), forPeers)
	if err != nil {
		return nil, err
	}
	return security.NewBlessings(resultBlessings)
}

func (b *blessingStore) ForPeer(peerBlessings ...string) security.Blessings {
	var resultBlessings security.WireBlessings
	err := b.caller.call("BlessingStoreForPeer", results(&resultBlessings), peerBlessings)
	if err != nil {
		vlog.Errorf("error calling BlessingStoreForPeer: %v", err)
		return nil
	}
	blessings, err := security.NewBlessings(resultBlessings)
	if err != nil {
		vlog.Errorf("error creating Blessings from WireBlessings: %v", err)
		return nil
	}
	return blessings
}

func (b *blessingStore) SetDefault(blessings security.Blessings) error {
	return b.caller.call("BlessingStoreSetDefault", results(), security.MarshalBlessings(blessings))
}

func (b *blessingStore) Default() security.Blessings {
	var resultBlessings security.WireBlessings
	err := b.caller.call("BlessingStoreDefault", results(&resultBlessings))
	if err != nil {
		vlog.Errorf("error calling BlessingStoreDefault: %v", err)
		return nil
	}
	blessings, err := security.NewBlessings(resultBlessings)
	if err != nil {
		vlog.Errorf("error creating Blessing from WireBlessings: %v", err)
		return nil
	}
	return blessings
}

func (b *blessingStore) PublicKey() security.PublicKey {
	return b.key
}

func (b *blessingStore) DebugString() (s string) {
	err := b.caller.call("BlessingStoreDebugString", results(&s))
	if err != nil {
		s = fmt.Sprintf("error calling BlessingStoreDebugString: %v", err)
		vlog.Errorf(s)
	}
	return
}

type blessingRoots struct {
	caller caller
}

func (b *blessingRoots) Add(root security.PublicKey, pattern security.BlessingPattern) error {
	marshalledKey, err := root.MarshalBinary()
	if err != nil {
		return err
	}
	return b.caller.call("BlessingRootsAdd", results(), marshalledKey, pattern)
}

func (b *blessingRoots) Recognized(root security.PublicKey, blessing string) error {
	marshalledKey, err := root.MarshalBinary()
	if err != nil {
		return err
	}
	return b.caller.call("BlessingRootsAdd", results(), marshalledKey, blessing)
}

func (b *blessingRoots) DebugString() (s string) {
	err := b.caller.call("BlessingRootsDebugString", results(&s))
	if err != nil {
		s = fmt.Sprintf("error calling BlessingRootsDebugString: %v", err)
		vlog.Errorf(s)
	}
	return
}
