/* Copyright (c) 2013 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package edu.stanford.ramcloud;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.LinkedList;

/*
 * This class provides Java bindings for RAMCloud. Right now it is a rather
 * simple subset of what RamCloud.h defines.
 *
 * Running ``javah'' on this file will generate a C header file with the
 * appropriate JNI function definitions. The glue interfacing to the C++
 * RAMCloud library can be found in JRamCloud.cc.
 *
 * For JNI information, the IBM tutorials and Android developer docs are much
 * better than Sun's at giving an overall intro:
 *      http://www.ibm.com/developerworks/java/tutorials/j-jni/section4.html
 *      http://developer.android.com/training/articles/perf-jni.html
 */
public class JRamCloud {
    static {
        System.loadLibrary("edu_stanford_ramcloud_JRamCloud");
    }

    public static final long VERSION_NONEXISTENT = 0L;

    /// Pointer to the underlying C++ RAMCloud object associated with this
    /// object.
    private long ramcloudObjectPointer = 0;

    /**
     * See src/RejectRules.h.
     */
    public static class RejectRules {
        // these needs to be in sync with JNI code;
        public static final int DoesntExist = 1;
        public static final int Exists = 1 << 1;
        public static final int VersionLeGiven = 1 << 2;
        public static final int VersionNeGiven = 1 << 3;

        protected long givenVersion;
        protected int flags;

        public RejectRules() {
            clear();
        }

        public void clear() {
            this.givenVersion = VERSION_NONEXISTENT;
            this.flags = 0x0;
        }

        public RejectRules set(int flags, long version) {
            this.flags = flags;
            this.givenVersion = version;
            return this;
        }

        public RejectRules set(int flags) {
            return set(flags,VERSION_NONEXISTENT);
        }

        public RejectRules rejectIfLeVersion(long version) {
            setVersion(version);
            this.flags |= VersionLeGiven;
            return this;
        }

        public RejectRules rejectIfExists() {
            this.flags |= Exists;
            return this;
        }

        public RejectRules rejectIfDoesntExists() {
            this.flags |= DoesntExist;
            return this;
        }

        public RejectRules rejectIfNeVersion(long version) {
            setVersion(version);
            this.flags |= VersionNeGiven;
            return this;
        }

        private void setVersion(long version) {
            this.givenVersion = version;
        }
    }

    public static class MultiReadObject {
        public long[] tableId;
        public byte[] key[];
        public short[] keyLength;

        public MultiReadObject(int size){
            this.tableId = new long[size];
            this.key = new byte[size][];
            this.keyLength = new short[size];
        }

        public void setObject(int num, long tableId, byte key[]){
            this.tableId[num] = tableId;
            this.key[num] = key;
            this.keyLength[num] = (short) this.key[num].length;
        }
    }

    public static class MultiWriteObject {
        public long[] tableId;
        public byte[] key[];
        public short[] keyLength;
        public byte[] value[];
        public int[] valueLength;
        public RejectRules[] rules;

        public MultiWriteObject(int size) {
            this.tableId = new long[size];
            this.key = new byte[size][];
            this.keyLength = new short[size];
            this.value = new byte[size][];
            this.valueLength = new int[size];
            this.rules = new RejectRules[size];
        }

        public void setObject(int num, long tableId, byte key[], byte value[], RejectRules rules){
            this.tableId[num] = tableId;
            this.key[num] = key;
            this.keyLength[num] = (short) key.length;
            this.value[num] = value;
            this.valueLength[num] = value.length;
            this.rules[num] = rules;
        }

    }

    public static class MultiWriteRspObject {
        private int status;
        private long version;

        public MultiWriteRspObject(int status, long version) {
            this.status = status;
            this.version = version;
        }
        public int getStatus() {
            return status;
        }

        public long getVersion() {
            return version;
        }
    }

    /**
     * This class is returned by Read operations. It encapsulates the entire
     * object, including the key, value, and version.
     *
     * It mostly exists because Java doesn't support primitive out parameters
     * or multiple return values, and we don't know the object's size ahead of
     * time, so passing in a fixed-length array would be problematic.
     */
    public static class Object {
        Object(byte[] _key, byte[] _value, long _version)
        {
            key = _key;
            value = _value;
            version = _version;
        }

        public String
        getKey()
        {
            return new String(key,StandardCharsets.UTF_8);
        }

        public String
        getValue()
        {
            return new String(value,StandardCharsets.UTF_8);
        }

        final public byte[] key;
        final public byte[] value;
        final public long version;
    }

