/*
 Copyright (c) 1997 by Columbia University. All rights reserved.
 */
import java.io.*;
import java.net.*;
import java.util.*;
import tjt.util.MsgDialog;
import symantec.itools.multimedia.SoundPlayer;

/**
 * NetTest includes the main function for the application.
 * It creates the GUI objects and displays them and it also 
 * calls the TracertWrapper and PingWrapper functions. 
 * This seperation allows for another interface to be easily
 * added (i.e. text based interface)
 * @version 1.0 31 Aug 1998
 * @author Terrence Truta
 */
 public class NetTest {
	//private TracertWrapper tw;
	private DisplayGUI guiDisplay;
	private ChartData chartdata;
  private StartGUI guiStart;
	private AutoOptions autoOptions;
	
	private boolean bDisplay = true; //display results of Trace true/false
	
	private boolean debug = false;

	private Vector tests;

	/** The main method of the the application */
	public static void main (String[] args) {
	  new NetTest();
	}
	
	/**
	 * The only constructor for NetTest. It just shows the initial GUI Frame
	 */
	NetTest() {
		try {
		 
		guiStart = new StartGUI(this);
		guiStart.show();


		} catch (Exception e) {
			System.out.println(e);
			System.exit(1);
		}
	}

	/**
	 * Disposes all GUI Frames, sets all the objects to null, then exits.
	 */
	public void exit() {
		if (guiStart != null) guiStart.dispose();
		if (guiDisplay != null) guiDisplay.dispose();
		guiStart = null;
		guiDisplay = null;
		chartdata = null;
		System.exit(0);
	}

	/** Uses a TracertWrapper object to run a standard traceroute to 
	  * a choosen host. It gets a ChartData object from the TracertWrapper
		* object which stores the data from the traceroute program. If this
		* method was called directly from StartGUI then it passes this object
		* to StartGUI. 
		*/
	public void executeTrace() {
		debugPrint("executing trace");
	  String host = guiStart.getHost();
		try {
			InetAddress address = InetAddress.getByName(host);
		} catch (UnknownHostException e) {
			guiStart.displayErrMsg("Error resolving host name.");
			return;
		}


		TracertWrapper tw = new TracertWrapper();
		debugPrint("setting address...");
		
		tw.setAddress(host);
		tw.setGUI(guiStart); //to update progress bar
		int progress;
		if (bDisplay) 
			progress = 4;
		else
			progress = 1;
		tw.setProgressIncr(progress);
		debugPrint("set Address to: " + host);
		tw.execute();
		debugPrint("setting data...");
		chartdata = tw.getChartData();
		chartdata.setAddress(host);
		
		if (bDisplay) {
			if (guiDisplay == null) guiDisplay = new DisplayGUI(this);
			guiDisplay.displayData(chartdata);
			guiDisplay.show();
			guiStart.resetProgressBar();
		}
		//guiStart.incrementProgressBar(10);
	}

	/** This method executes the ping program to the choosen host repeatedly
	  * with a delay between executions. The amount of times it is repeated
		* depends on the options choosen by the user which are stored in the
		* AutoOptions object. The <tt>monitorHours</tt> field determines how many
		* hours to stay in this method and the <tt>testMinutes</tt> specifies the
		* time between ping executions. After each execution of ping it tests the
		* alert cases choosen by the user if anything. If these cases are true then
		* a message box is displayed (modally) or an email is sent.
		*/
	public void executeAutoPing(AutoOptions ao) {
	  debugPrint("executing auto ping");
		this.autoOptions = ao;
		String host = guiStart.getHost();
		PingWrapper pw = new PingWrapper();
		//tests = new Vector();
		try {
			InetAddress address = InetAddress.getByName(host);
			pw.setAddress(host);
		} catch (UnknownHostException e) {
			guiStart.displayErrMsg("Error resolving host name.");
			return;
		}
		
    int numTests;
		int progress;
		try {
			numTests = (int)(ao.monitorHours * 60)/ao.testMinutes;
			debugPrint("numTests = " + numTests);
			progress = 100 / numTests;
			if (progress == 0) progress = 1;
		} catch (Exception e) {
			guiStart.displayErrMsg("Error calculating number of tests.");
			return;
		}

		int avg[] = new int[numTests];
		int loss[] = new int[numTests];
		long time[] = new long[numTests];
		for (int i = 0; i < numTests; i++) {
				

			  pw.execute();
				debugPrint("finished executing PingWrapper");
				guiStart.incrementProgressBar(progress);
				
				avg[i] = pw.getAvg();
				loss[i] = pw.getLost();
				time[i] = System.currentTimeMillis();
				debugPrint("avg[i] = " + avg[i] + ", loss[i] = " + loss[i]);
				
				debugPrint("ao.alerts = " + ao.alerts);
				debugPrint("ao.unreachable = " + ao.unreachable + ", ao.delay = " 
										+ ao.delay + ", ao.loss = " + ao.loss);
				if (ao.alerts) {
					Vector msgs = new Vector();
					if (ao.unreachable && (avg[i] == 0)) 
					  msgs.addElement(new String(host + " is unreachable"));
					if (ao.delay && (avg[i] > ao.delayValue))
						msgs.addElement(new String("delay to " + host 
																	+	" is > " + ao.delayValue));
					debugPrint("loss[i] > ao.lossValue = " + (loss[i] > ao.lossValue));
					if (ao.loss && (loss[i] > ao.lossValue)){
						msgs.addElement(new String("losses to " + host 
																	+ " are > " + ao.lossValue));
						debugPrint("Added msg");
					}

					if (msgs.size() > 0) {
						if (ao.displayMsg) {
							MsgDialog d = new MsgDialog(guiStart, true);
							for (int j = 0; j < msgs.size(); j++) 
								d.addMsg((String)msgs.elementAt(j));
							d.show();
						}
						/*if (ao.playSound) {
								try {
								SoundPlayer soundPlayer1 = new SoundPlayer();
								soundPlayer1.addStringURL(ao.soundFile);
								//URL url = new URL ("http://www-hsc.usc.edu/~gallaher/k_speaks/SanFrancisco.au");
							  soundPlayer1.play();
								} catch (Exception e) {}
						}*/
						if (ao.sendEmail) {
							try {
						  debugPrint("Sending email...");
						  String	cmd = "mail -s \"NetTest Alert\" " + ao.emailAddress;
							String msg = "The following events triggered this alert:\n";
							for (int j = 0; j < msgs.size(); j++) 
								msg = msg + (String)msgs.elementAt(j) + "\n";
							cmd = cmd + " < \"" + msg + "\"";
							debugPrint(cmd);
							Process p = Runtime.getRuntime().exec(cmd);
							} catch (Exception IO) {
								System.out.println("Error sending email");
							}
						}							
					}
				}
				
				if ((i+1) == numTests) break; //break before sleeping again since we are done
				//sleep until its time for the next test		
				try {
					Thread.sleep((long)(ao.testMinutes * 60 * 1000)); //convert min to millis
				} catch (Exception e) {}
		}
		
		if (ao.displaySummary) {
			if (guiDisplay == null) guiDisplay = new DisplayGUI(this);
			guiDisplay.displaySummaryData(avg, loss, time);
			guiDisplay.show();
		}
		guiStart.resetProgressBar();


	debugPrint("finished auto trace");



	}


/** Executes the ping program for every host identified after using the 
  * the traceroute program. If the traceroute program hasn't been executed to
	* the choosen host before calling this method, this method calls executeTrace
	* to obtain the names and IP addresses of all the hosts between the localhost
	* and the choosen host. It stores this information in the ChartData object
	* and then displays the data with the DisplayGUI object.
	*/
public void executeThoroughTrace() {

  debugPrint("executing thorough trace");
	try {
			//execute Tracert first if it hasn't been run already
			if ((chartdata == null) || 
					(chartdata.getAddress().compareTo(guiStart.getHost()) != 0)) {
				 bDisplay = false; //don't display anything yet
				 executeTrace();
				 bDisplay = true;
			}
			else
				guiStart.incrementProgressBar(chartdata.getLength());

		//if chartdata is still null then a problem must have occured
		if (chartdata == null) {
			guiStart.displayErrMsg("Error executing traceroute program.");
			return;
		}

		PingWrapper pw = new PingWrapper();
		
		int progress = (100 - chartdata.getLength()) / chartdata.getLength();
		debugPrint("progress is " + progress);
		debugPrint("chartdata.getLength() = " + chartdata.getLength());
		for (int i = 0; i < chartdata.getLength(); i++) {
		  try {
	  		debugPrint("IPNum[i] = " + chartdata.IPNum[i]);
	  		InetAddress address = InetAddress.getByName(chartdata.IPNum[i]);
				debugPrint("setting address: " + chartdata.hostName[i]);
	 		  pw.setAddress(chartdata.hostName[i]);
			}
		  catch (UnknownHostException e) {
				debugPrint("UnknownHostException");
				chartdata.avg[i] = 0;
				chartdata.packetLoss[i] = 0;
				continue;
			}
			
			pw.execute();
		  debugPrint("finished executing PingWrapper");
			guiStart.incrementProgressBar(progress);
		  chartdata.avg[i] = pw.getAvg();
		  chartdata.packetLoss[i] = pw.getLost();
		}
    chartdata.pingData = true;
		debugPrint("setting data...");
		
		if (guiDisplay == null) guiDisplay = new DisplayGUI(this);
		guiDisplay.displayData(chartdata);
		guiDisplay.show();
		guiStart.resetProgressBar();

	} catch (Exception e) {
		guiStart.displayErrMsg("Error executing traceroute program.");
		return;
	}
}



private void debugPrint(String s) {
       if (debug) System.out.println(s);
}

}
		