/*
 * IPump2Midlet.java
 *
 * Created on 07 May 2009, 19:47
 */

package iPump2;

import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
import javax.bluetooth.*;

/**
 *
 * @author Marco
 */
public class IPump2Midlet extends MIDlet implements CommandListener {
    
    private CommConnection      mBthConnection  =null;
    private OutputStream        mBthOS          =null;  // output stream from bluetooth connection.
    private InputStream         mBthIS          =null;  // Input stream from bluetooth connection.
    
    public class CBluetoothRecvr extends Thread
    {
        Form mHelloForm;
        StringItem mStatusStringItem;
        Alert mPumpingAlert;
        int progress;
//        Gauge mProgressGauge;
                
        CBluetoothRecvr(Form helloForm,StringItem statusStringItem,Alert pumpingAlert)
        {
            mHelloForm=helloForm;
            mStatusStringItem=statusStringItem;
            mPumpingAlert=pumpingAlert;
            progress=0;
//            mProgressGauge=progressGauge;
        }
        public void bthSend(String msg)
        {
            try
            {
//                mHelloForm.append("\n>Sending: "+msg);
                mBthOS.write((msg+"\r").getBytes());
            }
            catch (Exception ioe)
            {                
            }
        }
        public void run()
        {
            boolean             mConnected      =false;

//            mHelloForm.append("\n>Waiting pump connection");
            
            mStatusStringItem.setText("\nWaiting pump connection");
            
            while (true)
            {
                try
                {
                    mBthConnection=(CommConnection)Connector.open("comm:AT1");
                    // If we've made it here then we have not thrown an exception because the port is not
                    // open, therefore me must be connected.
                    mBthIS=mBthConnection.openInputStream();                
                    mBthOS=mBthConnection.openOutputStream();//openDataOutputStream();
//                    mConnected=true;
                    mStatusStringItem.setText("\nPump connected");
//                    mHelloForm.append("\n>Connected");
                    bthSend("OK");
//                    mBthOS.write(("OK\r").getBytes());
//                    while (mConnected==true)
                    while (mBthConnection!=null && mBthIS!=null && mBthOS!=null)
                    {
                        // Start waiting for messages.
                        String msg="";
                        byte[] data=new byte[1000];
//                        mHelloForm.append("\nA");
                        int length =mBthIS.read(data);
//                        mHelloForm.append("\nB");
                        while (length!=-1)
                        {
                            msg+=new String(data,0,length);
                            // Watch out for the end of the msg. Marked with a \r.
                            if (msg.indexOf('\r')>=0)
                            {
                                break;
                            }
                            length=mBthIS.read(data);
                        }
                        if (msg.length()==0)
                        {
                            mBthIS.close();
                            mBthOS.close();
                            mBthConnection.close();
                            break;
                        }
                        else
                        {
//                            mHelloForm.append("\n>Received: "+msg);                                
                            if (msg.startsWith("ACK"))
                            {
                                bthSend("OK");
                            }
                            else if (msg.startsWith("Pump"))
                            {
//                                if (progress==0)
//                                {
//                                    mPumpingAlert.getIndicator().setMaxValue(10);
//                                    mPumpingAlert.getIndicator().setValue(0);
//                                    
//                                }
//                                int progress=this.mProgressGauge.getValue();
//                                progress++;
//                                mProgressGauge.setValue(progress);
                                mStatusStringItem.setText("\n"+msg);
                                mPumpingAlert.setString(msg);
//                                mPumpingAlert.getIndicator().setValue(progress);
//                                mPumpingAlert.setIndicator()                              
                                bthSend("OK");
                            }
                            else
                            {
                                mHelloForm.append("\n>Received: ("+msg+")");                                
                            }
                        }
                    }
                    mStatusStringItem.setText("\nPump disconnected");                    
                }
                catch (Exception ioe)
                {
                    if (ioe.getMessage().indexOf("such port")<0)
                    {
                        mHelloForm.append("\n"+ioe.getMessage());
                    }
                }
            }
        
        }
    }

    /**
     * Creates a new instance of IPump2Midlet
     */
    public IPump2Midlet() {
    }
    