    public static class TableEnumeratorObject {
        TableEnumeratorObject(Object[] _object, long _nextHash)
        {
            object = _object;
            nextHash = _nextHash;
        }

        final public Object[] object;
        final public long nextHash;
    }

    public class TableEnumerator {
        private long tableEnumeratorObjectPointer = 0;
        private long ramCloudObjectPointer = 0;

        public TableEnumerator(long tableId)
        {
            ramCloudObjectPointer = ramcloudObjectPointer;
            tableEnumeratorObjectPointer = init(tableId);
        }

        private native long init(long tableId);
        public native boolean hasNext();
        public native Object next();
    }

    public class TableEnumerator2 {

        protected long tableId;
        protected LinkedList<JRamCloud.Object> rcobjs = null;
        protected long nextHash = 0;
        protected boolean done = false;

        public TableEnumerator2(long tableId)
        {
            this.tableId = tableId;
            rcobjs = new LinkedList<>();
        }
        public boolean hasNext() {
            if (rcobjs.isEmpty())
            {
                if (done) {
                    return false;
                }
                JRamCloud.TableEnumeratorObject o = getTableObjects(this.tableId, this.nextHash);
                if (o.nextHash == 0L) {
                    done = true;
                }
                this.nextHash = o.nextHash;
                rcobjs.addAll(Arrays.asList(o.object));
                if (rcobjs.isEmpty()) {
                    return false;
                }
            }
            return true;
        }

        public Object next()
        {
            return rcobjs.pop();
        }
    }

    /**
     * Connect to the RAMCloud cluster specified by the given coordinator's
     * service locator string. This causes the JNI code to instantiate the
     * underlying RamCloud C++ object.
     */
    public
    JRamCloud(String coordinatorLocator)
    {
        ramcloudObjectPointer = connect(coordinatorLocator);
    }

    /**
     * Disconnect from the RAMCloud cluster. This causes the JNI code to
     * destroy the underlying RamCloud C++ object.
     */
    public void
    disconnect()
    {
        if (ramcloudObjectPointer != 0) {
            disconnect(ramcloudObjectPointer);
            ramcloudObjectPointer = 0;
        }
    }

    /**
     * This method is called by the garbage collector before destroying the
     * object. The user really should have called disconnect, but in case
     * they did not, be sure to clean up after them.
     */
    @Override
    protected void
    finalize()
    {
        System.err.println("warning: JRamCloud::disconnect() was not called " +
                           "prior to the finalizer. You should disconnect " +
                           "your JRamCloud object when you're done with it.");
        disconnect();
    }

