package lbl.als.SCA;

/** Implements Simple Channel Access for accessing EPICS PVs
 * @author Chris Timossi Lawrence Berkeley National Laboratory
 * @version 1.0
 */
public class JSca {
    
    private String group;
    private int status;
    private int nr_elements = 0;
    
    static {
        System.loadLibrary("JSca");
    }
    
    /** Constructor with no arguments sets group
     * name to "DefaultGroup"
     */
    public JSca() {
        this.group = new String("DefaultGroup");
    }
    
    /** Constructor creates and names a group.
     *  PVs that are in the group will have their values refreshed
     *  at the same rate.
     * @param group A user selected string to identify the group
     */
    public JSca(String group) {
        this.group = new String(group);
    }
    
    /** Add a PV to the group
     * Adding PVs to a group optimizes performance of the name look ups
     * and allows batching of the 'gets'. Once all the items are added,
     * the first 'get' triggers the name look up. So the first 'get' will
     * be slowest.
     * @param pvname The name of the process variable to add.
     * @return The number of the item.
     * @exception JScaException Raised if get fails.
     */
    public synchronized int addItem (String pvname) throws JScaException {
        sca_group_additem(group,pvname);
        nr_elements++;
        return nr_elements;
    }
    
    /** Get a floating point value of the selected PV
     * @param pvname The name of the process variable.
     * @return The floating point value of the PV.
     * @exception JScaException Raised if get fails.
     */
    public synchronized float getFloat(String pvname) throws JScaException {
        return sca_group_getfloat(group,pvname);
    }
    
    /** Get a integer value of the selected PV
     * @param pvname The name of the process variable.
     * @return The integer point value of the PV.
     * @exception JScaException Raised if get fails.
     */
    public synchronized int getInt(String pvname) throws JScaException {
        return sca_group_getint(group,pvname);
    }
    
    /** Get a string value of the selected PV
     * @param pvname The name of the process variable.
     * @return The string value of the PV.
     * @exception JScaException Raised if get fails.
     */
    public synchronized String getString(String pvname) throws JScaException {
        return sca_group_getstring(group,pvname);
    }
    
     /** Set a floating point value of the selected PV
     * @param pvname The name of the process variable.
     * @param value The floating point value to set.
     * @exception JScaException Raised if the set fails.
     * @see SCA.sendValues
     */
    public synchronized void setFloat(String pvname, float value) throws JScaException {
        sca_group_setfloat(group,pvname,value);
    }
    
    /** Set an integer value for the selected PV
     * @param pvname The name of the process variable.
     * @param value  The integer value to set.
     * @see SCA.sendValues
     */
    public synchronized void setInt(String pvname, int value) throws JScaException {
        sca_group_setint(group,pvname,value);
    }
    
    /** Set a string value of the selected PV
     * @param pvname The name of the process variable.
     * @param value  The string value to set.
     * @see SCA.sendValues
     */
    public synchronized void setString(String pvname, String value) throws JScaException {
        sca_group_setstring(group,pvname,value);
    }
    
    /** Sends all the values that have been set
     * To change a PV value, the new value must first be set, then sent.
     * In this fashion, a number of new values maybe set before
     * they are actually sent out.
     * @see SCA.setString
     * @see SCA.setInt
     * @see SCA.setFloat
     */
    public synchronized int sendValues() throws JScaException {
        return sca_group_sendvalues();
    }
    
   /** Get the status of the previous get
     * @return The status of the previous get or put
     */
    public synchronized long getStatus() {
        return sca_get_status();
    }
    
    /** Frees the group
     *
     */
    protected void finalize () {
        sca_group_free(group);
    }
        
    private native int sca_group_additem(String group, String pvname);
    private native float sca_group_getfloat (String group, String name);
    private native int sca_group_getint (String group, String name);
    private native String sca_group_getstring (String group, String name);
    private native void sca_group_setfloat (String group, String name, float value);
    private native void sca_group_setint (String group, String name, int value);
    private native void sca_group_setstring (String group, String name, String value);
    private native int  sca_group_free(String group);
    private native int  sca_group_sendvalues();
    private native int sca_get_status();
    
    /** Test application to get or set PVs
     * Usage: java SCA.JSca pv_name [new value]
     * @param argv[0] The name of the process variable to get/set.
     * @param argv[1] If present, the PV is set to this value.
     */
    public static void main(String[] argv) {
       //set group name
       JSca sca1 = new JSca("group1");
       float newValue;
       
       //get values of PV name from the command line
        try {
            sca1.addItem(argv[0]);
            if ( argv.length == 2 ) {
                sca1.setString(argv[0],argv[1]);
                //newValue = Float.valueOf(argv[1]).floatValue();
                //sca1.setFloat(argv[0],newValue);
                sca1.sendValues();
                System.out.println(argv[0] +" new value = " + sca1.getString(argv[0]));
            }
        } catch (JScaException e) {
            System.out.println("Cant find name: " +argv[0]);
            System.out.println(e.getMessage());
        } catch (java.lang.ArrayIndexOutOfBoundsException e2) {
            System.out.println("Usage: java JSca <pv name> [<set value>]");
        }
        
        for (int i = 1; i <= 10000; i++)
        try {
            System.out.println(argv[0] +" float=   " + sca1.getFloat(argv[0]));
            System.out.println(argv[0] +" int =    " + sca1.getInt(argv[0]));
            System.out.println(argv[0] +" string = " + sca1.getString(argv[0]));
        } catch (JScaException e) {
            System.out.println(e.getMessage());
        }
    }
}