//-----------------------------------------------------------------------------
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606
//-----------------------------------------------------------------------------
//
// Description:
//      JAVA Applet for rsvc name server
//
// Author:  
//      Jie Chen
//      Jefferson Lab HPC Group
//
// Revision History:
//   $Log: rsvcDisplay.java,v $
//   Revision 1.1.1.1  2000/05/23 15:12:50  pal
//   cdev_psi_1.7.2
//
//   Revision 1.3  1999/12/14 15:38:16  chen
//   Add scrollbar to display
//
//   Revision 1.2  1999/10/18 17:16:06  chen
//   minor changes
//
//   Revision 1.1  1999/10/18 17:12:42  chen
//   *** empty log message ***
//
//
//
//
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;
import rsvcData;
import rsvcDataEntry;
import rsvcClient;
import rsvcEventHandler;
import rsvcConfig;

public class rsvcDisplay extends Applet implements Runnable, rsvcEventHandler
{
    // display tag names
    private final String[] tags_ = {"name","domain","status","host", "port", "owner"};
    private final int numtags_  = 6;

    // top level scroll pane
    private ScrollPane sclp_ = null;
    // top level panel
    private Panel dpanel_ = null;

    // title field of display
    private Label title_ = null;
    // information field of display
    private Label info_ = null;

    // maximum number of entries
    private final int size_ = 40;

    // current number of entries
    private int       num_ = 0;

    // category filed labels
    private Label nameLabel_ = null;
    private Label domainLabel_ = null;
    private Label statusLabel_ = null;
    private Label hostLabel_ = null;
    private Label portLabel_ = null;
    private Label userLabel_ = null;


    // diffrent fields
    private TextField[] name_;
    private TextField[] domain_;
    private TextField[] status_;
    private TextField[] host_;
    private TextField[] port_;
    private TextField[] user_;
    
    // layout
    private GridBagLayout layout_ = null;
    private GridBagConstraints c_ = null;

    // network connection
    private rsvcClient client_ = null;
    private String     serverHost_ = null;
    private int        serverPort_ = 0;

    // seperate thread to handle clean up information box
    private Thread     timerThread_ = null;

    public void setServerHost (String host)
    {
	serverHost_ = host;
    }

    public void setServerPort (int p)
    {
	serverPort_ = p;
    }

    private void startTimerThread ()
    {
	if (timerThread_ == null) {
	    timerThread_ = new Thread (this);
	    timerThread_.start();
	}
	else
	    timerThread_.resume ();

    }

    private void createLabel (String label)
    {
	Font lfont = new Font ("times", Font.BOLD, 14);
	Color lc = Color.blue;

	c_.weightx = 0;
	c_.gridwidth = GridBagConstraints.REMAINDER;
	title_ = new Label (label, Label.CENTER);
	title_.setFont (lfont);
	title_.setForeground (lc);
	layout_.setConstraints(title_, c_);
	dpanel_.add(title_);
    }

    private void createInfoLabel ()
    {
	Font lfont = new Font ("times", Font.BOLD, 12);

	c_.weightx = 0;
	c_.gridwidth = GridBagConstraints.REMAINDER;
	info_ = new Label ();
	info_.setFont (lfont);
	layout_.setConstraints(info_, c_);
	dpanel_.add (info_);
    }

    private void setInformation (String info)
    {
	info_.setText (info);
    }

    private void clearInformation ()
    {
	info_.setText (null);
    }

    private void createFieldLabels ()
    {
	Font lfont = new Font ("helvetica", Font.ITALIC, 12);
	c_.weightx = 1;
	c_.gridwidth = 1;
	nameLabel_ = new Label ("Name", Label.CENTER);
	nameLabel_.setFont (lfont);
	layout_.setConstraints(nameLabel_, c_);
	dpanel_.add(nameLabel_);

	domainLabel_ = new Label ("Domain", Label.CENTER);
	domainLabel_.setFont (lfont);
	layout_.setConstraints(domainLabel_, c_);
	dpanel_.add(domainLabel_);

	statusLabel_ = new Label ("Status", Label.CENTER);
	statusLabel_.setFont (lfont);
	layout_.setConstraints(statusLabel_, c_);
	dpanel_.add(statusLabel_);

	c_.gridwidth = 2;
	hostLabel_ = new Label ("Host", Label.CENTER);
	hostLabel_.setFont (lfont);
	layout_.setConstraints(hostLabel_, c_);
	dpanel_.add(hostLabel_);

	c_.gridwidth = 1;
	portLabel_ = new Label ("Port", Label.CENTER);
	portLabel_.setFont (lfont);
	layout_.setConstraints(portLabel_, c_);
	dpanel_.add(portLabel_);

	c_.gridwidth = GridBagConstraints.REMAINDER;
	userLabel_ = new Label ("User Name", Label.CENTER);
	userLabel_.setFont (lfont);
	layout_.setConstraints(userLabel_, c_);
	dpanel_.add(userLabel_);
    }

