// 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.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

// Seq is a sequence of machine-dependent encoded values.
// Used by automatically generated language bindings to talk to Go.
public class Seq {
	@SuppressWarnings("UnusedDeclaration")
	private long memptr; // holds C-allocated pointer

	public Seq() {
		ensure(64);
	}

	// Ensure that at least size bytes can be written to the Seq.
	// Any existing data in the buffer is preserved.
	public native void ensure(int size);

	// Moves the internal buffer offset back to zero.
	// Length and contents are maintained. Data can be read after a reset.
	public native void resetOffset();

	public native void log(String label);

	public native boolean readBool();
	public native byte readInt8();
	public native short readInt16();
	public native int readInt32();
	public native long readInt64();
	public long readInt() { return readInt64(); }

	public native float readFloat32();
	public native double readFloat64();
	public native String readUTF16();
	public String readString() { return readUTF16(); }
	public native byte[] readByteArray();

	public native void writeBool(boolean v);
	public native void writeInt8(byte v);
	public native void writeInt16(short v);
	public native void writeInt32(int v);
	public native void writeInt64(long v);
	public void writeInt(long v) { writeInt64(v); }

	public native void writeFloat32(float v);
	public native void writeFloat64(double v);
	public native void writeUTF16(String v);
	public void writeString(String v) { writeUTF16(v); }
	public native void writeByteArray(byte[] v);

	public void writeRef(Ref ref) {
		writeInt32(ref.refnum);
	}

	public Ref readRef() {
		int refnum = readInt32();
		return tracker.get(refnum);
	}

	static {
		initSeq();
	}

	static native void initSeq();

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

	// createRef creates a Ref to a Java object.
	public static Ref createRef(Seq.Object o) {
		return tracker.createRef(o);
	}

	// sends a function invocation request to Go.
	//
	// Blocks until the function completes.
	// If the request is for a method, the first element in src is
	// a Ref to the receiver.
	public static native void send(String descriptor, int code, Seq src, Seq dst);

	// recv returns the next request from Go for a Java call.
	static native void recv(Seq in, Receive params);

	// recvRes sends the result of a Java call back to Go.
	static native void recvRes(int handle, Seq out);

	static final class Receive {
		int refnum;
		int code;
		int handle;
	}

	protected void finalize() throws Throwable {
		super.finalize();
		free();
	}
	private native void free();

	private static final ExecutorService receivePool = Executors.newCachedThreadPool();

	// receive listens for callback requests from Go, invokes them on a thread
	// pool and sends the responses.
	public static void receive() {
		Seq.Receive params = new Seq.Receive();
		while (true) {
			final Seq in = new Seq();
			Seq.recv(in, params);

			final int code = params.code;
			final int handle = params.handle;
			final int refnum = params.refnum;

			if (code == -1) {
				// Special signal from seq.FinalizeRef.
				tracker.dec(refnum);
				Seq out = new Seq();
				Seq.recvRes(handle, out);
				continue;
			}

			receivePool.execute(new Runnable() {
				public void run() {
					Ref r = tracker.get(refnum);
					Seq out = new Seq();
					r.obj.call(code, in, out);
					Seq.recvRes(handle, out);
				}
			});
		}
	}

	// An Object is a Java object that matches a Go object.
	// The implementation of the object may be in either Java or Go,
	// with a proxy instance in the other language passing calls
	// through to the other language.
	//
	// Don't implement an Object directly. Instead, look for the
	// generated abstract Stub.
	public interface Object {
		public Ref ref();
		public void call(int code, Seq in, Seq out);
	}

	// A Ref is an object tagged with an integer for passing back and
	// forth across the language boundary.
	//
	// A Ref may represent either an instance of a Java Object subclass,
	// or an instance of a Go object. The explicit allocation of a Ref
	// is used to pin Go object instances when they are passed to Java.
	// The Go Seq library maintains a reference to the instance in a map
	// keyed by the Ref number. When the JVM calls finalize, we ask Go
	// to clear the entry in the map.
	public static final class Ref {
		// ref < 0: Go object tracked by Java
		// ref > 0: Java object tracked by Go
		int refnum;
		public Seq.Object obj;

		private Ref(int refnum, Seq.Object o) {
			this.refnum = refnum;
			this.obj = o;
			tracker.inc(refnum);
		}

		@Override
		protected void finalize() throws Throwable {
			tracker.dec(refnum);
			super.finalize();
		}
	}

	static final RefTracker tracker = new RefTracker();

	static final class RefTracker {
		// 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 = 42; // next Java object ref

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

		// Number of active references to a Go object. refnum -> count
		private SparseIntArray goObjs = new SparseIntArray();

		// 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 SparseArray<Ref> javaObjs = new SparseArray<Ref>();

		// inc increments the reference count to a Go object.
		synchronized void inc(int refnum) {
			if (refnum > 0) {
				return; // we don't count java objects
			}
			int count = goObjs.get(refnum);
			if (count == Integer.MAX_VALUE) {
				throw new RuntimeException("refnum " + refnum + " overflow");
			}
			goObjs.put(refnum, count+1);
		}

		// dec decrements the reference count to a Go object.
		// If the count reaches zero, the Go reference tracker is informed.
		synchronized void dec(int refnum) {
			if (refnum > 0) {
				// Java objects are removed on request of Go.
				javaObjs.remove(refnum);
				return;
			}
			int count = goObjs.get(refnum);
			if (count == 0) {
				throw new RuntimeException("refnum " + refnum + " underflow");
			}
			count--;
			if (count <= 0) {
				goObjs.delete(refnum);
				Seq.destroyRef(refnum);
			} else {
				goObjs.put(refnum, count);
			}
		}

		synchronized Ref createRef(Seq.Object o) {
			// TODO(crawshaw): use single Ref for null.
			if (next == Integer.MAX_VALUE) {
				throw new RuntimeException("createRef overflow for " + o);
			}
			int refnum = next++;
			Ref ref = new Ref(refnum, o);
			javaObjs.put(refnum, ref);
			return ref;
		}

		// get returns an existing Ref to either a Java or Go object.
		// It may be the first time we have seen the Go object.
		synchronized Ref get(int refnum) {
			if (refnum > 0) {
				Ref ref = javaObjs.get(refnum);
				if (ref == null) {
					throw new RuntimeException("unknown java Ref: "+refnum);
				}
				return ref;
			}
			return new Ref(refnum, null);
		}
	}
}
