/*
 * COPYRIGHT (c) 1998-1999 Jan-Henrik Haukeland, http://www.tildeslash.com/
 */



package ts.biff;

import java.net.*;
import java.io.*;

import javax.swing.event.*;

import ts.config.*;
import ts.event.*;


/**
 * This class binds a server socket to a given port, if anything
 * tries to connect to that port it will fire a WakeUp event to 
 * notify any listeners.
 *
 * @author  Jan-Henrik Haukeland &lt;hauk@tildeslash.com&gt;
 * @version $Id: WakeUpServer.java,v 1.10 1999/11/26 21:58:15 hauk Exp $ 
 */
public final class WakeUpServer extends Thread
{

  /** A list holding WakeUpListeners */
  protected EventListenerList listenerList= new EventListenerList();

  /** me, myself and I */
  private static WakeUpServer self;


  /**
   * Instantiate the class and start the thread
   */
  private WakeUpServer() {
    super("Wakeup");
    this.setPriority(Thread.MIN_PRIORITY);
    start();
  }


  /**
   * Returns a WakeUpServer singelton
   * @return A WakeUpServer singelton object
   */
  public static WakeUpServer getInstance() {
    if ( self == null )
	self= new WakeUpServer();
    return self;
  }



  /**
   * Listens for connections on a WakeUp port. When anything tries
   * to connect to the port, fire a WakeUpEvent to notify any listeners.
   * There's only a super simple protocol in use, since we're only 
   * interested in the connection. 
   */
  public void run() {

    String        error= "Error: Could not find a suitable wakeup "+
                         "port. No wakeup available!";

    PrintWriter  writer= null;
    ServerSocket server= null;
    Socket client=       null;
    
    try {

      server= new ServerSocket(getWakeUpPort());

      for(;;) {
	client= server.accept();
	
	writer= new PrintWriter(client.getOutputStream(), true);
	
	writer.println(Constant.WAKEUP_HELLO);
	
	fireWakeUpEvent(new WakeUpEvent(this));
	
	writer.close();
	client.close();
      }
    }	catch (IOException e) {
      Util.showError(error);
      return;
    }
    finally {
      try {
	writer.close();
	client.close();
	server.close();
      }catch (IOException iio) {}
    }
  }

  

  /**
   * Return a server portnumber for a WakeUp server object.
   * @return an available portnumber. 
   */
  private int getWakeUpPort() {
    return Config.getint("wakeup.server.port");
  }




  // ------------------- handle WakeUp events -------------------- //
 
  
  /**
   * Adds a WakeUpListener. 
   *
   * @param listener A WakeUp listener object
   */
  public void addWakeUpListener(WakeUpListener listener) 
  {
    listenerList.add(WakeUpListener.class, listener);
  }
  

  /**
   * Removes a WakeUpListener
   *
   * @param listener A WakeUP listener object
   */
  public void removeWakeUpListener(WakeUpListener listener) 
  {
    listenerList.remove(WakeUpListener.class, listener);
  }


  /*
   * Notify all listeners that have registered interest for
   * notification on this event type.  The event instance 
   * is lazily created using the parameters passed into 
   * the fire method.
   * @param w A WakeUp event
   * @see EventListenerList
   */
  private void fireWakeUpEvent(WakeUpEvent w)
  {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
      if (listeners[i]==WakeUpListener.class) {
        ((WakeUpListener)listeners[i+1]).wakeUp(w);
      }          
    }
  }    



}
    


