// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package go;

import android.content.Context;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;

import go.Universe;

// Seq is a sequence of machine-dependent encoded values.
// Used by automatically generated language bindings to talk to Go.
public class Seq {
	private static Logger log = Logger.getLogger("GoSeq");

	// also known to bind/seq/ref.go and bind/objc/seq_darwin.m
	private static final int NULL_REFNUM = 41;

	// use single Ref for null Object
	public static final Ref nullRef = new Ref(NULL_REFNUM, null);

	// The singleton GoRefQueue
	private static final GoRefQueue goRefQueue = new GoRefQueue();

	static {
		System.loadLibrary("gojni");
		init();
		Universe.touch();
	}

	// setContext sets the context in the go-library to be used in RunOnJvm.
	public static void setContext(Context context) {
		setContext((java.lang.Object)context);
	}

	private static native void init();

	// Empty method to run class initializer
	public static void touch() {}

	private Seq() {
	}

	// ctx is an android.context.Context.
	static native void setContext(java.lang.Object ctx);

	public static void incRefnum(int refnum) {
		tracker.incRefnum(refnum);
	}

	// incRef increments the reference count of Java objects.
	// For proxies for Go objects, it calls into the Proxy method
	// incRefnum() to make sure the Go reference count is positive
	// even if the Proxy is garbage collected and its Ref is finalized.
	public static int incRef(Object o) {
		return tracker.inc(o);
	}

	public static int incGoObjectRef(GoObject o) {
		return o.incRefnum();
	}

	// trackGoRef tracks a Go reference and decrements its refcount
	// when the given GoObject wrapper is garbage collected.
	//
	// TODO(crawshaw): We could cut down allocations for frequently
	// sent Go objects by maintaining a map to weak references. This
	// however, would require allocating two objects per reference
	// instead of one. It also introduces weak references, the bane
	// of any Java debugging session.
	//
	// When we have real code, examine the tradeoffs.
	public static void trackGoRef(int refnum, GoObject obj) {
		if (refnum > 0) {
			throw new RuntimeException("trackGoRef called with Java refnum " + refnum);
		}
		goRefQueue.track(refnum, obj);
	}

	public static Ref getRef(int refnum) {
		return tracker.get(refnum);
	}

	// Increment the Go reference count before sending over a refnum.
	// The ref parameter is only used to make sure the referenced
	// object is not garbage collected before Go increments the
	// count. It's the equivalent of Go's runtime.KeepAlive.
	public static native void incGoRef(int refnum, GoObject ref);

	// Informs the Go ref tracker that Java is done with this refnum.
	static native void destroyRef(int refnum);

	// decRef is called from seq.FinalizeRef
	static void decRef(int refnum) {
		tracker.dec(refnum);
	}

	// A GoObject is a Java class implemented in Go. When a GoObject
	// is passed to Go, it is wrapped in a Go proxy, to make it behave
	// the same as passing a regular Java class.
	public interface GoObject {
		// Increment refcount and return the refnum of the proxy.
		//
		// The Go reference count need to be bumped while the
		// refnum is passed to Go, to avoid finalizing and
		// invalidating it before being translated on the Go side.
		int incRefnum();
	}
	// A Proxy is a Java object that proxies a Go object. Proxies, unlike
	// GoObjects, are unwrapped to their Go counterpart when deserialized
	// in Go.
	public interface Proxy extends GoObject {}

	// A Ref represents an instance of a Java object passed back and forth
	// across the language boundary.
	public static final class Ref {
		public final int refnum;

		private int refcnt;  // Track how many times sent to Go.

		public final Object obj;  // The referenced Java obj.

		Ref(int refnum, Object o) {
			if (refnum < 0) {
				throw new RuntimeException("Ref instantiated with a Go refnum " + refnum);
			}
			this.refnum = refnum;
			this.refcnt = 0;
			this.obj = o;
		}

		void inc() {
			// Count how many times this ref's Java object is passed to Go.
			if (refcnt == Integer.MAX_VALUE) {
				throw new RuntimeException("refnum " + refnum + " overflow");
			}
			refcnt++;
		}
	}

	static final RefTracker tracker = new RefTracker();

	static final class RefTracker {
		private static final int REF_OFFSET = 42;

		// Next Java object reference number.
		//
		// Reference numbers are positive for Java objects,
		// and start, arbitrarily at a different offset to Go
		// to make debugging by reading Seq hex a little easier.
		private int next = REF_OFFSET; // next Java object ref

		// Java objects that have been passed to Go. refnum -> Ref
		// The Ref obj field is non-null.
		// This map pins Java objects so they don't get GCed while the
		// only reference to them is held by Go code.
		private final RefMap javaObjs = new RefMap();

		// Java objects to refnum
		private final IdentityHashMap<Object, Integer> javaRefs = new IdentityHashMap<>();

		// inc increments the reference count of a Java object when it
		// is sent to Go. inc returns the refnum for the object.
		synchronized int inc(Object o) {
			if (o == null) {
				return NULL_REFNUM;
			}
			if (o instanceof Proxy) {
				return ((Proxy)o).incRefnum();
			}
			Integer refnumObj = javaRefs.get(o);
			if (refnumObj == null) {
				if (next == Integer.MAX_VALUE) {
					throw new RuntimeException("createRef overflow for " + o);
				}
				refnumObj = next++;
				javaRefs.put(o, refnumObj);
			}
			int refnum = refnumObj;
			Ref ref = javaObjs.get(refnum);
			if (ref == null) {
				ref = new Ref(refnum, o);
				javaObjs.put(refnum, ref);
			}
			ref.inc();
			return refnum;
		}