    private Form helloForm;//GEN-BEGIN:MVDFields
    private StringItem helloStringItem;
    private Command exitCommand;
    private StringItem statusStringItem;
    private Spacer spacer1;
    private TextField doseTextField;
    private Spacer spacer2;
    private Command pumpCommand;
    private org.netbeans.microedition.lcdui.WaitScreen waitScreen;
    private Command cancelCommand;
    private Form form1;
    private Alert pumpingAlert;
    private Gauge indicator1;
    private org.netbeans.microedition.lcdui.SplashScreen splashScreen1;//GEN-END:MVDFields
    private CBluetoothRecvr bluetoothRecvr;

//GEN-LINE:MVDMethods

    /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin
     */
    private void initialize() {//GEN-END:MVDInitBegin
        // Insert pre-init code here
        getDisplay().setCurrent(get_helloForm());//GEN-LINE:MVDInitInit
        // Insert post-init code here
    }//GEN-LINE:MVDInitEnd
    
    /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin
     * @param command the Command that ws invoked
     * @param displayable the Displayable on which the command was invoked
     */
    public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin
        // Insert global pre-action code here
        if (displayable == helloForm) {//GEN-BEGIN:MVDCABody
            if (command == exitCommand) {//GEN-END:MVDCABody
                // Insert pre-action code here
                exitMIDlet();//GEN-LINE:MVDCAAction3
                // Insert post-action code here
            } else if (command == pumpCommand) {//GEN-LINE:MVDCACase3
                // Insert pre-action code here
                getDisplay().setCurrent(get_pumpingAlert(), get_helloForm());//GEN-LINE:MVDCAAction12
                // Insert post-action code here
                statusStringItem.setText("\nRequesting "+doseTextField.getString()+" units");
                bluetoothRecvr.bthSend("DOSE:"+doseTextField.getString());                
            }//GEN-BEGIN:MVDCACase12
        } else if (displayable == waitScreen) {
            if (command == waitScreen.FAILURE_COMMAND) {//GEN-END:MVDCACase12
                // Insert pre-action code here
                // Do nothing//GEN-LINE:MVDCAAction15
                // Insert post-action code here
            } else if (command == waitScreen.SUCCESS_COMMAND) {//GEN-LINE:MVDCACase15
                // Insert pre-action code here
                // Do nothing//GEN-LINE:MVDCAAction14
                // Insert post-action code here
            } else if (command == cancelCommand) {//GEN-LINE:MVDCACase14
                // Insert pre-action code here
                // Do nothing//GEN-LINE:MVDCAAction17
                // Insert post-action code here
            }//GEN-BEGIN:MVDCACase17
        } else if (displayable == splashScreen1) {
            if (command == splashScreen1.DISMISS_COMMAND) {//GEN-END:MVDCACase17
                // Insert pre-action code here
                // Do nothing//GEN-LINE:MVDCAAction22
                // Insert post-action code here
            }//GEN-BEGIN:MVDCACase22
        }//GEN-END:MVDCACase22
        // Insert global post-action code here
}//GEN-LINE:MVDCAEnd
    
    /**
     * This method should return an instance of the display.
     */
    public Display getDisplay() {//GEN-FIRST:MVDGetDisplay
        return Display.getDisplay(this);
    }//GEN-LAST:MVDGetDisplay
    
    /**
     * This method should exit the midlet.
     */
    public void exitMIDlet() {//GEN-FIRST:MVDExitMidlet
        getDisplay().setCurrent(null);
        destroyApp(true);
        notifyDestroyed();
    }//GEN-LAST:MVDExitMidlet
    
    /** This method returns instance for helloForm component and should be called instead of accessing helloForm field directly.//GEN-BEGIN:MVDGetBegin2
     * @return Instance for helloForm component
     */
    public Form get_helloForm() {
        if (helloForm == null) {//GEN-END:MVDGetBegin2
            // Insert pre-init code here
            helloForm = new Form(null, new Item[] {//GEN-BEGIN:MVDGetInit2
                get_helloStringItem(),
                get_statusStringItem(),
                get_spacer1(),
                get_doseTextField(),
                get_spacer2()
            });
            helloForm.addCommand(get_exitCommand());
            helloForm.addCommand(get_pumpCommand());
            helloForm.setCommandListener(this);//GEN-END:MVDGetInit2
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd2
        return helloForm;
    }//GEN-END:MVDGetEnd2
    
    /** This method returns instance for helloStringItem component and should be called instead of accessing helloStringItem field directly.//GEN-BEGIN:MVDGetBegin4
     * @return Instance for helloStringItem component
     */
    public StringItem get_helloStringItem() {
        if (helloStringItem == null) {//GEN-END:MVDGetBegin4
            // Insert pre-init code here
            helloStringItem = new StringItem("iPump", "");//GEN-BEGIN:MVDGetInit4
            helloStringItem.setLayout(Item.LAYOUT_CENTER);//GEN-END:MVDGetInit4
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd4
        return helloStringItem;
    }//GEN-END:MVDGetEnd4
    
    /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin5
     * @return Instance for exitCommand component
     */
    public Command get_exitCommand() {
        if (exitCommand == null) {//GEN-END:MVDGetBegin5
            // Insert pre-init code here
            exitCommand = new Command("Exit", Command.EXIT, 1);//GEN-LINE:MVDGetInit5
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd5
        return exitCommand;
    }//GEN-END:MVDGetEnd5

    /** This method returns instance for statusStringItem component and should be called instead of accessing statusStringItem field directly.//GEN-BEGIN:MVDGetBegin6
     * @return Instance for statusStringItem component
     */
    public StringItem get_statusStringItem() {
        if (statusStringItem == null) {//GEN-END:MVDGetBegin6
            // Insert pre-init code here
            statusStringItem = new StringItem("Status:", "Unknown");//GEN-LINE:MVDGetInit6
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd6
        return statusStringItem;
    }//GEN-END:MVDGetEnd6

    /** This method returns instance for spacer1 component and should be called instead of accessing spacer1 field directly.//GEN-BEGIN:MVDGetBegin7
     * @return Instance for spacer1 component
     */
    public Spacer get_spacer1() {
        if (spacer1 == null) {//GEN-END:MVDGetBegin7
            // Insert pre-init code here
            spacer1 = new Spacer(1000, 1);//GEN-LINE:MVDGetInit7
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd7
        return spacer1;
    }//GEN-END:MVDGetEnd7

    /** This method returns instance for doseTextField component and should be called instead of accessing doseTextField field directly.//GEN-BEGIN:MVDGetBegin8
     * @return Instance for doseTextField component
     */
    public TextField get_doseTextField() {
        if (doseTextField == null) {//GEN-END:MVDGetBegin8
            // Insert pre-init code here
            doseTextField = new TextField("Enter Dose (units):", null, 120, TextField.NUMERIC);//GEN-LINE:MVDGetInit8
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd8
        return doseTextField;
    }//GEN-END:MVDGetEnd8

    /** This method returns instance for spacer2 component and should be called instead of accessing spacer2 field directly.//GEN-BEGIN:MVDGetBegin9
     * @return Instance for spacer2 component
     */
    public Spacer get_spacer2() {
        if (spacer2 == null) {//GEN-END:MVDGetBegin9
            // Insert pre-init code here
            spacer2 = new Spacer(1000, 1);//GEN-LINE:MVDGetInit9
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd9
        return spacer2;
    }//GEN-END:MVDGetEnd9
    /** This method returns instance for pumpCommand component and should be called instead of accessing pumpCommand field directly.//GEN-BEGIN:MVDGetBegin11
     * @return Instance for pumpCommand component
     */
    public Command get_pumpCommand() {
        if (pumpCommand == null) {//GEN-END:MVDGetBegin11
            // Insert pre-init code here
            pumpCommand = new Command("Pump", Command.OK, 1);//GEN-LINE:MVDGetInit11
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd11
        return pumpCommand;
    }//GEN-END:MVDGetEnd11

    /** This method returns instance for waitScreen component and should be called instead of accessing waitScreen field directly.//GEN-BEGIN:MVDGetBegin13
     * @return Instance for waitScreen component
     */
    public org.netbeans.microedition.lcdui.WaitScreen get_waitScreen() {
        if (waitScreen == null) {//GEN-END:MVDGetBegin13
            // Insert pre-init code here
            waitScreen = new org.netbeans.microedition.lcdui.WaitScreen(getDisplay());//GEN-BEGIN:MVDGetInit13
            waitScreen.addCommand(get_cancelCommand());
            waitScreen.setCommandListener(this);
            waitScreen.setTitle("Pumping");
            waitScreen.setText("Pumping");//GEN-END:MVDGetInit13
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd13
        return waitScreen;
    }//GEN-END:MVDGetEnd13

    /** This method returns instance for cancelCommand component and should be called instead of accessing cancelCommand field directly.//GEN-BEGIN:MVDGetBegin16
     * @return Instance for cancelCommand component
     */
    public Command get_cancelCommand() {
        if (cancelCommand == null) {//GEN-END:MVDGetBegin16
            // Insert pre-init code here
            cancelCommand = new Command("Cancel", Command.CANCEL, 1);//GEN-LINE:MVDGetInit16
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd16
        return cancelCommand;
    }//GEN-END:MVDGetEnd16

    /** This method returns instance for form1 component and should be called instead of accessing form1 field directly.//GEN-BEGIN:MVDGetBegin18
     * @return Instance for form1 component
     */
    public Form get_form1() {
        if (form1 == null) {//GEN-END:MVDGetBegin18
            // Insert pre-init code here
            form1 = new Form(null, new Item[0]);//GEN-LINE:MVDGetInit18
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd18
        return form1;
    }//GEN-END:MVDGetEnd18

    /** This method returns instance for pumpingAlert component and should be called instead of accessing pumpingAlert field directly.//GEN-BEGIN:MVDGetBegin19
     * @return Instance for pumpingAlert component
     */
    public Alert get_pumpingAlert() {
        if (pumpingAlert == null) {//GEN-END:MVDGetBegin19
            // Insert pre-init code here
            pumpingAlert = new Alert("Pumping", "Pumping", null, AlertType.CONFIRMATION);//GEN-BEGIN:MVDGetInit19
            pumpingAlert.setTimeout(-2);
            pumpingAlert.setIndicator(get_indicator1());//GEN-END:MVDGetInit19
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd19
        return pumpingAlert;
    }//GEN-END:MVDGetEnd19

    /** This method returns instance for indicator1 component and should be called instead of accessing indicator1 field directly.//GEN-BEGIN:MVDGetBegin20
     * @return Instance for indicator1 component
     */
    public Gauge get_indicator1() {
        if (indicator1 == null) {//GEN-END:MVDGetBegin20
            // Insert pre-init code here
            indicator1 = new Gauge(null, false, 100, 50);//GEN-LINE:MVDGetInit20
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd20
        return indicator1;
    }//GEN-END:MVDGetEnd20

    /** This method returns instance for splashScreen1 component and should be called instead of accessing splashScreen1 field directly.//GEN-BEGIN:MVDGetBegin21
     * @return Instance for splashScreen1 component
     */
    public org.netbeans.microedition.lcdui.SplashScreen get_splashScreen1() {
        if (splashScreen1 == null) {//GEN-END:MVDGetBegin21
            // Insert pre-init code here
            splashScreen1 = new org.netbeans.microedition.lcdui.SplashScreen(getDisplay());//GEN-BEGIN:MVDGetInit21
            splashScreen1.setCommandListener(this);//GEN-END:MVDGetInit21
            // Insert post-init code here
        }//GEN-BEGIN:MVDGetEnd21
        return splashScreen1;
    }//GEN-END:MVDGetEnd21
    
    public void startApp() {
        initialize();
        bluetoothRecvr=new CBluetoothRecvr(get_helloForm(),
                this.get_statusStringItem(),
                this.get_pumpingAlert());
/*        this.get_progressGauge().setMaxValue(10);
        for (int i=0;i<10;i++)
        {
            this.get_progressGauge().setValue(i);
        }
        this.get_progressGauge().setMaxValue(this.get_progressGauge().CONTINUOUS_RUNNING);*/
        bluetoothRecvr.start();
    }
    
    public void pauseApp() {
    }
    
    public void destroyApp(boolean unconditional) {
        try
        {
            this.mBthOS.close();
            this.mBthIS.close();
            this.mBthConnection.close();
        }
        catch (Exception e)
        {
            helloForm.append(e.getMessage());
        }
    }
    
}

