/*
 * Copyright 2000-2001 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.print;

import java.util.Vector;

import javax.print.PrintService;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.HashPrintServiceAttributeSet;
import javax.print.event.PrintServiceAttributeEvent;
import javax.print.event.PrintServiceAttributeListener;

/*
 * A utility class usable by all print services for managing listeners
 * The services create an instance and delegate the listener callback
 * management to this class. The ServiceNotifier calls back to the service
 * to obtain the state of the attributes and notifies the listeners of
 * any changes.
 */
class ServiceNotifier extends Thread {

    private PrintService service;
    private Vector listeners;
    private boolean stop = false;
    private PrintServiceAttributeSet lastSet;

    ServiceNotifier(PrintService service) {
        super(service.getName() + " notifier");
        this.service = service;
        listeners = new Vector();
        try {
              setPriority(Thread.NORM_PRIORITY-1);
              setDaemon(true);
              start();
        } catch (SecurityException e) {
        }
    }

    void addListener(PrintServiceAttributeListener listener) {
        synchronized (this) {
            if (listener == null || listeners == null) {
                return;
            }
            listeners.add(listener);
        }
    }

    void removeListener(PrintServiceAttributeListener listener) {
         synchronized (this) {
            if (listener == null || listeners == null) {
                return;
            }
            listeners.remove(listener);
        }
    }

   boolean isEmpty() {
     return (listeners == null || listeners.isEmpty());
   }

   void stopNotifier() {
      stop = true;
   }

    /* If a service submits a job it may call this method which may prompt
     * immediate notification of listeners.
     */
    void wake() {
        try {
            interrupt();
        } catch (SecurityException e) {
        }
    }

   /* A heuristic is used to calculate sleep time.
     * 10 times the time taken to loop through all the listeners, with
     * a minimum of 15 seconds. Ensures this won't take more than 10%
     * of available time.
     */
    public void run() {

       long minSleepTime = 15000;
       long sleepTime = 2000;
       HashPrintServiceAttributeSet attrs;
       PrintServiceAttributeEvent attrEvent;
       PrintServiceAttributeListener listener;
       PrintServiceAttributeSet psa;

       while (!stop) {
           try {
                Thread.sleep(sleepTime);
           } catch (InterruptedException e) {
           }
           synchronized (this) {
               if (listeners == null) {
                   continue;
               }
               long startTime = System.currentTimeMillis();
               if (listeners != null) {
                    if (service instanceof AttributeUpdater) {
                       psa =
                          ((AttributeUpdater)service).getUpdatedAttributes();
                    } else {
                       psa = service.getAttributes();
                    }
                    if (psa != null && !psa.isEmpty()) {
                        for (int i = 0; i < listeners.size() ; i++) {
                            listener = (PrintServiceAttributeListener)
                                listeners.elementAt(i);
                            attrs =
                                new HashPrintServiceAttributeSet(psa);
                            attrEvent =
                                new PrintServiceAttributeEvent(service, attrs);
                            listener.attributeUpdate(attrEvent);
                        }
                    }
               }
               sleepTime = (System.currentTimeMillis()-startTime)*10;
               if (sleepTime < minSleepTime) {
                   sleepTime = minSleepTime;
               }
           }
       }
    }

}
