/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2003-2006 RSSOwl Development Team                                  **
 **   http://www.rssowl.org/                                                 **
 **                                                                          **
 **   All rights reserved                                                    **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the Eclipse Public License 1.0 which accompanies this     **
 **   distribution, and is available at:                                     **
 **   http://www.rssowl.org/legal/epl-v10.html                               **
 **                                                                          **
 **   A copy is found in the file epl-v10.html and important notices to the  **
 **   license from the team is found in the textfile LICENSE.txt distributed **
 **   in this package.                                                       **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Contributors:                                                          **
 **     RSSOwl - initial API and implementation (bpasero@rssowl.org)         **
 **                                                                          **
 **  **********************************************************************  */

package net.sourceforge.rssowl.controller.thread;

import net.sourceforge.rssowl.controller.GUI;
import net.sourceforge.rssowl.model.Favorite;

import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.TreeSet;

/**
 * The RSSAutoUpdater checks a Hashtable every 5 seconds and reloads each
 * Favorite which update date is before the current date. After reload the
 * AutoUpdater will remove the update date from the Hashtable and put a new one
 * in it, which is calculated with the update interval value of the Favorite.
 * 
 * @author <a href="mailto:bpasero@rssowl.org">Benjamin Pasero </a>
 * @version 1.2.3
 */
public class FeedAutoUpdater extends Thread {

  /** Array containing the possible auto-update values */
  public static int[] updateInterval = new int[] { 0, 1, 5, 15, 30, 60, 180, 360, 720, 1440 };

  /** Array containing the i18n values for the update intervals */
  public static String[] updateIntervalNames = new String[] { "UPDATE_INTERVAL_NO", "UPDATE_INTERVAL_ONE", "UPDATE_INTERVAL_FIVE", "UPDATE_INTERVAL_FIFTEEN", "UPDATE_INTERVAL_THIRTY", "UPDATE_INTERVAL_ONEHOUR", "UPDATE_INTERVAL_THREEHOURS", "UPDATE_INTERVAL_SIXHOURS", "UPDATE_INTERVAL_TWELVEHOURS", "UPDATE_INTERVAL_ONEDAY" };

  /** The treeset holding each favorite that has a update interval */
  private static TreeSet dateList = new TreeSet();

  /** The hashtable holding each favorite that has a update interval */
  private static Hashtable feedList = new Hashtable();

  /** This long is used to create unique dates */
  private static long uniqueCounter;

  /** Interval to look for favorites that need an update */
  private static final int UPDATE_INTERVAL = 5 * 1000;

  /** Favorite to update */
  Favorite currentRSSOwlFavorite;

  /** The RSSOwl Maincontroller */
  GUI rssOwlGui;

  /**
   * Instantiates a new FeedAutoUpdater
   * 
   * @param rssOwlGui The RSSOwl Maincontroller
   */
  public FeedAutoUpdater(GUI rssOwlGui) {
    this.rssOwlGui = rssOwlGui;
    uniqueCounter = 0;
    setDaemon(true);
    setName("Feed Update Thread");
  }

  /**
   * This method removes a Favorite from the feedList. This method is
   * synchronized, because it alters a Hashtable which might be iterated in the
   * RSSAutoUpdater thread at the same time.
   * 
   * @param rssOwlFavorite Favorite to remove
   */
  public static synchronized void removeFavorite(Favorite rssOwlFavorite) {
    Enumeration keys = feedList.keys();
    while (keys.hasMoreElements()) {
      Object key = keys.nextElement();

      /** If the URL matches the url of the favorite, remove it */
      if (rssOwlFavorite.getUrl().equals(((Favorite) feedList.get(key)).getUrl())) {
        feedList.remove(key);
        dateList.remove(key);
        return;
      }
    }
  }

  /**
   * Update the feedList. This method replaces the favorite from the feedList if
   * the updateinterval is bigger than 0. Otherwise the favorite just gets
   * removed from the list. This method is synchronized, because it alters a
   * Hashtable which might be iterated in the RSSAutoUpdater thread at the same
   * time.
   * 
   * @param rssOwlFavorite Favorite to update
   */
  public static synchronized void updateFeedList(Favorite rssOwlFavorite) {

    /** Remove favorite from the update list */
    removeFavorite(rssOwlFavorite);

    /** Add favorite to the update list with new update date */
    if (rssOwlFavorite.getUpdateInterval() > 0) {

      /**
       * Having a list of favorites with the same update interval using
       * System.currentTimeMillis() will not create a unique nextUpdate time on
       * fast PCs. Therefor increment the uniqueCounter and add it to the next
       * update time.
       */
      uniqueCounter++;
      long nextUpdate = rssOwlFavorite.getUpdateInterval() * 1000 * 60 + System.currentTimeMillis() + uniqueCounter;
      feedList.put(new Date(nextUpdate), rssOwlFavorite);
      dateList.add(new Date(nextUpdate));
    }
  }

  /**
   * Check the feedList in a certain interval and update the next favorite which
   * update date is before the current date.
   */
  public void run() {
    while (!isInterrupted()) {

      /** Get the oldest update date if not currently loading */
      if (!rssOwlGui.isBusyLoading() && dateList.iterator().hasNext()) {

        /** Get the next update date */
        Date upDate = (Date) dateList.iterator().next();

        /** Reset the current rssowl favorite */
        currentRSSOwlFavorite = null;

        /** Get favorite if update is before current date and thereby outstanding */
        if (upDate.before(new Date()))
          currentRSSOwlFavorite = (Favorite) feedList.get(upDate);

        /**
         * Only reload if there is a favorites to reload and if there is
         * currently no feed loading in RSSOwl
         */
        if (currentRSSOwlFavorite != null && !rssOwlGui.isBusyLoading() && GUI.isAlive()) {

          /** Perform load of favorites */
          GUI.display.syncExec(new Runnable() {
            public void run() {

              /** Reload news feed */
              rssOwlGui.reloadNewsFeed(currentRSSOwlFavorite.getUrl());
            }
          });

          /** Set a new update date for the favorite in the feedList */
          updateFeedList(currentRSSOwlFavorite);
        }
      }

      /** Sleep for some seconds */
      try {
        sleep(UPDATE_INTERVAL);
      } catch (InterruptedException e) {
        return;
      }
    }
  }
}