import java.util.*;

/**
 * A PointSubject that generates a sequence of Point objects
 * in the shape of the Way icon
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class WayIconSubject implements Runnable, PointSubject
{
    private Hashtable            observers;
    private Thread               controlThread;
    private Vector               points;
    
    /**
     * Default Constructor
     */
    public WayIconSubject()
    {
       controlThread = new Thread(this);
    
       observers = new Hashtable();
       

       // Define the points
       points = new Vector();
       for (double x=70; x<=140; x++) addPoint(x, 140);
       for (double y=140;y<=170; y++) addPoint(140, y);
       for (double d=0; d<=80; d++)   addPoint(140+d, 170-d);
       for (double d=0; d<=80; d++)   addPoint(220-d, 90-d);
       for (double y=10;y<=40; y++)   addPoint(140, y);
       for (double x=140; x>=50; x--) addPoint(x, 40);
       for (double d=0; d<=100; d++)  addPoint(50+d/5,40+d);
    }



    /**
     * A utility method for adding a Point to the
     * (pre-defined) collection of Point "events"
     *
     * @param x   The horizontal coordinate
     * @param y   The vertical coordinate
     */ 
    private void addPoint(double x, double y)
    {
       double[]      v;

       v = new double[2];

       v[0] = x;
       v[1] = y;
       points.add(new Point(v));

    }



    /**
     * Add a PointObserver to the list of existing observers
     * (required by PointSubject)
     *
     * @param observer  The PointObserver to add
     */
    public void addPointObserver(PointObserver observer)
    {
       observers.put(observer, observer);
    }
    


    /**
     * Notify all observers of a Point "event"
     * (required by PointSubject)
     *
     * @param p    The Point to notify the observers about
     */
    public void notifyPointObservers(Point p)
    {
       Enumeration       e;
       PointObserver     observer;
       
       
       e = observers.elements();
       while (e.hasMoreElements())
       {
          observer = (PointObserver)e.nextElement();
          observer.handlePoint(this, p);
       }
    }
    
    

    /**
     * Remove a PointObserver from the list of existing observers
     * (required by PointSubject)
     *
     * @param observer  The PointObserver to remove
     */
    public void removePointObserver(PointObserver observer)
    {
       observers.remove(observer);
    }
    


    
    /**
     * The code to execute (required by Runnable)
     *
     * Specifically, inform all observers of the sequence of
     * Point "events"
     */
    public void run()
    {
       Enumeration      e;
       Point            p;
       
       
       e = points.elements();
       while (e.hasMoreElements())
       {
          p = (Point)e.nextElement();
          notifyPointObservers(p);
          
          try
          {
             controlThread.sleep(10);
          }
          catch (InterruptedException ie)
          {
             // Ignore
          }
       }
    }
       

    /**
     * Start the new thread of execution
     */
    public void start()
    {
       controlThread.start();
    }
    

    
}