		synchronized void incRefnum(int refnum) {
			Ref ref = javaObjs.get(refnum);
			if (ref == null) {
				throw new RuntimeException("referenced Java object is not found: refnum="+refnum);
			}
			ref.inc();
		}

		// dec decrements the reference count of a Java object when
		// Go signals a corresponding proxy object is finalized.
		// If the count reaches zero, the Java object is removed
		// from the javaObjs map.
		synchronized void dec(int refnum) {
			if (refnum <= 0) {
				// We don't keep track of the Go object.
				// This must not happen.
				log.severe("dec request for Go object "+ refnum);
				return;
			}
			if (refnum == Seq.nullRef.refnum) {
				return;
			}
			// Java objects are removed on request of Go.
			Ref obj = javaObjs.get(refnum);
			if (obj == null) {
				throw new RuntimeException("referenced Java object is not found: refnum="+refnum);
			}
			obj.refcnt--;
			if (obj.refcnt <= 0) {
				javaObjs.remove(refnum);
				javaRefs.remove(obj.obj);
			}
		}

		// get returns an existing Ref to a Java object.
		synchronized Ref get(int refnum) {
			if (refnum < 0) {
				throw new RuntimeException("ref called with Go refnum " + refnum);
			}
			if (refnum == NULL_REFNUM) {
				return nullRef;
			}
			Ref ref = javaObjs.get(refnum);
			if (ref == null) {
				throw new RuntimeException("unknown java Ref: "+refnum);
			}
			return ref;
		}
	}

	// GoRefQueue is a queue of GoRefs that are no longer live. An internal thread
	// processes the queue and decrement the reference count on the Go side.
	static class GoRefQueue extends ReferenceQueue<GoObject> {
		// The set of tracked GoRefs. If we don't hold on to the GoRef instances, the Java GC
		// will not add them to the queue when their referents are reclaimed.
		private final Collection<GoRef> refs = Collections.synchronizedCollection(new HashSet<GoRef>());

		void track(int refnum, GoObject obj) {
			refs.add(new GoRef(refnum, obj, this));
		}

		GoRefQueue() {
			Thread daemon = new Thread(new Runnable() {
				@Override public void run() {
					while (true) {
						try {
							GoRef ref = (GoRef)remove();
							refs.remove(ref);
							destroyRef(ref.refnum);
							ref.clear();
						} catch (InterruptedException e) {
							// Ignore
						}
					}
				}
			});
			daemon.setDaemon(true);
			daemon.setName("GoRefQueue Finalizer Thread");
			daemon.start();
		}
	}

	// A GoRef is a PhantomReference to a Java proxy for a Go object.
	// GoRefs are enqueued to the singleton GoRefQueue when no longer live,
	// so the corresponding reference count can be decremented.
	static class GoRef extends PhantomReference<GoObject> {
		final int refnum;

		GoRef(int refnum, GoObject obj, GoRefQueue q) {
			super(obj, q);
			if (refnum > 0) {
				throw new RuntimeException("GoRef instantiated with a Java refnum " + refnum);
			}
			this.refnum = refnum;
		}
	}

	// RefMap is a mapping of integers to Ref objects.
	//
	// The integers can be sparse. In Go this would be a map[int]*Ref.
	static final class RefMap {
		private int next = 0;
		private int live = 0;
		private int[] keys = new int[16];
		private Ref[] objs = new Ref[16];

		RefMap() {}

		Ref get(int key) {
			int i = Arrays.binarySearch(keys, 0, next, key);
			if (i >= 0) {
				return objs[i];
			}
			return null;
		}

		void remove(int key) {
			int i = Arrays.binarySearch(keys, 0, next, key);
			if (i >= 0) {
				if (objs[i] != null) {
					objs[i] = null;
					live--;
				}
			}
		}

		void put(int key, Ref obj) {
			if (obj == null) {
				throw new RuntimeException("put a null ref (with key "+key+")");
			}
			int i = Arrays.binarySearch(keys, 0, next, key);
			if (i >= 0) {
				if (objs[i] == null) {
					objs[i] = obj;
					live++;
				}
				if (objs[i] != obj) {
					throw new RuntimeException("replacing an existing ref (with key "+key+")");
				}
				return;
			}
			if (next >= keys.length) {
				grow();
				i = Arrays.binarySearch(keys, 0, next, key);
			}
			i = ~i;
			if (i < next) {
				// Insert, shift everything afterwards down.
				System.arraycopy(keys, i, keys, i+1, next-i);
				System.arraycopy(objs, i, objs, i+1, next-i);
			}
			keys[i] = key;
			objs[i] = obj;
			live++;
			next++;
		}

		private void grow() {
			// Compact and (if necessary) grow backing store.
			int[] newKeys;
			Ref[] newObjs;
			int len = 2*roundPow2(live);
			if (len > keys.length) {
				newKeys = new int[keys.length*2];
				newObjs = new Ref[objs.length*2];
			} else {
				newKeys = keys;
				newObjs = objs;
			}

			int j = 0;
			for (int i = 0; i < keys.length; i++) {
				if (objs[i] != null) {
					newKeys[j] = keys[i];
					newObjs[j] = objs[i];
					j++;
				}
			}
			for (int i = j; i < newKeys.length; i++) {
				newKeys[i] = 0;
				newObjs[i] = null;
			}

			keys = newKeys;
			objs = newObjs;
			next = j;

			if (live != next) {
				throw new RuntimeException("bad state: live="+live+", next="+next);
			}
		}

		private static int roundPow2(int x) {
			int p = 1;
			while (p < x) {
				p *= 2;
			}
			return p;
		}
	}
}
