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

import (
	"bytes"
	"encoding/binary"
	"unsafe"

	"v.io/v23/discovery"
	"v.io/v23/security"
	idiscovery "v.io/x/ref/lib/discovery"

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

// #include "jni.h"
// #include <stdlib.h>
import "C"

var (
	updateSign = jutil.ClassSign("io.v.v23.discovery.Update")

	// Global reference for java.util.UUID class.
	jUUIDClass jutil.Class

	// Global reference io.v.impl.google.lib.discovery.ScanHandler
	jScanHandlerClass jutil.Class

	// Global reference io.v.v23.discovery.Service
	jServiceClass jutil.Class

	// Global reference io.v.v23.security.BlessingPattern
	jBlessingPatternClass jutil.Class

	// Global reference io.v.v23.discovery.Update
	jUpdateClass jutil.Class

	// Global reference io.v.impl.google.lib.discovery.VDiscoveryImpl
	jVDiscoveryImplClass jutil.Class
)

// Init initializes the JNI code with the given Java environment. This method
// must be called from the main Java thread.
func Init(env jutil.Env) error {
	// Cache global references to all Java classes used by the package.  This is
	// necessary because JNI gets access to the class loader only in the system
	// thread, so we aren't able to invoke FindClass in other threads.
	var err error
	jUUIDClass, err = jutil.JFindClass(env, "java/util/UUID")
	if err != nil {
		return err
	}
	jScanHandlerClass, err = jutil.JFindClass(env, "io/v/impl/google/lib/discovery/ScanHandler")
	if err != nil {
		return err
	}
	jServiceClass, err = jutil.JFindClass(env, "io/v/v23/discovery/Service")
	if err != nil {
		return err
	}
	jBlessingPatternClass, err = jutil.JFindClass(env, "io/v/v23/security/BlessingPattern")
	if err != nil {
		return err
	}
	jUpdateClass, err = jutil.JFindClass(env, "io/v/v23/discovery/Update")
	if err != nil {
		return err
	}

	jVDiscoveryImplClass, err = jutil.JFindClass(env, "io/v/impl/google/lib/discovery/VDiscoveryImpl")
	if err != nil {
		return err
	}

	return nil
}

func convertStringtoUUID(jenv *C.JNIEnv, _ C.jclass, jName C.jstring, generator func(string) idiscovery.Uuid) C.jobject {
	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
	name := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
	uuid := generator(name)
	buf := bytes.NewBuffer(uuid)
	var high, low int64
	binary.Read(buf, binary.BigEndian, &high)
	binary.Read(buf, binary.BigEndian, &low)
	jUUID, err := jutil.NewObject(env, jUUIDClass, []jutil.Sign{jutil.LongSign, jutil.LongSign}, high, low)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	return C.jobject(unsafe.Pointer(jUUID))
}

//export Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForInterfaceName
func Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForInterfaceName(jenv *C.JNIEnv, jclass C.jclass, jName C.jstring) C.jobject {
	return convertStringtoUUID(jenv, jclass, jName, idiscovery.NewServiceUUID)
}

//export Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForAttributeKey
func Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForAttributeKey(jenv *C.JNIEnv, jclass C.jclass, jName C.jstring) C.jobject {
	converter := func(s string) idiscovery.Uuid {
		return idiscovery.NewAttributeUUID(s)
	}
	return convertStringtoUUID(jenv, jclass, jName, converter)
}

//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeFinalize
func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeFinalize(jenv *C.JNIEnv, _ C.jobject, discovery C.jlong, trigger C.jlong) {
	jutil.GoUnref(jutil.NativePtr(discovery))
	jutil.GoUnref(jutil.NativePtr(trigger))
}

//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_advertise
func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_advertise(jenv *C.JNIEnv, jDiscoveryObj C.jobject, jContext C.jobject, jServiceObject C.jobject, jVisibility C.jobject, jCallback C.jobject) {
	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
	ctx, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
	if err != nil {
		return
	}
	jService := jutil.Object(uintptr(unsafe.Pointer(jServiceObject)))
	var service discovery.Service
	if err := jutil.GoVomCopy(env, jService, jServiceClass, &service); err != nil {
		jutil.JThrowV(env, err)
		return
	}

	visibilityArray, err := jutil.GoObjectList(env, jutil.Object(uintptr(unsafe.Pointer(jVisibility))))
	if err != nil {
		jutil.JThrowV(env, err)
		return
	}
	visibilitySlice := make([]security.BlessingPattern, len(visibilityArray))
	for i, jPattern := range visibilityArray {
		if err := jutil.GoVomCopy(env, jPattern, jBlessingPatternClass, &visibilitySlice[i]); err != nil {
			jutil.JThrowV(env, err)
			return
		}
	}
	jDiscovery := jutil.Object(uintptr(unsafe.Pointer(jDiscoveryObj)))
	discoveryPtr, err := jutil.JLongField(env, jDiscovery, "nativeDiscovery")
	if err != nil {
		jutil.JThrowV(env, err)
		return
	}

	ds := *(*discovery.T)(jutil.NativePtr(discoveryPtr))

	triggerPtr, err := jutil.JLongField(env, jDiscovery, "nativeTrigger")
	if err != nil {
		jutil.JThrowV(env, err)
		return
	}

	trigger := (*idiscovery.Trigger)(jutil.NativePtr(triggerPtr))

	done, err := ds.Advertise(ctx, &service, visibilitySlice)
	if err != nil {
		jutil.JThrowV(env, err)
		return
	}
	// Copy back service.InstanceId to jServiceObject since it's the only field that would be updated.
	if err = jutil.CallVoidMethod(env, jutil.Object(uintptr(unsafe.Pointer(jServiceObject))), "setInstanceId", []jutil.Sign{jutil.StringSign}, jutil.JString(env, service.InstanceId)); err != nil {
		jutil.JThrowV(env, err)
		return
	}
	cb := jutil.Object(uintptr(unsafe.Pointer(jCallback)))
	cb = jutil.NewGlobalRef(env, cb)
	trigger.Add(func() {
		env, freeFunc := jutil.GetEnv()
		defer freeFunc()
		// TODO(bjornick): What should we do on errors?
		if err := jutil.CallVoidMethod(env, cb, "done", nil); err != nil {
			ctx.Errorf("failed to call done:", err)
		}
		jutil.DeleteGlobalRef(env, cb)
	}, done)
}

//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_scan
func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_scan(jenv *C.JNIEnv, jDiscoveryObj C.jobject, jContext C.jobject, jQuery C.jstring, jCallback C.jobject) {
	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
	ctx, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
	if err != nil {
		return
	}
	query := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jQuery))))

	jDiscovery := jutil.Object(uintptr(unsafe.Pointer(jDiscoveryObj)))
	discoveryPtr, err := jutil.JLongField(env, jDiscovery, "nativeDiscovery")
	if err != nil {
		jutil.JThrowV(env, err)
		return
	}
	ds := *(*discovery.T)(jutil.NativePtr(discoveryPtr))

	updates, err := ds.Scan(ctx, query)

	jutil.NewGlobalRef(env, jutil.Object(uintptr(unsafe.Pointer(jCallback))))
	if err != nil {
		jutil.JThrowV(env, err)
		return
	}
	cb := jutil.Object(uintptr(unsafe.Pointer(jCallback)))
	cb = jutil.NewGlobalRef(env, cb)
	go func() {
		env, freeFunc := jutil.GetEnv()
		defer freeFunc()
		for v := range updates {
			jUpdate, err := jutil.JVomCopy(env, v, jUpdateClass)
			if err != nil {
				ctx.Errorf("Failed to convert update: %v", err)
				continue
			}
			err = jutil.CallVoidMethod(env, cb, "handleUpdate", []jutil.Sign{updateSign}, jUpdate)
			if err != nil {
				ctx.Errorf("Failed to call handler: %v", err)
				continue
			}
		}
		jutil.DeleteGlobalRef(env, cb)
	}()
}
