package serial;

import java.io.*;
import Serialio.*;

public class ph_driver {
    
	private SerialPortLocal sp;

	public ph_driver(String devName,SerialEvObserver obs) throws IOException {
	    init(devName);
		TermRcvTask rcv = new TermRcvTask(sp,obs);
		
		// TermSndTask snd = new TermSndTask(sp);
		//rcv.start();
		//snd.start();
		//System.out.println("\nUse ^C to exit...");
	    
	} // end ctor
	
	//public void addSerialEvObserver(SerialEvObserver obs ){aSerialEvObserver=obs;}
	    
    private void init(String devName){
	try {
    	SerialConfig serCfg = new SerialConfig(devName);
		sp = new SerialPortLocal(serCfg);
		// settings
		sp.setBitRate(SerialConfig.BR_9600);
        sp.setDataBits(SerialConfig.LN_8BITS);
        sp.setStopBits(SerialConfig.ST_1BITS);
        sp.setParity(SerialConfig.PY_NONE);
        //sp.setHandshake(SerialConfig.HS_CTSRTS);
        sp.setHandshake(SerialConfig.HS_NONE);
        //

		sp.setTimeoutRx(1000);
		sp.setDTR(true); //some modems will not respond if DTR is low
		//int verLib = sp.getLibVer();
		//short vMajor = (short)(verLib >> 16);
		//short vMinor = (short)(verLib & 0xffff);
		//System.out.println("DLL version: "+vMajor+"."+vMinor);
		
		
		putCommand("ate0"); // set echo off
		putCommand("ats10=20"); // set activity timeout
		
		
		}
	catch (Exception ioe) {
		System.out.println(ioe);
		System.exit(1);
		}
  	}
  	
	// write a byte to the serial line
	public void putByte(byte b) throws IOException {
	    sp.putByte(b);
	} // end putByte
	
	public void putString(String s) throws IOException {
	    sp.putString(s);
	} // end putString
	
	public void putDTMF(String s) {
	    try {
    	    sp.putString("atdt");
    	    sp.putString(s);
    	    sp.putByte((byte)13);
    	    sp.putByte((byte)10);
	    } catch (IOException e) { System.err.println("problems on the putDTMF "+e);}
	} // end putDTMF
	
	// hangup a call
	public boolean bye() {
	    return putCommand("ath");   // pick-up
	} // end bye
	
	// Answer an incoming call
	public boolean answer() {
	    return putCommand("ata");   // pick-up
	} // end answer
	
	public boolean putCommand(String cmd) {
	    try {
    	    sp.putString(cmd);sp.putByte((byte)13);sp.putByte((byte)10);
	    } catch (IOException e) { System.err.println("problems on the answer "+e);return false;}
	    return true;
	} // end answer
  	 

	public static void main(String args[]) throws IOException{
    	String devName = "com1";
    	if (args.length != 0)devName = args[0];
    	ph_driver aPh_driver = new ph_driver(devName,null);
	} // end main
} // end class

/*-----------------------------------------------------------------------------
 * This thread reads the Recieve buffer and displays the values on the
 * console as characters
 *---------------------------------------------------------------------------*/
class TermRcvTask extends Thread {
    
    private SerialEvObserver obs; 
    private SerialPortLocal sp;
    
    private final static int INIT = 0;
    
	public TermRcvTask(SerialPortLocal sp,SerialEvObserver obs ) throws IOException{
		if (sp.getPortNum() == -1)throw new IOException("TermSndTask: serial port not initialized");
	    this.obs = obs;
	    this.sp = sp;
	    
	    this.start(); // start the listener;
	    
	} // end ctor

	public void run() {
		int b;
		int state = INIT;
		StringBuffer line = new StringBuffer();
		StringBuffer DTMFLine = new StringBuffer();
		for (;;) {
			try {
				while((b = sp.getByte()) != -1) {
					// System.out.print((char)b+":"+b);
				    if ((b>='0')&(b<='9')|(b=='*')) { // DTMF TONE
				        SerialEv ev = new SerialDTMFEv((char)b);
				        if (obs!=null) obs.notify(ev);
				        DTMFLine.append((char)b);
				    }
				    
			        if (b=='#') { // end selection
			           if (obs!=null) obs.notify(new SerialDTMFLineEv(DTMFLine.toString()));
			           DTMFLine = new StringBuffer();
			        }
				    
                    // read the line until find the cr (10)
		            if (b==13) break; // skip CR
		            if (b==10) { // LF
				        SerialEv ev = new SerialLineEv(line.toString());
				        if (obs!=null) obs.notify(ev);
				        line = new StringBuffer();
				        break;
				    }
		                
                    line.append((char)b);
				    
				    //SerialEv ev = new SerialEv((char)b);
				    //if (obs!=null) obs.notify(ev);
				    
					// System.out.print((char)b);
				} // end while
			} catch (Exception e) {
				System.out.println("Error in TermRcvTask "+e);
		 		}
			}
		}

	SerialPortLocal p;
}

/*-----------------------------------------------------------------------------
 * This thread reads the keyboard for input and sends the keystrokes to
 * the serial port transmit buffer
 *---------------------------------------------------------------------------*/
class TermSndTask extends Thread {
	TermSndTask(SerialPortLocal sp) throws IOException
		{
		if (sp.getPortNum() == -1)
			throw new IOException("TermRcvTask: serial port not initialized");
		p = sp;
		}

	public void run() {
		int b;
		for (;;) {
			try {
//				System.out.println("Input...");
				b = System.in.read(); // blocks if input not available
//				System.out.println("PutByte("+b+")");
				p.putByte((byte)b);
				}
			catch (Exception e) {
				System.out.println("Error in TermSndTask "+e);
				}
			}
		}

	SerialPort p;
}