import javax.swing.*;
import java.util.*;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

/* master server */
class Wind2 extends Thread {
	protected String inifile;
	protected boolean useDlogClock, useWrenDAQ;
	protected String stationID;
	protected boolean hideGUI;
	protected IniFile ini;
	Wind2SmallDisplay disp;
	WrenDAQSmallDisplay wrenDAQdisp;

	
	
	Wind2 (String inifilename) {
		inifile = inifilename;
	}

	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 + ")";
	}

	protected void loadHistory() {
		String directory = ini.getValue("LOGLOCAL","directory");
		
		/* current date */
		Date now = new Date();
		DateFormat df = new SimpleDateFormat("yyyyMMdd");
		/* replace the provided date with our date */
		
		String filename = directory + "/" + df.format(now) + ".CSV";
		System.err.println("# Loading history from " + filename);
		
		File f = new File(filename);
		if ( ! f.canRead() ) {
			System.err.println("# Cannot read history file");
			return;
		}
		
		
		BufferedReader inputStream;
		/* Open file */
		try {
			inputStream = new BufferedReader(new FileReader(filename));
			
			String line;
			Wind2Record rec;
			
			int i=0;
			while ( inputStream.ready() ) {
				line=inputStream.readLine();
				rec=new Wind2Record(line,true);
				
				if ( ! rec.isValid() )
					continue;
				
				disp.addHistoricalRecord(rec);
				i++;
				
				if ( 0 == i%100 ) {
					System.err.print(".");
				}
			}
            if ( null != inputStream ) {
            	inputStream.close();
            }
            System.err.println("\n# " + i + " records read from history");

			
		} catch (IOException e) {
			System.err.println("Exception: " + e);
		}

		
		
	
	}
	
	@SuppressWarnings("deprecation")
	public void run() {
		// Open configuration file
		ini = new IniFile(inifile);
		stationID = ini.getValue("GENERAL", "stationID").toUpperCase();
		useDlogClock=ini.isTrue("GENERAL", "useDlogClock");
		hideGUI=ini.isTrue("GENERAL","hideGUI");
		useWrenDAQ=ini.isTrue("WRENDAQ","useWrenDAQ");
		
		
		/* GUI screens */
		disp=null;
		wrenDAQdisp=null;

		System.err.println("# Establishing data link");
		/* we can have one data source. Currently they are {tcp, serial} */
		Wind2Link link = null;
		if ("tcp".equals(ini.getValue("LINK", "type"))) {
			link = new Wind2TCPLink(ini);
		} else if ("serial".equals(ini.getValue("LINK", "type"))) {
			link = new Wind2SerialLink(ini);
		} else {
			System.err.println("Invalid Configuration File");
			new Wind2Select().show();
			return;
		}

		if ( ! hideGUI ) {
			/* Start the GUI */
			disp = new Wind2SmallDisplay(ini);

			/* only show wrenDAQ if we have that enabled in ini file */
			if ( useWrenDAQ ) {
				wrenDAQdisp = new WrenDAQSmallDisplay(ini);
			}
		}
		
		/* if we are loading history then do so now */
		if ( ini.isTrue("GUI","loadHistory") && null != ini.getValue("LOGLOCAL","directory")) {
			loadHistory();
		}

		// Establish the Link
		if (!link.Connect()) {
			String message = "Invalid link type.";

			if ( "tcp".equals(ini.getValue("LINK","type")) ) {
				message = "Failed to establish " + ini.getValue("LINK","type").toUpperCase() + " link to " + ini.getValue("TCP","host") + ":" + ini.getValue("TCP","port");
			} else if ( "serial".equals(ini.getValue("LINK","type")) ) {
				message = "Failed to establish " + ini.getValue("LINK","type").toUpperCase() + " link to " + ini.getValue("SERIAL","port");
			}


			System.err.println("ABORT: Error Establishing Link\n" + message);
			if ( ! hideGUI ) {
				JOptionPane.showMessageDialog(disp.f, message, "Link Failure", JOptionPane.ERROR_MESSAGE);

				/* kill the gui screens */
				if ( useWrenDAQ )
					wrenDAQdisp.f.dispose();

				disp.f.dispose();
				new Wind2Select().show();
			}

			return;
		}

		Wind2Mysql db = null;
		if (ini.isTrue("MYSQL", "useMySQL")) {
			db = new Wind2Mysql(ini);
			try {
				db.connect();
			} catch (Exception e) {
				System.err.println("Failed to connect to MySQL database.");
				System.err.println(e);
				db = null;
			}
		}

		LogHTTP http = null;
		if (ini.isTrue("LOGHTTP", "useLogHTTP")) {
			System.err.println("# Using LogHTTP");
			http = new LogHTTP(ini);
		}


		LogLocal log = null;
		if (ini.isTrue("LOGLOCAL", "useLogLocal")) {
			String directory = ini.getValue("LOGLOCAL","directory");
			System.err.println("# Using LogLocal");
			log = new LogLocal(directory);
		}

		disp.setVisible(true);
		String line;
		while ((line = link.getLine()) != null) { 
			System.out.println(line);

			/* determine record type and handle appropriately */
			if ( useWrenDAQ && line.startsWith("A1076") ) {
				/* wrenDAQ */
				WrenDAQRecord rec = new WrenDAQRecord(line);

				if ( rec.isValid() ) {
					if ( ! hideGUI )  {
						wrenDAQdisp.updateDisplay(rec);
					}
				} else {
					System.err.println("Invalid line data from WrenDAQ.");
				}
			} else {
				/* default: wind data logger */
				Wind2Record rec = new Wind2Record(line,useDlogClock);

				if (rec.isValid()) {
					if ( ! hideGUI ) {
						disp.updateDisplay(rec);
					}

					/* wind2record may have modified the line (ie change the date), so we use it from now on */
					line=rec.wind2record;

					/* log to text file, if requested */
					if ( null != log ) {
						log.log(line,rec.rxDate);
					}

					/* insert record into database and update the date of the last received packet */
					if (db != null) {
						String sql = sqlInsert(rec.sqlValues(), rec.date);
						db.query(sql);
						sql="UPDATE siteInfo SET last_packet_date=now() WHERE station_id='" + stationID + "'";
						db.query(sql);
					}
				} else {
					System.err.println("Invalid line data from Wind Data Logger.");
				}

			}

			/* everything gets here */

			/* send our line of data to the web */	
			if (http != null) {
				http.sendRecord(line);
			}
		}

		// Clean Up
		link.Disconnect();
	}

	public static void main (String args[]) {
		String ini = null;

		// Parse arguments
		if (args.length == 0) {
			new Wind2Select().setVisible(true);
			return;
		} else if (args.length == 1) {
			ini = args[0];
		} else {
			System.err.println("Usage: java Wind2 inifile");
			System.err.println("Invoke with -Dswing.aatext=true for anti-aliased fonts");
			System.exit(-1);
		}

		(new Wind2(ini)).start();
	}
}
