/*   **********************************************************************  **
 **   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.model;

import net.sourceforge.rssowl.controller.GUI;
import net.sourceforge.rssowl.controller.thread.FeedAutoUpdater;
import net.sourceforge.rssowl.util.GlobalSettings;
import net.sourceforge.rssowl.util.shop.FontShop;
import net.sourceforge.rssowl.util.shop.PaintShop;
import net.sourceforge.rssowl.util.shop.StringShop;
import net.sourceforge.rssowl.util.shop.WidgetShop;

import org.eclipse.swt.widgets.TreeItem;

/**
 * This is a Favorite for Newsfeeds.
 * 
 * @author <a href="mailto:bpasero@rssowl.org">Benjamin Pasero </a>
 * @version 1.2.3
 */
public class Favorite {

  /** The String representation of the category */
  private String catPath;

  /** Date of creation */
  private long creationDate;

  /** Description of the feed */
  private String description;

  /** TRUE if an warning occured while loading the favorite */
  private boolean errorLoading;

  /** Homepage of this favorites newsfeed */
  private String homepage;

  /** If TRUE this favorite is showing when a blogroll is synced */
  private boolean isSynchronizer;

  /** Language of the feed */
  private String language;

  /** Date of last visit */
  private long lastVisitDate;

  /** TRUE if the favorite should be load on startup of RSSOwl */
  private boolean loadOnStartup;

  /** TRUE if the feed should open on startup */
  private boolean openOnStartup;

  /** The category this favorite is saved into */
  private Category rssOwlCategory;

  /** Title of the favorite */
  private String title;

  /** The number of unread news in this favorite */
  private int unreadNewsCount;

  /** Update interval of the favorite */
  private int updateInterval;

  /** URL of the favorite */
  private String url;

  /** TRUE if a proxy should be used */
  private boolean useProxy;

  /** The treeitem this favorite is saved in */
  TreeItem treeItem;

  /**
   * Instantiate a new Favorite
   * 
   * @param url The URL / Path to the RSS / RDF XML
   * @param title Title of the favorite
   * @param rssOwlCategory The category this favorite is saved into
   */
  public Favorite(String url, String title, Category rssOwlCategory) {
    this.url = url;
    this.title = title;
    this.rssOwlCategory = rssOwlCategory;
    isSynchronizer = false;
    errorLoading = false;
    description = "";
    language = "";
    homepage = "";

    /** Use Default Settings */
    loadOnStartup = GlobalSettings.favDefaultReloadOnStartup;
    openOnStartup = GlobalSettings.favDefaultOpenOnStartup;
    updateInterval = GlobalSettings.favDefaultAutoReloadInterval;
  }

  /**
   * Reset the Metadata Information of this Favorite.
   */
  public void clearMetaData() {
    setDescription("");
    setLanguage("");
    setHomepage("");
  }

  /**
   * Clone settings from this favorite into the given one
   * 
   * @param rssOwlFavorite The favorite to clone the settings into
   */
  public void clone(Favorite rssOwlFavorite) {
    rssOwlFavorite.setOpenOnStartup(openOnStartup);
    rssOwlFavorite.setLoadOnStartup(loadOnStartup);
    rssOwlFavorite.setUpdateInterval(updateInterval);
    rssOwlFavorite.setCreationDate(creationDate);
    rssOwlFavorite.setDescription(description);
    rssOwlFavorite.setErrorLoading(errorLoading);
    rssOwlFavorite.setHomepage(homepage);
    rssOwlFavorite.setLanguage(language);
    rssOwlFavorite.setLastVisitDate(lastVisitDate);
    rssOwlFavorite.setUnreadNewsCount(unreadNewsCount);
    rssOwlFavorite.setUseProxy(useProxy);
  }

  /**
   * Duplicate this favorite into the given one. In difference to the clone()
   * Method the duplicate method will not only clone lightweight settings but
   * also copy the url, title and category represented as String.
   * 
   * @param rssOwlFavorite The favorite to duplicate into
   */
  public void duplicate(Favorite rssOwlFavorite) {
    rssOwlFavorite.setUrl(url);
    rssOwlFavorite.setTitle(title);
    rssOwlFavorite.setCatPath((rssOwlCategory != null) ? rssOwlCategory.toCatPath() : catPath);
    clone(rssOwlFavorite);
  }

  /**
   * Get the String representation of the category this favorite is in. The
   * field is not set automatically.
   * 
   * @return String The String representation of the category this favorite is
   * in if the field was set
   */
  public String getCatPath() {
    return catPath;
  }

  /**
   * Get the creation date of this favorite
   * 
   * @return long Returns the creationDate.
   */
  public long getCreationDate() {
    return creationDate;
  }

  /**
   * Get the description of this favorit's feed
   * 
   * @return String Returns the description.
   */
  public String getDescription() {
    return description;
  }

