package eu.simuline.octave;

import java.math.BigDecimal;
import java.util.Comparator;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * This class offers fields and methods to be accessed from within Octave 
 * to test Octave's Java interface. 
 *
 *
 * Created: Tue Jul 19 16:27:02 2016
 *
 * @author <a href="mailto:rei3ner@arcor.de">Ernst Reissner</a>
 * @version 1.0
 */
public class OctaveInterfaceTester {

    // a non-public field 

    private int inaccessibleI;

    // primitive types (except void) and their wrappers 
    // names of these fields according to type names in jvm specification 

    // character types: char and Character
    public char      cVal;

    public Character cVAL;

    // logical types: boolean and Boolean 
    public boolean   zVal;

    public Boolean   zVAL;

    // floating point types: double, Double, float and Float 
    public double    dVal;

    public Double    dVAL;

    public float     fVal;

    public Float     fVAL;

    // integer types: long, Long, int, Integer, short, Short, byte and Byte

    public long      jVal;

    public Long      jVAL;

    public int       iVal;

    public Integer   iVAL;

    public short     sVal;

    public Short     sVAL;

    public byte      bVal;

    public Byte      bVAL;

    // arrays of primitive types (except void) and of their wrappers 

    // character types: char and Character
    public char[]      acVal;

    public Character[] acVAL;

    // logical types: boolean and Boolean 
    public boolean[]   azVal;

    public Boolean[]   azVAL;

    // floating point types: double, Double, float and Float 
    public double[]    adVal;

    public Double[]    adVAL;

    public float[]     afVal;

    public Float[]     afVAL;

    // integer types: long, Long, int, Integer, short, Short, byte and Byte

    public long[]      ajVal;

    public Long[]      ajVAL;

    public int[]       aiVal;

    public Integer[]   aiVAL;

    public short[]     asVal;

    public Short[]     asVAL;

    public byte[]      abVal;

    public Byte[]      abVAL;




    public Byte[][]     aabVAL;




    // a static field 
    public static Comparator<?> cmp;

    // a field with Number type but no wrapper of primitive type 

    public BigDecimal bdVal;

    // string and string array 
    public String    str;
    public String[] aStr;


    /**
     * Creates a new <code>OctaveInterfaceTester</code> instance.
     *
     */
    public OctaveInterfaceTester() {

    }

    private Object inaccessibleO() {
	return "return string O";
    }

    // sets dVAL 
    public void setDouble(Double num) {
	System.out.println("D");
	this.dVAL = num;
    }

    // sets dVal
    public void setDouble(double num) {
	System.out.println("d");
	this.dVal = num;
    }

    public Object throwException(int num) {
	throw new IllegalStateException("No input can be valid. ");
    }

    public Object returnNull() {
	return null;
    }

    public static Object returnNullS() {
	return null;
    }

    public void returnVoid() {
    }

    public String toString() {
	StringBuffer res = new StringBuffer();
	Field[] fields = this.getClass().getFields();
	for (int idx = 0; idx < fields.length; idx++) {
	    if (!Modifier.isPublic(fields[idx].getModifiers())) {
		continue;
	    }

	    res.append(fields[idx].getName());
	    res.append(' ');
	    try {
		res.append(fields[idx].get(this));
	    } catch (IllegalAccessException e) {
		throw new IllegalStateException
		    ("Found non-public field '" + fields[idx].getName() +"'. ");
	    }
	    res.append('\n');
	}

	return res.toString();
    }

    // vital for tests: static m ethod 
    public static void main(String[] args) throws Exception {// NOPMD
	System.load
	    ("/home/ernst/Octave/octave/.build/libinterp/.libs/" + 
	     "liboctinterp.so.3.0.0");
	org.octave.Octave o = new org.octave.Octave();
	System.out.println("need threaded invocation: "
	 		   + o.needThreadedInvocation());

	Object[] argin, argout;
	o.doEvalString("1;");
	//o.doEvalString("a");
	argin  = new Object[0];
	argout = new Object[1];
	argin  = new Object[] {Double.valueOf(1)};
	argout = new Object[1];// {Double.valueOf(42)};
	System.out.println("call succeeded: "+o.call("sin", argin, argout));
	System.out.println("result in:  "+argin [0]);
	System.out.println("result out: "+argout[0]);
	//o.doEvalString("42;");


	// java.io.File file = new java.io.File ("/home/ernst");//("../Software");//("~/Octave");
	// System.out.println(":"+file.toURI ());
	// java.net.URL url = new java.net.URL("~/Octave");
	// System.out.println(":"+url.toURI());
    }
}
