/*
 * Copyright (c) 1995, 2003, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.awt.image;

import java.util.Vector;
import sun.awt.AppContext;

/**
  * An ImageFetcher is a thread used to fetch ImageFetchable objects.
  * Once an ImageFetchable object has been fetched, the ImageFetcher
  * thread may also be used to animate it if necessary, via the
  * startingAnimation() / stoppingAnimation() methods.
  *
  * There can be up to FetcherInfo.MAX_NUM_FETCHERS_PER_APPCONTEXT
  * ImageFetcher threads for each AppContext.  A per-AppContext queue
  * of ImageFetchables is used to track objects to fetch.
  *
  * @author Jim Graham
  * @author Fred Ecks
  */
class ImageFetcher extends Thread {
    static final int HIGH_PRIORITY = 8;
    static final int LOW_PRIORITY = 3;
    static final int ANIM_PRIORITY = 2;

    static final int TIMEOUT = 5000; // Time in milliseconds to wait for an
                                     // ImageFetchable to be added to the
                                     // queue before an ImageFetcher dies

    /**
      * Constructor for ImageFetcher -- only called by add() below.
      */
    private ImageFetcher(ThreadGroup threadGroup, int index) {
        super(threadGroup, "Image Fetcher " + index);
        setDaemon(true);
    }

    /**
      * Adds an ImageFetchable to the queue of items to fetch.  Instantiates
      * a new ImageFetcher if it's reasonable to do so.
      */
    public static void add(ImageFetchable src) {
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
        synchronized(info.waitList) {
            if (!info.waitList.contains(src)) {
                info.waitList.addElement(src);
                if (info.numWaiting == 0 &&
                            info.numFetchers < info.fetchers.length) {
                    createFetchers(info);
                }
                info.waitList.notify();
            }
        }
    }

    /**
      * Removes an ImageFetchable from the queue of items to fetch.
      */
    public static void remove(ImageFetchable src) {
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
        synchronized(info.waitList) {
            if (info.waitList.contains(src)) {
                info.waitList.removeElement(src);
            }
        }
    }