  /**
   * Get the homepage of this favorit's feed
   * 
   * @return Returns the homepage.
   */
  public String getHomepage() {
    return homepage;
  }

  /**
   * Ge the language of this favorit's feed
   * 
   * @return String Returns the language.
   */
  public String getLanguage() {
    return language;
  }

  /**
   * Get the last visit date of this favorite
   * 
   * @return long Returns the lastVisitDate.
   */
  public long getLastVisitDate() {
    return lastVisitDate;
  }

  /**
   * Get the rssOwlCategory this favorite is saved into.
   * 
   * @return Category The category this favorite is saved into
   */
  public Category getRSSOwlCategory() {
    return rssOwlCategory;
  }

  /**
   * @return String Title of the Favorite
   */
  public String getTitle() {
    return title;
  }

  /**
   * @return Returns the treeItem this favorite is saved in.
   */
  public TreeItem getTreeItem() {
    return treeItem;
  }

  /**
   * Get the number of unread news for this favorite.
   * 
   * @return Returns the unreadNewsCount.
   */
  public int getUnreadNewsCount() {
    return unreadNewsCount;
  }

  /**
   * Get the update interval
   * 
   * @return int Updateinterval in minutes
   */
  public int getUpdateInterval() {
    return updateInterval;
  }

  /**
   * @return String URL / Path of the RSS / RDF XML
   */
  public String getUrl() {
    return url;
  }

  /**
   * @return TRUE if there is an warning loading the favorite
   */
  public boolean isErrorLoading() {
    return errorLoading;
  }

  /**
   * @return boolean TRUE if the favorite should load on startup of RSSOwl
   */
  public boolean isLoadOnStartup() {
    return loadOnStartup;
  }

  /**
   * @return boolean TRUE if the favorite should open on startup of RSSOwl
   */
  public boolean isOpenOnStartup() {
    return openOnStartup;
  }

  /**
   * @return TRUE if this favorite is a synchronizer
   */
  public boolean isSynchronizer() {
    return isSynchronizer;
  }

  /**
   * @return boolean TRUE if use proxy
   */
  public boolean isUseProxy() {
    return useProxy;
  }

  /**
   * Set the String representation of the category this favorite is in
   * 
   * @param catPath The path to the category this favorite is in
   */
  public void setCatPath(String catPath) {
    this.catPath = catPath;
  }

  /**
   * Set the creation date of this favorite
   * 
   * @param creationDate The creationDate to set.
   */
  public void setCreationDate(long creationDate) {
    this.creationDate = creationDate;
  }

  /**
   * Set the description of this favorit's feed
   * 
   * @param description The description to set.
   */
  public void setDescription(String description) {
    this.description = description;
  }

  /**
   * Set TRUE if there is an warning loading the favorite
   * 
   * @param errorLoading
   */
  public void setErrorLoading(boolean errorLoading) {
    this.errorLoading = errorLoading;
  }

  /**
   * Set the homepage of this favorite's feed
   * 
   * @param homepage The homepage to set.
   */
  public void setHomepage(String homepage) {
    this.homepage = homepage;
  }

  /**
   * Set the language of this favorit's feed
   * 
   * @param language The language to set.
   */
  public void setLanguage(String language) {
    this.language = language;
  }

  /**
   * Set the last visit date
   * 
   * @param lastVisitDate The lastVisitDate to set.
   */
  public void setLastVisitDate(long lastVisitDate) {
    this.lastVisitDate = lastVisitDate;
  }

  /**
   * Set TRUE if the favorite should load on startup of RSSOwl
   * 
   * @param loadOnStartup
   */
  public void setLoadOnStartup(boolean loadOnStartup) {
    this.loadOnStartup = loadOnStartup;
  }

  /**
   * Set TRUE if the favorite should open on startup
   * 
   * @param openOnStartup The openOnStartup to set.
   */
  public void setOpenOnStartup(boolean openOnStartup) {
    this.openOnStartup = openOnStartup;
  }

  /**
   * If set to TRUE, this favorite is showing when a Blogroll is synced.
   * 
   * @param isSynchronizer The isSynchronizer to set.
   */
  public void setSynchronizer(boolean isSynchronizer) {
    this.isSynchronizer = isSynchronizer;
  }

  /**
   * Set the title of this favorite
   * 
   * @param title
   */
  public void setTitle(String title) {
    this.title = title;
  }

  /**
   * @param treeItem The treeItem in which this favorite is saved.
   */
  public void setTreeItem(TreeItem treeItem) {
    this.treeItem = treeItem;
  }

  /**
   * Set the number of unread news for this favorite.
   * 
   * @param unreadNewsCount The unreadNewsCount to set.
   */
  public void setUnreadNewsCount(int unreadNewsCount) {
    this.unreadNewsCount = unreadNewsCount;
  }

