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

// +build java android

package security

import (
	"fmt"
	"log"
	"runtime"
	"unsafe"

	"v.io/v23/security"
	jutil "v.io/x/jni/util"
)

// #include "jni.h"
import "C"

// JavaPrincipal converts the provided Go Principal into a Java VPrincipal
// object.
// NOTE: Because CGO creates package-local types and because this method may be
// invoked from a different package, Java types are passed in an empty interface
// and then cast into their package local types.
func JavaPrincipal(jEnv interface{}, principal security.Principal) (unsafe.Pointer, error) {
	if principal == nil {
		return nil, nil
	}
	jPrincipal, err := jutil.NewObject(jEnv, jVPrincipalImplClass, []jutil.Sign{jutil.LongSign, signerSign, blessingStoreSign, blessingRootsSign}, int64(jutil.PtrValue(&principal)), C.jobject(nil), C.jobject(nil), C.jobject(nil))
	if err != nil {
		return nil, err
	}
	jutil.GoRef(&principal) // Un-refed when the Java VPrincipalImpl is finalized.
	return jPrincipal, nil
}

// GoPrincipal converts the provided Java VPrincipal object into a Go Principal.
// NOTE: Because CGO creates package-local types and because this method may be
// invoked from a different package, Java types are passed in an empty interface
// and then cast into their package local types.
func GoPrincipal(jEnv, jPrincipalObj interface{}) (security.Principal, error) {
	if jutil.IsNull(jPrincipalObj) {
		return nil, nil
	}
	// Reference Java VPrincipal; it will be de-referenced when the Go Principal
	// created below is garbage-collected (through the finalizer callback we
	// setup just below).
	jPrincipal := C.jobject(jutil.NewGlobalRef(jEnv, jPrincipalObj))
	// Create Go Principal.
	p := &principal{
		jPrincipal: jPrincipal,
	}
	runtime.SetFinalizer(p, func(p *principal) {
		jEnv, freeFunc := jutil.GetEnv()
		env := (*C.JNIEnv)(jEnv)
		defer freeFunc()
		jutil.DeleteGlobalRef(env, p.jPrincipal)
	})
	return p, nil
}

type principal struct {
	jPrincipal C.jobject
}

func (p *principal) Bless(key security.PublicKey, with security.Blessings, extension string, caveat security.Caveat, additionalCaveats ...security.Caveat) (security.Blessings, error) {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()

	jKey, err := JavaPublicKey(env, key)
	if err != nil {
		return security.Blessings{}, err
	}
	jWith, err := JavaBlessings(env, with)
	if err != nil {
		return security.Blessings{}, err
	}
	jCaveat, err := JavaCaveat(env, caveat)
	if err != nil {
		return security.Blessings{}, err
	}
	jAdditionalCaveats, err := JavaCaveats(env, additionalCaveats)
	if err != nil {
		return security.Blessings{}, err
	}
	jBlessings, err := jutil.CallObjectMethod(env, p.jPrincipal, "bless", []jutil.Sign{publicKeySign, blessingsSign, jutil.StringSign, caveatSign, jutil.ArraySign(caveatSign)}, blessingsSign, jKey, jWith, extension, jCaveat, jAdditionalCaveats)
	if err != nil {
		return security.Blessings{}, err
	}
	return GoBlessings(env, jBlessings)
}

func (p *principal) BlessSelf(name string, caveats ...security.Caveat) (security.Blessings, error) {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jCaveats, err := JavaCaveats(env, caveats)
	if err != nil {
		return security.Blessings{}, err
	}
	jBlessings, err := jutil.CallObjectMethod(env, p.jPrincipal, "blessSelf", []jutil.Sign{jutil.StringSign, jutil.ArraySign(caveatSign)}, blessingsSign, name, jCaveats)
	if err != nil {
		return security.Blessings{}, err
	}
	return GoBlessings(env, jBlessings)
}