    /**
      * Checks to see if the given thread is one of the ImageFetchers.
      */
    public static boolean isFetcher(Thread t) {
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
        synchronized(info.waitList) {
            for (int i = 0; i < info.fetchers.length; i++) {
                if (info.fetchers[i] == t) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
      * Checks to see if the current thread is one of the ImageFetchers.
      */
    public static boolean amFetcher() {
        return isFetcher(Thread.currentThread());
    }

    /**
      * Returns the next ImageFetchable to be processed.  If TIMEOUT
      * elapses in the mean time, or if the ImageFetcher is interrupted,
      * null is returned.
      */
    private static ImageFetchable nextImage() {
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
        synchronized(info.waitList) {
            ImageFetchable src = null;
            long end = System.currentTimeMillis() + TIMEOUT;
            while (src == null) {
                while (info.waitList.size() == 0) {
                    long now = System.currentTimeMillis();
                    if (now >= end) {
                        return null;
                    }
                    try {
                        info.numWaiting++;
                        info.waitList.wait(end - now);
                    } catch (InterruptedException e) {
                        // A normal occurrence as an AppContext is disposed
                        return null;
                    } finally {
                        info.numWaiting--;
                    }
                }
                src = (ImageFetchable) info.waitList.elementAt(0);
                info.waitList.removeElement(src);
            }
            return src;
        }
    }

    /**
      * The main run() method of an ImageFetcher Thread.  Calls fetchloop()
      * to do the work, then removes itself from the array of ImageFetchers.
      */
    public void run() {
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
        try {
            fetchloop();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            synchronized(info.waitList) {
                Thread me = Thread.currentThread();
                for (int i = 0; i < info.fetchers.length; i++) {
                    if (info.fetchers[i] == me) {
                        info.fetchers[i] = null;
                        info.numFetchers--;
                    }
                }
            }
        }
    }

    /**
      * The main ImageFetcher loop.  Repeatedly calls nextImage(), and
      * fetches the returned ImageFetchable objects until nextImage()
      * returns null.
      */
    private void fetchloop() {
        Thread me = Thread.currentThread();
        while (isFetcher(me)) {
            // we're ignoring the return value and just clearing
            // the interrupted flag, instead of bailing out if
            // the fetcher was interrupted, as we used to,
            // because there may be other images waiting
            // to be fetched (see 4789067)
            me.interrupted();
            me.setPriority(HIGH_PRIORITY);
            ImageFetchable src = nextImage();
            if (src == null) {
                return;
            }
            try {
                src.doFetch();
            } catch (Exception e) {
                System.err.println("Uncaught error fetching image:");
                e.printStackTrace();
            }
            stoppingAnimation(me);
        }
    }


    /**
      * Recycles this ImageFetcher thread as an image animator thread.
      * Removes this ImageFetcher from the array of ImageFetchers, and
      * resets the thread name to "ImageAnimator".
      */
    static void startingAnimation() {
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
        Thread me = Thread.currentThread();
        synchronized(info.waitList) {
            for (int i = 0; i < info.fetchers.length; i++) {
                if (info.fetchers[i] == me) {
                    info.fetchers[i] = null;
                    info.numFetchers--;
                    me.setName("Image Animator " + i);
                    if(info.waitList.size() > info.numWaiting) {
                       createFetchers(info);
                    }
                    return;
                }
            }
        }
        me.setPriority(ANIM_PRIORITY);
        me.setName("Image Animator");
    }

    /**
      * Returns this image animator thread back to service as an ImageFetcher
      * if possible.  Puts it back into the array of ImageFetchers and sets
      * the thread name back to "Image Fetcher".  If there are already the
      * maximum number of ImageFetchers, this method simply returns, and
      * fetchloop() will drop out when it sees that this thread isn't one of
      * the ImageFetchers, and this thread will die.
      */
    private static void stoppingAnimation(Thread me) {
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
        synchronized(info.waitList) {
            int index = -1;
            for (int i = 0; i < info.fetchers.length; i++) {
                if (info.fetchers[i] == me) {
                    return;
                }
                if (info.fetchers[i] == null) {
                    index = i;
                }
            }
            if (index >= 0) {
                info.fetchers[index] = me;
                info.numFetchers++;
                me.setName("Image Fetcher " + index);
                return;
            }
        }
    }

    /**
      * Create and start ImageFetcher threads in the appropriate ThreadGroup.
      */
    private static void createFetchers(final FetcherInfo info) {
       // We need to instantiate a new ImageFetcher thread.
       // First, figure out which ThreadGroup we'll put the
       // new ImageFetcher into
       final AppContext appContext = AppContext.getAppContext();
       ThreadGroup threadGroup = appContext.getThreadGroup();
       ThreadGroup fetcherThreadGroup;
       try {
          if (threadGroup.getParent() != null) {
             // threadGroup is not the root, so we proceed
             fetcherThreadGroup = threadGroup;
          } else {
             // threadGroup is the root ("system") ThreadGroup.
             // We instead want to use its child: the "main"
             // ThreadGroup.  Thus, we start with the current
             // ThreadGroup, and go up the tree until
             // threadGroup.getParent().getParent() == null.
             threadGroup = Thread.currentThread().getThreadGroup();
             ThreadGroup parent = threadGroup.getParent();
             while ((parent != null)
                  && (parent.getParent() != null)) {
                  threadGroup = parent;
                  parent = threadGroup.getParent();
             }
             fetcherThreadGroup = threadGroup;
         }
       } catch (SecurityException e) {
         // Not allowed access to parent ThreadGroup -- just use
         // the AppContext's ThreadGroup
         fetcherThreadGroup = appContext.getThreadGroup();
       }
       final ThreadGroup fetcherGroup = fetcherThreadGroup;

       java.security.AccessController.doPrivileged(
         new java.security.PrivilegedAction() {
         public Object run() {
             for (int i = 0; i < info.fetchers.length; i++) {
               if (info.fetchers[i] == null) {
                   info.fetchers[i] = new ImageFetcher(
                           fetcherGroup, i);
                   info.fetchers[i].start();
                   info.numFetchers++;
                   break;
               }
             }
          return null;
        }
       });
      return;
    }

}

/**
  * The FetcherInfo class encapsulates the per-AppContext ImageFetcher
  * information.  This includes the array of ImageFetchers, as well as
  * the queue of ImageFetchable objects.
  */
class FetcherInfo {
    static final int MAX_NUM_FETCHERS_PER_APPCONTEXT = 4;

    Thread[] fetchers;
    int numFetchers;
    int numWaiting;
    Vector waitList;

    private FetcherInfo() {
        fetchers = new Thread[MAX_NUM_FETCHERS_PER_APPCONTEXT];
        numFetchers = 0;
        numWaiting = 0;
        waitList = new Vector();
    }

    /* The key to put()/get() the FetcherInfo into/from the AppContext. */
    private static final Object FETCHER_INFO_KEY =
                                        new StringBuffer("FetcherInfo");

    static FetcherInfo getFetcherInfo() {
        AppContext appContext = AppContext.getAppContext();
        synchronized(appContext) {
            FetcherInfo info = (FetcherInfo)appContext.get(FETCHER_INFO_KEY);
            if (info == null) {
                info = new FetcherInfo();
                appContext.put(FETCHER_INFO_KEY, info);
            }
            return info;
        }
    }
}