  /**
   * Set the updateinterval in minutes
   * 
   * @param updateInterval
   */
  public void setUpdateInterval(int updateInterval) {
    this.updateInterval = updateInterval;
    FeedAutoUpdater.updateFeedList(this);
  }

  /**
   * Set the URL of this favorite
   * 
   * @param url
   */
  public void setUrl(String url) {
    this.url = url;
  }

  /**
   * Set TRUE if use proxy
   * 
   * @param useProxy
   */
  public void setUseProxy(boolean useProxy) {
    this.useProxy = useProxy;
  }

  /**
   * Sync up the meta data for this favorite
   * 
   * @param rssChannel The feed to get the data from
   */
  public void syncMetaData(Channel rssChannel) {

    /** Description */
    setDescription(StringShop.isset(rssChannel.getDescription()) ? rssChannel.getDescription() : "");

    /** Language */
    setLanguage(StringShop.isset(rssChannel.getLanguage()) ? rssChannel.getLanguage() : "");

    /** Homepage */
    setHomepage(StringShop.isset(rssChannel.getHomepage()) ? rssChannel.getHomepage() : "");
  }

  /**
   * @return TRUE if unread news are available
   */
  public boolean unreadNewsAvailable() {
    return (unreadNewsCount != 0);
  }

  /**
   * Update the state of the warning flag to the in a seperate asynchron
   * runnable.
   * 
   * @param isError TRUE if there was an warning loading the favorite
   */
  public void updateErrorState(final boolean isError) {

    /** Only perform this Runnable if RSSOwl was not closed */
    if (GUI.isAlive()) {
      GUI.display.asyncExec(new Runnable() {
        public void run() {

          /** Only update on changes and if treeitem is not yet disposed */
          if (WidgetShop.isset(getTreeItem()) && isErrorLoading() != isError) {

            /** Set Error Flag to TRUE */
            setErrorLoading(isError);

            /** Reset the number of unread News to 0 in case of an error */
            if (isError)
              updateReadStatus(0);

            /** Update the Icon */
            GUI.rssOwlGui.getRSSOwlFavoritesTree().updateTreeItemIcon(getTreeItem());
          }
        }
      });
    }
  }

  /**
   * Update this favorites number of unread news and also update the connected
   * treeitem.
   * 
   * @param unreadNewsCount Number of unread news
   */
  public void updateReadStatus(final int unreadNewsCount) {
    updateReadStatus(unreadNewsCount, true);
  }

  /**
   * Update this favorites number of unread news and also update the connected
   * treeitem.
   * 
   * @param unreadNewsCount Number of unread news
   * @param updateSysTray Wether to update the Systemtray status
   */
  public void updateReadStatus(final int unreadNewsCount, final boolean updateSysTray) {

    /** Remember old unread News Count */
    int oldUnreadNewsCount = getUnreadNewsCount();

    /** Flag indicating a State Change */
    final boolean isStateChange = (oldUnreadNewsCount > 0 && unreadNewsCount == 0) || (oldUnreadNewsCount == 0 && unreadNewsCount > 0);

    /** Assign new count to favorite */
    setUnreadNewsCount(unreadNewsCount);

    /** Do nothing if number did not change */
    if (oldUnreadNewsCount == unreadNewsCount)
      return;

    /** Only perform this Runnable if RSSOwl was not closed */
    if (GUI.isAlive()) {
      GUI.display.syncExec(new Runnable() {
        public void run() {
          if (!treeItem.isDisposed()) {

            /** Update the title to include the count * */
            GUI.rssOwlGui.getRSSOwlFavoritesTree().appendUnreadCount(treeItem, getTitle(), unreadNewsCount);

            /** Return at this point, if the state has not changed */
            if (!isStateChange)
              return;

            /** Set image in dependance of available unread news */
            treeItem.setImage((unreadNewsCount > 0) ? PaintShop.iconLenseUnread : PaintShop.iconLense);

            /** Set Font style in dependance if unread news are available */
            treeItem.setFont((unreadNewsCount > 0) ? FontShop.treeBoldFont : FontShop.treeFont);

            /** Update TreeItem Data to new status */
            ((TreeItemData) treeItem.getData()).setStatusUnread((unreadNewsCount > 0));

            /** Update complete tree */
            GUI.rssOwlGui.getRSSOwlFavoritesTree().updateTreeReadStatus(treeItem);

            /** Update the systray status if required */
            if (GlobalSettings.useSystemTray() && GlobalSettings.showSystrayIcon && GUI.rssOwlGui.getRSSOwlSystray() != null && updateSysTray) {
              boolean treeHasUnreadFavs = GUI.rssOwlGui.getRSSOwlFavoritesTree().getTreeHasUnreadFavs();
              GUI.rssOwlGui.getRSSOwlSystray().setTrayItemState(treeHasUnreadFavs);
            }
          }
        }
      });
    }
  }
}