package com.WorldOfBeverage.examples.VoyagerChat;

import java.awt.TextField;
import java.awt.Button;
import java.awt.Label;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Vector;
import java.util.Enumeration;

import com.objectspace.voyager.VObject;
import com.objectspace.voyager.VoyagerException;

/**
  * A widget that allows the user to enter a Voyager VObject address and attempt to
  * connect with it. Emits ConnectionEvents when successful; erases the text field
  * if unsuccessful.
  * @author Paul Reavis
  */
public class Connector extends Container {

	//******** private state
	private TextField addressField;
	private Button connectButt;
	private Vector listeners;

	//******** properties
	private VObject connectedTo;

	//******** constructors
	public Connector() {

		addressField = new TextField();
		connectButt = new Button("connect");

		setLayout(new BorderLayout());
		add(new Label("address: "), "West");
		add(addressField, "Center");
		add(connectButt, "East");

		ActionListener buttonEar = new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				connect();
				}
			};
		connectButt.addActionListener(buttonEar);
		}

	//******** primary methods
	/**
	 * If we're connected, disconnects. If not, tries to connect to the VObject
	 * specified in the address field.
	 */
	public void connect() {
		if (connectedTo != null)
			setConnectedTo(null);
		else {
			try {
				setConnectedTo(VObject.forObjectAt(getAddress()));
				}
			catch (VoyagerException oopsie) {
				setConnectedTo(null);
				connectButt.setLabel("try again");
				}
			}
      
		}
  

	//******** accessors
	public String getAddress() {
		return addressField.getText();
		}

	public void setAddress(String newAddress) {
		addressField.setText(newAddress);
		}

	public VObject getConnectedTo() {
		return connectedTo;
		}

	public void setConnectedTo(VObject newVob) {
		// announce disconnect
		if (connectedTo != null)
			dispatchConnectionEvent(new ConnectionEvent(this, false, connectedTo));

		connectedTo = newVob;

		// announce connect; set button label appropriately
		if (connectedTo != null) {
			dispatchConnectionEvent(new ConnectionEvent(this, true, connectedTo));
			connectButt.setLabel("disconnect");
			}
		else {
			connectButt.setLabel("connect");
			}      

		}

	//******** event registrars
	public synchronized void addConnectionListener(ConnectionListener listener) {
		if (listeners == null) listeners = new Vector();
		listeners.addElement(listener);
		}

	public synchronized void removeConnectionListener(ConnectionListener listener) {
		if (listeners == null) return;
		listeners.removeElement(listener);
		}

	//******** private methods
	private void dispatchConnectionEvent(ConnectionEvent event) {
		if (listeners == null) return;
		Vector temp;
		synchronized(this) {temp = (Vector)listeners.clone();}
		Enumeration e = temp.elements();
		while (e.hasMoreElements()) {
			ConnectionListener ear = (ConnectionListener)e.nextElement();
			ear.handleConnection(event);
			}
		}

	}