    /**
     * Convenience read() wrapper that take a String key argument.
     */
    public Object
    read(long tableId, String key)
    {
        return read(tableId, key.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Convenience read() wrapper that take a String key argument.
     * @throws RejectRulesException
     */
    public Object
    read(long tableId, String key, RejectRules rules) throws RejectRulesException
    {
        return read(tableId, key.getBytes(StandardCharsets.UTF_8), rules);
    }

    /**
     * Convenience remove() wrapper that take a String key argument.
     */
    public long
    remove(long tableId, String key)
    {
        return remove(tableId, key.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Convenience remove() wrapper that take a String key argument.
     * @throws RejectRulesException
     */
    public long
    remove(long tableId, String key, RejectRules rules) throws RejectRulesException
    {
        return remove(tableId, key.getBytes(StandardCharsets.UTF_8), rules);
    }

    /**
     * Convenience write() wrapper that take String key and value arguments.
     */
    public long
    write(long tableId, String key, String value)
    {
        return write(tableId, key.getBytes(StandardCharsets.UTF_8), value.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Convenience write() wrapper that take String key and value arguments.
     * @throws RejectRulesException
     */
    public long
    write(long tableId, String key, String value, RejectRules rules) throws RejectRulesException
    {
        return write(tableId, key.getBytes(StandardCharsets.UTF_8), value.getBytes(StandardCharsets.UTF_8), rules);
    }

    /**
     * Convenience write() wrapper that takes a String key and a byte[] value
     * argument.
     */
    public long
    write(long tableId, String key, byte[] value)
    {
        return write(tableId, key.getBytes(StandardCharsets.UTF_8), value);
    }

    /**
     * Convenience write() wrapper that takes a String key and a byte[] value
     * argument.
     * @throws RejectRulesException
     */
    public long
    write(long tableId, String key, byte[] value, RejectRules rules) throws RejectRulesException
    {
        return write(tableId, key.getBytes(StandardCharsets.UTF_8), value, rules);
    }

    private static native long connect(String coordinatorLocator);
    private static native void disconnect(long ramcloudObjectPointer);

    public native long createTable(String name);
    public native long createTable(String name, int serverSpan);
    public native void dropTable(String name);
    public native long getTableId(String name);
    public native Object read(long tableId, byte[] key);
    public native Object read(long tableId, byte[] key, RejectRules rules) throws RejectRulesException;
    public native Object[] multiRead(long[] tableId, byte[] keydata[], short[] keyDataSize, int requestNum);
    public native long remove(long tableId, byte[] key);
    public native long remove(long tableId, byte[] key, RejectRules rules) throws RejectRulesException;
    public native long write(long tableId, byte[] key, byte[] value);
    public native long write(long tableId, byte[] key, byte[] value, RejectRules rules) throws RejectRulesException;
    @Deprecated
    public native long writeRule(long tableId, byte[] key, byte[] value, RejectRules rules);
    public native MultiWriteRspObject[] multiWrite(long[] tableId, byte[] key[], short[] keyDataSize, byte[] value[], int[] valueDataSize, int requestNum, RejectRules[] rules);
    public native TableEnumeratorObject getTableObjects(long tableId, long nextHash);

    /*
     * The following exceptions may be thrown by the JNI functions:
     */

    public static class TableDoesntExistException extends RuntimeException {
        public TableDoesntExistException(String message)
        {
            super(message);
        }
    }

    public static class ObjectDoesntExistException extends RejectRulesException {
        public ObjectDoesntExistException(String message)
        {
            super(message);
        }
    }

    public static class ObjectExistsException extends RejectRulesException {
        public ObjectExistsException(String message)
        {
            super(message);
        }
    }

    public static class WrongVersionException extends RejectRulesException {
        public WrongVersionException(String message)
        {
            super(message);
        }
    }

    public static class InvalidObjectException extends RuntimeException {
        public InvalidObjectException(String message) {
            super(message);
        }
    }

    public static class RejectRulesException extends Exception {
        public RejectRulesException(String message) {
            super(message);
        }
    }

    public static void tableEnumeratorTest(JRamCloud ramcloud) {
        long startTime = 0;
        for (int x = 0 ; x < 2 ; x ++){
        for(int N = 1000; N < 10000; N += 1000) {
            long EnumerateTesttable = ramcloud.createTable("EnumerateTest");
            for(int i = 0 ; i < N ; ++i) {
                String key = String.valueOf(i);
                ramcloud.write(EnumerateTesttable, key.getBytes(StandardCharsets.UTF_8), "Hello, World!".getBytes(StandardCharsets.UTF_8));
            }

            long tableIdList[] = new long[N];
            byte[] keydata[] = new byte[N][];
            short keydataSize[] = new short[N];
            startTime = System.nanoTime();
            for (int j = 0 ; j < N ; ++j) {
                tableIdList[j] = EnumerateTesttable;
                String key = String.valueOf(j);
                keydata[j] = key.getBytes(StandardCharsets.UTF_8);
                keydataSize[j] = (short) keydata[j].length;
            }
            JRamCloud.Object out[] = ramcloud.multiRead(tableIdList, keydata, keydataSize, N);
            for (int i = 0; i < N; ++i) {
                if(out[i].version == 0) {
                        System.out.println("Verify fail " + out[i].getKey() + " V:" + out[i].getValue());
                }
            }

            System.out.println("multiRead           : " + N + " Time : " + (System.nanoTime()-startTime));

            startTime = System.nanoTime();
            JRamCloud.TableEnumerator tableEnum = ramcloud.new TableEnumerator(EnumerateTesttable);
            while (tableEnum.hasNext()) {
                Object tableEntry = tableEnum.next();
                if (tableEntry != null) {
                    System.out.println("tableEnumerator object: key = [" + tableEntry.getKey() + "], value = [" + tableEntry.getValue() + "]");
                }
            }
            System.out.println("old TableEnumerator : " + N + " Time : " + (System.nanoTime()-startTime));

            startTime = System.nanoTime();
            JRamCloud.TableEnumerator2 tableEnum2 = ramcloud.new TableEnumerator2(EnumerateTesttable);
            while (tableEnum2.hasNext()) {
                Object tableEntry2 = tableEnum2.next();
                if (tableEntry2 != null) {
                    System.out.println("tableEnumerator2 object: key = [" + tableEntry2.getKey() + "], value = [" + tableEntry2.getValue() + "]");
                }
            }
            System.out.println("new TableEnumerator : " + N + " Time : " + (System.nanoTime()-startTime));
            ramcloud.dropTable("EnumerateTest");
        }
        }
    }
    /**
     * A simple end-to-end test of the java bindings.
     */
    public static void
    main(String argv[])
    {
        JRamCloud ramcloud = new JRamCloud(argv[0]);
        long tableId = ramcloud.createTable("hi");
        System.out.println("created table, id = " + tableId);
        long tableId2 = ramcloud.getTableId("hi");
        System.out.println("getTableId says tableId = " + tableId2);

        System.out.println("wrote obj version = " +
            ramcloud.write(tableId, "thisIsTheKey", "thisIsTheValue"));

        JRamCloud.Object o = ramcloud.read(tableId, "thisIsTheKey");
        System.out.println("read object: key = [" + o.getKey() + "], value = ["
            + o.getValue() + "], version = " + o.version);

        ramcloud.remove(tableId, "thisIsTheKey");

        try {
            ramcloud.read(tableId, "thisIsTheKey");
            System.out.println("Error: shouldn't have read successfully!");
        } catch (Exception e) {
            // OK
        }

        ramcloud.write(tableId, "thisIsTheKey", "thisIsTheValue");

        long before = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            @SuppressWarnings("unused")
            JRamCloud.Object unused = ramcloud.read(tableId, "thisIsTheKey");
        }
        long after = System.nanoTime();
        System.out.println("Avg read latency: " +
            ((double)(after - before) / 1000 / 1000) + " usec");

        // multiRead test
        long tableId4 = ramcloud.createTable("table4");
        System.out.println("table4 id " + tableId4);
        ramcloud.write(tableId4, "object1-1", "value:1-1");
        ramcloud.write(tableId4, "object1-2", "value:1-2");
        ramcloud.write(tableId4, "object1-3", "value:1-3");
        long tableId5 = ramcloud.createTable("table5");
        System.out.println("table5 id " + tableId5);
        ramcloud.write(tableId5, "object2-1", "value:2-1");
        long tableId6 = ramcloud.createTable("table6");
        ramcloud.write(tableId6, "object3-1", "value:3-1");
        ramcloud.write(tableId6, "object3-2", "value:3-2");

        MultiReadObject mr = new MultiReadObject(2);
        MultiWriteObject mw = new MultiWriteObject(2);

        mr.setObject(0, tableId4, "object1-1".getBytes(StandardCharsets.UTF_8));
        mr.setObject(1, tableId5, "object2-1".getBytes(StandardCharsets.UTF_8));

        JRamCloud.Object out[] = ramcloud.multiRead(mr.tableId, mr.key, mr.keyLength, 2);
        for (int i = 0 ; i < 2 ; i++){
            System.out.println("multi read object: key = [" + out[i].getKey() + "], value = ["
                    + out[i].getValue() + "]");
        }

        for (int i = 0; i < 1000; i++) {
            String key1 = "key1" + String.valueOf(i);
            String key2 = "key2" + String.valueOf(i);

            mw.setObject(0, tableId4, key1.getBytes(StandardCharsets.UTF_8), "v0-value".getBytes(StandardCharsets.UTF_8), null);
            mw.setObject(1, tableId5, key2.getBytes(StandardCharsets.UTF_8), "v1".getBytes(StandardCharsets.UTF_8), null);

            MultiWriteRspObject[] rsp = ramcloud.multiWrite(mw.tableId, mw.key, mw.keyLength, mw.value, mw.valueLength, 2, mw.rules);
            if (rsp != null) {
                for (int j = 0; j < rsp.length; j++) {
                    System.out.println("multi write rsp(" + j + ") status:version " + rsp[j].getStatus() + ":" + rsp[j].getVersion());
                }
            }
        }
        for (int i = 0; i < 1000; i++) {
            String key1 = "key1" + String.valueOf(i);
            String key2 = "key2" + String.valueOf(i);

            mr.setObject(0, tableId4, key1.getBytes(StandardCharsets.UTF_8));
            mr.setObject(1, tableId5, key2.getBytes(StandardCharsets.UTF_8));

            out = ramcloud.multiRead(mr.tableId, mr.key, mr.keyLength, 2);
            for (int j = 0; j < 2; j++) {
                System.out.println("multi read object: key = [" + out[j].getKey() + "], value = [" + out[j].getValue() + "]");
            }
        }

        tableEnumeratorTest(ramcloud);

        ramcloud.dropTable("table4");
        ramcloud.dropTable("table5");
        ramcloud.dropTable("table6");
        ramcloud.disconnect();
    }
}
