import gnu.io.*;
import java.util.*;
import java.io.*;

class Wind2SerialServer {

	protected String wantedPortName;
	protected BufferedReader is;
	protected PrintStream os;
	protected SerialPort port;
	protected String stationID;
	protected boolean useDlogClock, useDB, useLogHTTP;
	protected IniFile ini;
	
	protected void initSerial() {
	//	wantedPortName = "/dev/ttyS0"; // platform specific port name, here a Unix name

		Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers();
		
		/* Check each identifier if (a) it indicates a serial (not a parallel)
		port, and (b) matches the desired name. */

		CommPortIdentifier portId = null;  // will be set if port found
		while (portIdentifiers.hasMoreElements()) { 
			CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement();
			if(pid.getPortType() == CommPortIdentifier.PORT_SERIAL && pid.getName().equals(wantedPortName)) {
				portId=pid;
				break;
			}
		}
		
		if(portId == null) {
			System.err.println("# Could not find serial port " + wantedPortName );
			System.exit(1);
		}

		port = null;
		try {
			/* application requesting port, milliseconds time-out */
			port = (SerialPort) portId.open( "name", 100 ); 
		} catch(PortInUseException e) {
				System.err.println("# Port already in use: " + e);
				System.exit(1);
		}

		/* setup serial port parameters */
		try { 
			port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
		} catch ( Exception e ) {
			System.err.println("# Error setting port parameters");
			System.exit(1);
		}

		is = null;
		os = null;

		try {
			is = new BufferedReader(new InputStreamReader(port.getInputStream()));
		} catch (IOException e) {
			System.err.println("# Can't open input stream: write-only");
			is = null;
		}

		try {
			os = new PrintStream(port.getOutputStream(), true);
		} catch ( IOException e ) {
			System.err.println("# Can't open output stream: read-only");
			os = null;
		}

		System.out.println("# Done initializing serial port");
	}

	protected void closeSerial() {
		/* shut down */
		try {
			// Very important to close output/input streams as well as the port. 
			if (is != null) {
				is.close();
				System.err.println("# input stream closed");
			}
			if (os != null) { 
				os.close();
				System.err.println("# output stream closed");
			}
			if (port != null) {
				port.close();
				System.err.println("# Serial port closed");
			}
		} catch ( IOException e ) {
			System.err.println("# caught IOException: " + e);
		}
	}

	public Wind2SerialServer(IniFile i) {
		ini=i;
		wantedPortName=ini.getValue("SERIAL","port");
		stationID=ini.getValue("GENERAL","stationID").toUpperCase();

		useDlogClock=ini.isTrue("GENERAL","useDlogClock");
		useDB=ini.isTrue("MYSQL","useMySQL");

		useLogHTTP=ini.isTrue("LOGHTTP","useLogHTTP");
	}

	protected String sqlInsert(String values, String date) {
		String d;
		if ( false == useDlogClock ) {
			d="now()";
		} else {
			d="'" + date + "'";
		}

		return "INSERT INTO data VALUES(CONCAT('" + stationID + "|" + "',now()),'" + stationID + "'," + d + "," + values + ")";
	}

	public void go() {
		/* open the serial port */
		initSerial();

		/* open the windData JDBC connection */
		Wind2Mysql db=new Wind2Mysql(ini);
		if ( useDB ) {
			try {
				db.connect();
			} catch ( Exception e ) {
				System.err.println("# Exception encountered when trying to connect to MySQL server.");
				System.err.println("# MySQL will not be used. ");
				System.err.println(e);
				useDB=false;
			}
		}

		/* setup the LogHTTP, if enabled */
		LogHTTP http = new LogHTTP(ini);

		/* setup the GUI */
		Wind2SmallDisplay disp = new Wind2SmallDisplay(ini);


		/* actually do something */
		String line;
		String sql;
		Wind2Record rec;
		try { 
			while ( (line = is.readLine()) != null) {
				System.out.println( "received: " + line );
				rec=new Wind2Record(line,useDlogClock);

				if ( ! rec.isValid() ) {
					System.err.println("# Invalid CRC or exception parsing");
					continue;
				}

				if ( useDB ) {
					/* make SQL for data */
					sql=sqlInsert(rec.sqlValues(),rec.date);
					db.query(sql);
					System.out.println("SQL: " + sql);

					/* update last time in siteInfo table */
					sql="UPDATE siteInfo SET last_packet_date=now() WHERE station_id='" + stationID + "'";
					db.query(sql);
					System.out.println("SQL: " + sql);
				}

				if ( useLogHTTP ) {
					http.sendRecord(rec.wind2record);
				}

				System.out.println("------------------------------------------------------------------");

				disp.updateDisplay(rec);

			}
		} catch ( IOException e ) {
			System.err.println("# error reading line: " + e);
		}

		/* free */
		db.close();
		closeSerial();
	
	}
}