    private void createEmptyFields (int index)
    {
	c_.gridwidth = 1;

	name_[index] = new TextField (10);
	name_[index].setEditable (false);
	layout_.setConstraints(name_[index], c_);
	dpanel_.add(name_[index]);
	
	domain_[index] = new TextField (10);
	domain_[index].setEditable (false);
	layout_.setConstraints(domain_[index], c_);
	dpanel_.add(domain_[index]);

	status_[index] = new TextField (10);
	status_[index].setEditable (false);
	layout_.setConstraints(status_[index], c_);
	dpanel_.add(status_[index]);

	c_.gridwidth = 2;
	host_[index] = new TextField (20);
	host_[index].setEditable (false);
	layout_.setConstraints(host_[index], c_);
	dpanel_.add(host_[index]);
	
	port_[index] = new TextField (10);
	port_[index].setEditable (false);
	layout_.setConstraints(port_[index], c_);
	dpanel_.add(port_[index]);


	c_.gridwidth = GridBagConstraints.REMAINDER;	
	user_[index] = new TextField (10);
	user_[index].setEditable (false);
	layout_.setConstraints(user_[index], c_);
	dpanel_.add(user_[index]);

	// force to display
	validate ();
    }

    private void updateEntryAt (rsvcData data, int index)
    {
	String dispval = null;
	int    i = 0;

	rsvcDataEntry dentry = data.get (tags_[i++]);
	dentry = data.get (tags_[i++]);

	dentry = data.get (tags_[i++]);
	int statusval;
	if (dentry != null) {
	    statusval = dentry.intValue ();
	    if (statusval == 0) {
		status_[index].setBackground (Color.green);
		status_[index].setText ("Alive");
	    }
	    else if (statusval == 2) {
		status_[index].setBackground (Color.red);
		status_[index].setText ("Dead");
	    }
	    else if (statusval == 1) {
		status_[index].setBackground (Color.yellow);
		status_[index].setText ("Dormant");
	    }
	    else {
		status_[index].setBackground (Color.white);
		status_[index].setText ("Unknown");
	    }
	}

	dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    host_[index].setText (dispval);
	}

	dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    port_[index].setText (dispval);
	}


	dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    user_[index].setText (dispval);
	}
    }


    public void updateEntry (rsvcData data, boolean create)
    {
	int i = 0;
	String dispval = null;
	String name = null;
	String domain = null;

	rsvcDataEntry dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    name = dispval;
	}

	dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    domain = dispval;
	}

	i = 0;
	String tname = null;
	String tdomain = null;
	int found = 0;

	if (name != null && domain != null) {
	    for (i = 0; i < num_; i++) {
		tname = name_[i].getText ();
		tdomain = domain_[i].getText ();
		if (name.compareTo (tname) == 0 &&
		    domain.compareTo (tdomain) == 0) {
		    updateEntryAt (data, i);
		    found = 1;
		    break;
		}
	    }
	}
	if (found == 0 && create == true)
	    addEntry (data);
    }
	

    public void addEntry (rsvcData data)
    {
	String dispval = null;
	int    i = 0;
	String name = null;
	String domain = null;
	    

	createEmptyFields (num_);

	rsvcDataEntry dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    name_[num_].setText (dispval);
	    name = dispval;
	}

	dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    domain_[num_].setText (dispval);
	    domain = dispval;
	}

	dentry = data.get (tags_[i++]);
	int statusval;
	if (dentry != null) {
	    statusval = dentry.intValue ();
	    if (statusval == 0) {
		status_[num_].setBackground (Color.green);
		status_[num_].setText ("Alive");
	    }
	    else if (statusval == 2) {
		status_[num_].setBackground (Color.red);
		status_[num_].setText ("Dead");
	    }
	    else if (statusval == 1) {
		status_[num_].setBackground (Color.yellow);
		status_[num_].setText ("Dormant");
	    }
	    else {
		status_[num_].setBackground (Color.white);
		status_[num_].setText ("Unknown");
	    }
	}

	dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    host_[num_].setText (dispval);
	}

	dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    port_[num_].setText (dispval);
	}


	dentry = data.get (tags_[i++]);
	if (dentry != null) {
	    dispval = dentry.stringValue ();
	    user_[num_].setText (dispval);
	}
	num_ ++;

	if (name != null && domain != null) {
	    rsvcData serverinfo = new rsvcData ();
	    rsvcEvent oevent = null;

	    serverinfo.insert ("name", name);
	    serverinfo.insert ("domain", domain);

	    try {
		oevent = client_.monitorValue ("cdevServers", serverinfo,
					       this);
	    }catch (IOException e) {
		;
	    }
	}
	    
    }

    private void cleanupEntries ()
    {
	for (int i = 0; i < num_; i++) {
	    remove (name_[i]);
	    remove (domain_[i]);
	    remove (status_[i]);	    
	    remove (host_[i]);
	    remove (port_[i]);
	    remove (user_[i]);
	}
	num_ = 0;
	
	validate ();
    }
		
    public void init () 
    {
	// create a border layout for applet
	setLayout(new BorderLayout ());
	
	// create top level scroll pane
	sclp_ = new ScrollPane (ScrollPane.SCROLLBARS_ALWAYS);
	add (sclp_);
	sclp_.setSize (400, 100);

	// create layout manager
	layout_ = new GridBagLayout();
	c_ = new GridBagConstraints();
	c_.fill = GridBagConstraints.BOTH;

	// create top level panel
	dpanel_ = new Panel (layout_);
	dpanel_.setSize (700, 100);

	// add this panel to scroll pane
	sclp_.add (dpanel_);

	// create array of text fields
	name_ = new TextField[size_];
	domain_ = new TextField[size_];
	status_ = new TextField[size_];	
	host_ = new TextField[size_];
	port_ = new TextField[size_];
	user_ = new TextField[size_];
	
	num_ = 0;

	// create top label
	createLabel ("CDEV Name Server Information");

	// create information label
	createInfoLabel ();

	// create category labels
	createFieldLabels ();

	// create network handler to rsvcServer
	client_ = new rsvcClient();

	if (serverHost_ == null) {
	  // get parameters for server host and server port
	  serverHost_ = getParameter ("host");
	  serverPort_ = Integer.valueOf (getParameter ("port")).intValue();
	}
    }


    public void start ()
    {
	// start timer thread
	startTimerThread ();

	setInformation ("Connecting to server on " + serverHost_ + " at port " + String.valueOf (serverPort_));
	try {
	    client_.connect (serverHost_, serverPort_);
	}catch (UnknownHostException ue) {
	    setInformation ("Unknown Host " + serverHost_);
	}catch (IOException e) {
	    setInformation ("Cannot connect to the server");
	}

	// if connected 
	if (client_.connected() == true) {
	    setInformation ("Connection to the server is established");

	    // get all 
	    rsvcEvent oevent = null;
	    try {
		oevent = client_.query ("cdevServers", "all", this);
	    }catch (IOException e) {
		setInformation ("Cannot send out query information to the server");
	    }

	    // monitor on new entries
	    rsvcData noused = new rsvcData();
	    try {
		oevent = client_. monitorIncomingEntries ("cdevServers",
							  noused, this);
	    } catch (IOException e) {
		setInformation ("Cannot send out monitor request to the server"); 
	    }

	    // add disconnection handler
	    client_.addDisconnectHandler (this);
	    
	}

    }

    public void stop ()
    {
	if (client_.connected () == true) {
	    try {
		client_.disconnect ();
	    }catch (IOException e) {
		;
	    }
	}
	timerThread_.suspend ();
    }

    
    public void handleEvent (rsvcEvent event)
    {
	int status = event.getStatus ();
	int opcode = event.getOpcode ();
	rsvcData data = event.getData ();

	if (status == rsvcConfig.RSVC_DISCONNECTED) {
	    setInformation ("Server is Gone");
	    cleanupEntries ();
	}
	else {
	    if (opcode == rsvcConfig.RSVC_QUERY) {
		if (status == rsvcConfig.RSVC_INCOMPLETE || 
		    status == rsvcConfig.RSVC_SUCCESS) 
		    addEntry (data);
	    }
	    else if (opcode == rsvcConfig.RSVC_MONITOR_ON) {
		if (status == rsvcConfig.RSVC_SUCCESS)
		    updateEntry (data, false);
	    }
	    else if (opcode == rsvcConfig.RSVC_MONITOR_ENTRIES) {
		if (status == rsvcConfig.RSVC_SUCCESS && data.isEmpty() != true)
		    updateEntry (data, true);
	    }
	}
    }

    public void run ()
    {
	while (true) {
	    // check to see whether there is something in the
	    // information display area. If there is, clean out
	    String infotext = info_.getText ();
	    if (infotext != null)
		info_.setText (null);
	    // sleep 3 seconds
	    try {
		Thread.sleep (3000);
	    } catch (InterruptedException e) {
		;
	    }
	}
    }

    public static void main(String args[]) {
      if (args.length < 2) {
	System.err.println ("Usage: rsvcDisplay host port");
	System.exit (-1);
      }
      Frame f = new Frame("CDEV Name Server Information");
      rsvcDisplay display = new rsvcDisplay();
      display.setServerHost (args[0]);
      display.setServerPort (Integer.valueOf (args[1]).intValue());
      display.init();
      display.start ();
      
      f.add("Center", display);
      f.pack();
      f.setSize(f.getPreferredSize());
      f.show();
    }
}    
