package trust

import (
	"fmt"
	"time"

	"github.com/docker/docker/engine"
	"github.com/docker/docker/pkg/log"
	"github.com/docker/libtrust"
)

func (t *TrustStore) Install(eng *engine.Engine) error {
	for name, handler := range map[string]engine.Handler{
		"trust_key_check":   t.CmdCheckKey,
		"trust_update_base": t.CmdUpdateBase,
	} {
		if err := eng.Register(name, handler); err != nil {
			return fmt.Errorf("Could not register %q: %v", name, err)
		}
	}
	return nil
}

func (t *TrustStore) CmdCheckKey(job *engine.Job) engine.Status {
	if n := len(job.Args); n != 1 {
		return job.Errorf("Usage: %s NAMESPACE", job.Name)
	}
	var (
		namespace = job.Args[0]
		keyBytes  = job.Getenv("PublicKey")
	)

	if keyBytes == "" {
		return job.Errorf("Missing PublicKey")
	}
	pk, err := libtrust.UnmarshalPublicKeyJWK([]byte(keyBytes))
	if err != nil {
		return job.Errorf("Error unmarshalling public key: %s", err)
	}

	permission := uint16(job.GetenvInt("Permission"))
	if permission == 0 {
		permission = 0x03
	}

	t.RLock()
	defer t.RUnlock()
	if t.graph == nil {
		job.Stdout.Write([]byte("no graph"))
		return engine.StatusOK
	}

	// Check if any expired grants
	verified, err := t.graph.Verify(pk, namespace, permission)
	if err != nil {
		return job.Errorf("Error verifying key to namespace: %s", namespace)
	}
	if !verified {
		log.Debugf("Verification failed for %s using key %s", namespace, pk.KeyID())
		job.Stdout.Write([]byte("not verified"))
	} else if t.expiration.Before(time.Now()) {
		job.Stdout.Write([]byte("expired"))
	} else {
		job.Stdout.Write([]byte("verified"))
	}

	return engine.StatusOK
}

func (t *TrustStore) CmdUpdateBase(job *engine.Job) engine.Status {
	t.fetch()

	return engine.StatusOK
}