// 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 (
	"log"
	"runtime"
	"time"

	jutil "v.io/x/jni/util"
	jcontext "v.io/x/jni/v23/context"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/naming"
	"v.io/v23/security"
	"v.io/v23/vdl"
)

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

// JavaCall converts the provided Go (security) Call into a Java Call object.
func JavaCall(env jutil.Env, call security.Call) (jutil.Object, error) {
	jCall, err := jutil.NewObject(env, jCallImplClass, []jutil.Sign{jutil.LongSign}, int64(jutil.PtrValue(&call)))
	if err != nil {
		return jutil.NullObject, err
	}
	jutil.GoRef(&call) // Un-refed when the Java CallImpl object is finalized.
	return jCall, nil
}

// GoCall creates instance of security.Call that uses the provided Java
// Call as its underlying implementation.
func GoCall(env jutil.Env, jCall jutil.Object) (security.Call, error) {
	if jCall.IsNull() {
		return nil, nil
	}
	if jutil.IsInstanceOf(env, jCall, jCallImplClass) {
		// Called with our implementation of Call, which maintains a Go pointer - use it.
		goPtr, err := jutil.CallLongMethod(env, jCall, "nativePtr", nil)
		if err != nil {
			return nil, err
		}
		return (*(*security.Call)(jutil.NativePtr(goPtr))), nil
	}
	// Reference Java call; it will be de-referenced when the go call
	// created below is garbage-collected (through the finalizer callback we
	// setup just below).
	jCall = jutil.NewGlobalRef(env, jCall)
	call := &callImpl{
		jCall: jCall,
	}
	runtime.SetFinalizer(call, func(c *callImpl) {
		env, freeFunc := jutil.GetEnv()
		defer freeFunc()
		jutil.DeleteGlobalRef(env, c.jCall)
	})
	return call, nil
}

// callImpl is the go interface to the java implementation of security.Call
type callImpl struct {
	jCall jutil.Object
}

func (c *callImpl) Timestamp() time.Time {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jTime, err := jutil.CallObjectMethod(env, c.jCall, "timestamp", nil, jutil.DateTimeSign)
	if err != nil {
		log.Println("Couldn't call Java timestamp method: ", err)
		return time.Time{}
	}
	t, err := jutil.GoTime(env, jTime)
	if err != nil {
		log.Println("Couldn't convert Java time to Go: ", err)
		return time.Time{}
	}
	return t
}

func (c *callImpl) Method() string {
	return jutil.UpperCamelCase(c.callStringMethod("method"))
}

func (c *callImpl) MethodTags() []*vdl.Value {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jTags, err := jutil.CallObjectMethod(env, c.jCall, "methodTags", nil, jutil.ArraySign(jutil.VdlValueSign))
	if err != nil {
		log.Println("Couldn't call Java methodTags method: ", err)
		return nil
	}
	tags, err := jutil.GoVDLValueArray(env, jTags)
	if err != nil {
		log.Println("Couldn't convert Java tags to Go: ", err)
		return nil
	}
	return tags
}

func (c *callImpl) Suffix() string {
	return c.callStringMethod("suffix")
}

func (c *callImpl) LocalDischarges() map[string]security.Discharge {
	return c.callDischargeMapMethod("localDischarges")
}

func (c *callImpl) RemoteDischarges() map[string]security.Discharge {
	return c.callDischargeMapMethod("remoteDischarges")
}

func (c *callImpl) LocalEndpoint() naming.Endpoint {
	epStr := c.callStringMethod("localEndpoint")
	ep, err := v23.NewEndpoint(epStr)
	if err != nil {
		log.Printf("Couldn't parse endpoint string %q: %v", epStr, err)
		return nil
	}
	return ep
}

func (c *callImpl) LocalPrincipal() security.Principal {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jPrincipal, err := jutil.CallObjectMethod(env, c.jCall, "localPrincipal", nil, principalSign)
	if err != nil {
		log.Printf("Couldn't call Java localPrincipal method: %v", err)
		return nil
	}
	principal, err := GoPrincipal(env, jPrincipal)
	if err != nil {
		log.Printf("Couldn't convert Java principal to Go: %v", err)
		return nil
	}
	return principal
}

func (c *callImpl) LocalBlessings() security.Blessings {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jBlessings, err := jutil.CallObjectMethod(env, c.jCall, "localBlessings", nil, blessingsSign)
	if err != nil {
		log.Printf("Couldn't call Java localBlessings method: %v", err)
		return security.Blessings{}
	}
	blessings, err := GoBlessings(env, jBlessings)
	if err != nil {
		log.Printf("Couldn't convert Java Blessings into Go: %v", err)
		return security.Blessings{}
	}
	return blessings
}

func (c *callImpl) RemoteBlessings() security.Blessings {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jBlessings, err := jutil.CallObjectMethod(env, c.jCall, "remoteBlessings", nil, blessingsSign)
	if err != nil {
		log.Printf("Couldn't call Java remoteBlessings method: %v", err)
		return security.Blessings{}
	}
	blessings, err := GoBlessings(env, jBlessings)
	if err != nil {
		log.Printf("Couldn't convert Java Blessings into Go: %v", err)
		return security.Blessings{}
	}
	return blessings
}

func (c *callImpl) RemoteEndpoint() naming.Endpoint {
	epStr := c.callStringMethod("remoteEndpoint")
	ep, err := v23.NewEndpoint(epStr)
	if err != nil {
		log.Printf("Couldn't parse endpoint string %q: %v", epStr, err)
		return nil
	}
	return ep
}

func (c *callImpl) Context() *context.T {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	contextSign := jutil.ClassSign("io.v.v23.context.VContext")
	jCtx, err := jutil.CallObjectMethod(env, c.jCall, "context", nil, contextSign)
	if err != nil {
		log.Printf("Couldn't get Java Vanadium context: %v", err)
	}
	ctx, err := jcontext.GoContext(env, jCtx)
	if err != nil {
		log.Printf("Couldn't convert Java Vanadium context to Go: %v", err)
	}
	return ctx
}

func (c *callImpl) callStringMethod(methodName string) string {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	ret, err := jutil.CallStringMethod(env, c.jCall, methodName, nil)
	if err != nil {
		log.Printf("Couldn't call Java %q method: %v", methodName, err)
		return ""
	}
	return ret
}

func (c *callImpl) callDischargeMapMethod(methodName string) map[string]security.Discharge {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	javaObjectMap, err := jutil.CallMapMethod(env, c.jCall, methodName, nil)
	if err != nil {
		log.Printf("Couldn't call Java %q method: %v", methodName, err)
		return nil
	}
	discharges := make(map[string]security.Discharge)
	for jKey, jValue := range javaObjectMap {
		key := jutil.GoString(env, jKey)
		discharge, err := GoDischarge(env, jValue)
		if err != nil {
			log.Printf("Couldn't convert Java Discharge to Go Discharge: %v", err)
			return nil
		}
		discharges[key] = discharge
	}
	return discharges
}
