package com.wiley.compbooks.brose.chapter9.appletServer;

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.CosNaming.*;
import com.wiley.compbooks.brose.chapter9.appletServer.Talk.*;


class ListenerImpl 
    extends ListenerPOA 
{
    private AppletServer talkApplet;

    /** constructor */

    ListenerImpl( AppletServer applet ) {
        talkApplet = applet;
    }

    /** operation */
    public void message( String msg ) 
    {
	talkApplet.display( msg );
        return;
    }
}



public class AppletServer
    extends java.applet.Applet
    implements ActionListener 
{
    private ORB orb;
    private NamingContextExt naming;

    private Listener remoteListener;
    private ListenerImpl myListener;

    private Panel namePanel;
    private Panel buttonPanel;
    private Panel textPanel;
    private Panel talkersPanel;

    private Button registerButton;
    private Button connectButton;
    private Button sendButton;
    private Button updateButton;
    private Button clearButton;

    private Label nameLabel;
    private Label talkersLabel;
    private Label partnerLabel;

    private TextField nameField;
    private TextField talkersField;
    private TextField partnerField;

    private TextArea inArea;
    private TextArea outArea;

    private String myName;

    /** 
     * Applet initialization 
     */

    public void init() {

        registerButton = new Button("register");
        registerButton.setFont(new Font("Helvetica", Font.BOLD, 20));
        registerButton.setActionCommand("register");
        registerButton.addActionListener( (ActionListener) this );

        connectButton = new Button("connect");
        connectButton.setFont(new Font("Helvetica", Font.BOLD, 20));
        connectButton.setActionCommand("connect");
        connectButton.addActionListener( (ActionListener) this );

        sendButton = new Button("send");
        sendButton.setFont(new Font("Helvetica", Font.BOLD, 20));
        sendButton.setActionCommand("send");
        sendButton.addActionListener( (ActionListener) this );

        updateButton = new Button("update");
        updateButton.setFont(new Font("Helvetica", Font.BOLD, 20));
	updateButton.setActionCommand("update");
        updateButton.addActionListener( (ActionListener) this );

        clearButton = new Button("clear");
        clearButton.setFont(new Font("Helvetica", Font.BOLD, 20));
	clearButton.setActionCommand("clear");
        clearButton.addActionListener( (ActionListener) this );

        nameLabel = new Label("Enter name: ");
        nameLabel.setFont(new Font("Helvetica", Font.BOLD, 14));
	nameField = new TextField();
        nameField.setFont(new Font("Helvetica", Font.BOLD, 14));

	talkersField = new TextField();
        talkersField.setFont(new Font("Helvetica", Font.BOLD, 14));
        talkersLabel = new Label("Currently registered: ");
        talkersLabel.setFont(new Font("Helvetica", Font.BOLD, 14));

	partnerField = new TextField();
        partnerField.setFont(new Font("Helvetica", Font.BOLD, 14));
        partnerLabel = new Label("Talk to: ");
        partnerLabel.setFont(new Font("Helvetica", Font.BOLD, 14));


	namePanel = new Panel();
        textPanel = new Panel();

	namePanel.setLayout( new GridLayout(3,3));
        namePanel.add( nameLabel );
        namePanel.add( nameField );
        namePanel.add( registerButton );

        namePanel.add( talkersLabel );
        namePanel.add( talkersField );
	namePanel.add( updateButton );

        namePanel.add( partnerLabel );
        namePanel.add( partnerField );
	namePanel.add( connectButton );

	Panel inPanel = new Panel();
	inPanel.setLayout(new BorderLayout());

	Label inLabel = new Label("Write here:");
	inLabel.setFont(new Font("Helvetica", Font.BOLD, 14));

        inArea = new TextArea("", 40, 5 );
        inArea.setFont(new Font("Helvetica", Font.BOLD, 14));

	Panel buttonPanel = new Panel();
	buttonPanel.setLayout( new FlowLayout());
	buttonPanel.add( sendButton );
	buttonPanel.add( clearButton );

	inPanel.add("North", inLabel );
	inPanel.add("Center", inArea );
	inPanel.add("South", buttonPanel );

	Panel outPanel = new Panel();
	outPanel.setLayout(new BorderLayout());

	Label outLabel = new Label("Read here:");
	outLabel.setFont(new Font("Helvetica", Font.BOLD, 14));

        outArea = new TextArea("", 40, 5 );
	outArea.setEditable(false);
        outArea.setFont(new Font("Helvetica", Font.BOLD, 14));

	outPanel.add("North", outLabel );
	outPanel.add("Center", outArea );

	textPanel.setLayout( new GridLayout(2,1));
        textPanel.add( inPanel );
        textPanel.add( outPanel );

	setLayout( new BorderLayout());
        add( "North", namePanel );
        add( "Center", textPanel );

        try {
            java.util.Properties props = new java.util.Properties();
            props.put("org.omg.CORBA.ORBClass","jacorb.orb.ORB");
            props.put("org.omg.CORBA.ORBSingletonClass","jacorb.orb.ORBSingleton");

            //init ORB
            orb = ORB.init( this, props );
	    POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA") );
            // create a Listener object
            myListener = new ListenerImpl( this );
            
            naming = NamingContextExtHelper.narrow( orb.resolve_initial_references("NameService"));
            
	    // activate the object
            poa.activate_object( myListener );
	    poa.the_POAManager().activate();
        }
        catch(UserException u) {
	    u.printStackTrace();
	}
	catch(SystemException e) {
	    e.printStackTrace();
        }
    }

    public synchronized void register() {
        
        try {
            myName = nameField.getText();
            naming.bind( naming.to_name(myName + ".talker" ), myListener._this() );
	    registerButton.setLabel("deregister");
	    registerButton.setActionCommand("deregister");
        }
        catch(UserException ue) {
            outArea.append( "register " + myName + " failed: " + ue );
        }
        catch(SystemException se) {
            outArea.append( "Exception: " + se );
        }
    }

    public synchronized void deregister() {
        try {
	    if( myName != null )
	    {
		naming.unbind( naming.to_name( myName + ".talker" ));
	    }

	    registerButton.setLabel("register");
	    registerButton.setActionCommand("register");
	    myName = null;
	    nameField.setText("");
        }
        catch(UserException ue) {
                System.err.println(ue);
        }
        catch(SystemException se) {
                System.err.println(se);
        }
    }

    public void updateTalkers()
    {
	StringBuffer sb = new StringBuffer();
	Vector talkersList = new Vector();

	list( naming, talkersList );
	for( int i = 0; i < talkersList.size(); i++ )
	{
	    String talker = (String)talkersList.elementAt(i);
	    sb.append( talker + " ");
	}

	talkersField.setText( sb.toString());
    }


    private void list( NamingContextExt n, Vector v )
    {
	try {
	    BindingListHolder blsoh = 
		new BindingListHolder(new Binding[0]);
	    BindingIteratorHolder bioh = 
		new BindingIteratorHolder();

	    n.list( 0, blsoh, bioh );

	    BindingHolder bh = new BindingHolder();

	    if( bioh.value == null )
		return; 

	    while( bioh.value.next_one( bh )) 
	    {
		String stringName = n.to_string( bh.value.binding_name);
		if( stringName.endsWith(".talker"))
		    v.addElement( stringName.substring(0,stringName.indexOf(".talker")) );

		if( bh.value.binding_type.value() == BindingType._ncontext ) {
		    
		    NameComponent [] name = n.to_name(stringName);
		    NamingContextExt sub_context = 
			NamingContextExtHelper.narrow(n.resolve(name));
		    list(sub_context,v);
		}
		else
		    System.out.println();
	    }
	} 
	catch (Exception e) 
	{
	    e.printStackTrace();
	}
    }


    public void disconnect()
    {
	// send last message
	remoteListener.message( myName + " is disconnecting...\n");
	remoteListener._release();
	remoteListener = null;
	partnerField.setText("");
	connectButton.setLabel("connect");
	connectButton.setActionCommand("connect");
    }
	

    public void connect() 
    {
        // invoke the operation
        try {
	    String name = partnerField.getText();
	    if( name != null && name.length() > 0 )
	    {

		//resolve name and narrow it to Listener
		remoteListener = ListenerHelper.narrow( 
	       			       naming.resolve( naming.to_name( name + ".talker" ) ));

		// send initial message
		remoteListener.message( "Connected to " + myName + "\n" );
		connectButton.setLabel("disconnect");
		connectButton.setActionCommand("disconnect");
	    }
        }
        // catch exceptions
        catch(UserException ue) {
	    outArea.append( "resolve failed: " + ue );
        }
        catch(SystemException se) {
	    outArea.append( "Exception: " + se );
        }
    }




    public void display( String msg ) {

	outArea.append( msg );
    }


    public void clear()
    {
	outArea.setText(null);
	inArea.setText(null);
    }



    public void actionPerformed(ActionEvent ev) {

        // catch and process events
        if(ev.getActionCommand().equals("connect") ) {

            // resolve to name and connect
            connect();
        }

        if(ev.getActionCommand().equals("disconnect") ) {
	    // release the remote Listener
            disconnect();
        }

        if(ev.getActionCommand().equals("register") ) {
            // register yourself
            register();
        }

        if(ev.getActionCommand().equals("update") ) 
	{
            updateTalkers();
        }

        if(ev.getActionCommand().equals("clear") ) 
	{
            clear();
        }

        if(ev.getActionCommand().equals("deregister") ) {

            // deregister
            deregister();
        }

        if(ev.getActionCommand().equals("send") ) {

            // invoke the operation
            try {
				String msg = inArea.getText();
				if( msg != null )
					remoteListener.message( msg );
            }
            // catch exceptions
            catch(SystemException ex) {
	        outArea.append( "Exception: " + ex );
            }
        }
    }
}