func (p *principal) Sign(message []byte) (security.Signature, error) {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jSig, err := jutil.CallObjectMethod(env, p.jPrincipal, "sign", []jutil.Sign{jutil.ArraySign(jutil.ByteSign)}, signatureSign, message)
	if err != nil {
		return security.Signature{}, err
	}
	return GoSignature(env, jSig)
}

func (p *principal) MintDischarge(forThirdPartyCaveat, caveatOnDischarge security.Caveat, additionalCaveatsOnDischarge ...security.Caveat) (security.Discharge, error) {
	return security.Discharge{}, fmt.Errorf("MintDischarge not yet implemented")
}

func (p *principal) PublicKey() security.PublicKey {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jPublicKey, err := jutil.CallObjectMethod(env, p.jPrincipal, "publicKey", nil, publicKeySign)
	if err != nil {
		log.Printf("Couldn't get Java public key: %v", err)
		return nil
	}
	key, err := GoPublicKey(env, C.jobject(jPublicKey))
	if err != nil {
		log.Printf("Couldn't convert Java public key to Go: %v", err)
		return nil
	}
	return key
}

func (p *principal) BlessingsByName(name security.BlessingPattern) []security.Blessings {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jName, err := JavaBlessingPattern(env, name)
	if err != nil {
		log.Printf("Couldn't convert Go blessing pattern: %v", err)
		return nil
	}
	barr, err := jutil.CallObjectArrayMethod(env, p.jPrincipal, "blessingsByName", []jutil.Sign{blessingPatternSign}, blessingsSign, jName)
	if err != nil {
		log.Printf("Couldn't get Java blessings for name: %v", err)
		return nil
	}
	ret := make([]security.Blessings, len(barr))
	for i, jBlessings := range barr {
		var err error
		if ret[i], err = GoBlessings(env, jBlessings); err != nil {
			log.Printf("Couldn't convert Java blessings to Go: %v", err)
			return nil
		}
	}
	return ret
}

func (p *principal) BlessingsInfo(blessings security.Blessings) map[string][]security.Caveat {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jBlessings, err := JavaBlessings(env, blessings)
	if err != nil {
		log.Printf("Couldn't convert Go blessings to Java: %v", err)
		return nil
	}
	infomap, err := jutil.CallMapMethod(env, p.jPrincipal, "blessingsInfo", []jutil.Sign{blessingsSign}, jBlessings)
	if err != nil {
		log.Printf("Couldn't get Java blessings info: %v", err)
		return nil
	}
	ret := make(map[string][]security.Caveat)
	for jName, jCaveats := range infomap {
		name := jutil.GoString(env, jName)
		caveats, err := GoCaveats(env, jCaveats)
		if err != nil {
			log.Printf("Couldn't convert Java Caveats to Go: %v", err)
			return nil
		}
		ret[name] = caveats
	}
	return ret
}

func (p *principal) BlessingStore() security.BlessingStore {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jBlessingStore, err := jutil.CallObjectMethod(env, p.jPrincipal, "blessingStore", nil, blessingStoreSign)
	if err != nil {
		log.Printf("Couldn't get Java Blessing Store: %v", err)
		return nil
	}
	store, err := GoBlessingStore(env, C.jobject(jBlessingStore))
	if err != nil {
		log.Printf("Couldn't convert Java Blessing Store to Go: %v", err)
		return nil
	}
	return store
}

func (p *principal) Roots() security.BlessingRoots {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jBlessingRoots, err := jutil.CallObjectMethod(env, p.jPrincipal, "roots", nil, blessingRootsSign)
	if err != nil {
		log.Printf("Couldn't get Java Blessing Roots: %v", err)
		return nil
	}
	roots, err := GoBlessingRoots(env, C.jobject(jBlessingRoots))
	if err != nil {
		log.Printf("Couldn't convert Java Blessing Roots to Go: %v", err)
		return nil
	}
	return roots
}

func (p *principal) AddToRoots(blessings security.Blessings) error {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jBlessings, err := JavaBlessings(env, blessings)
	if err != nil {
		return err
	}
	return jutil.CallVoidMethod(env, p.jPrincipal, "addToRoots", []jutil.Sign{blessingsSign}, jBlessings)
}
