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

import net.sourceforge.rssowl.model.NewsItem;
import net.sourceforge.rssowl.util.GlobalSettings;

import java.util.Comparator;
import java.util.Date;
import java.util.Hashtable;

/**
 * Abstract class implementing Comparator and taking a Hashtable of RSSNewsItems
 * as the list of elements givin the ordering consists of keys to retrieve those
 * RSSNewsItems from the Hashtable.
 * 
 * @author <a href="mailto:masterludo@gmx.net">Ludovic Kim-Xuan Galibert </a>
 * @version 1.2.3
 */
public abstract class AbstractSorter implements Comparator {

  /** Holds the Hashtable of RSSNewsItems */
  private Hashtable items;

  /**
   * Creates a new instance of AbstractSorter.
   * 
   * @param someItems a Hashtable containing RSSNewsItems, may be null.
   */
  protected AbstractSorter(Hashtable someItems) {
    setItems(someItems);
  }

  /**
   * This method is called in case two newsitems with the same values where
   * compared with. This is most common in case newsitems are first sorted by
   * status. In that case, this method will try to sort the two newsitems by
   * other items from the sortOrder Vector.
   * 
   * @param o1 the first key (news title) to retrieve the first NewsItem to
   * compare
   * @param o2 the second key (news title) to retrieve the second NewsItem to
   * compare
   * @return -1 if the first NewsItem is alphabetically before the second, and 1
   * if the second NewsItem is alphabetically before the first.
   */
  protected int completeCompare(Object o1, Object o2) {
    NewsItem item1 = (NewsItem) getItems().get(o1);
    NewsItem item2 = (NewsItem) getItems().get(o2);

    /** For each sort order item, beginning with the second one */
    for (int a = 1; a < GlobalSettings.sortOrder.size(); a++) {
      String sortOrderItem = (String) GlobalSettings.sortOrder.get(a);

      /** Sort on Publish Date */
      if (sortOrderItem.equals("TABLE_HEADER_PUBDATE")) {
        Date date1 = (item1.getPubDate() != null) ? item1.getPubDateParsed() : null;
        Date date2 = (item2.getPubDate() != null) ? item2.getPubDateParsed() : null;

        /** Check if Publish Date is available */
        if (date1 != null && date2 != null) {
          int result = date2.compareTo(date1);
          if (result != 0)
            return result;
        }

        /** NewsItem2 is alphabetical before NewsItem1 */
        else if (date1 != null)
          return -1;

        /** NewsItem1 is alphabetical before NewsItem2 */
        else if (date2 != null)
          return 1;
      }

      /** Sort on Status */
      else if (sortOrderItem.equals("TABLE_HEADER_STATUS")) {
        int result = String.valueOf(item1.isRead()).compareTo(String.valueOf(item2.isRead()));
        if (result != 0)
          return result;
      }

      /** Sort on Title. That is default sort order */
      else if (sortOrderItem.equals("TABLE_HEADER_NEWSTITLE")) {
        break;
      }

      /** Sort on Author */
      else if (sortOrderItem.equals("TABLE_HEADER_AUTHOR")) {

        /** Check if author is available */
        if (item1.getAuthor() != null && item2.getAuthor() != null) {
          int result = item1.getAuthor().compareTo(item2.getAuthor());
          if (result != 0)
            return result;
        }

        /** NewsItem1 is alphabetical before NewsItem2 */
        else if (item1.getAuthor() != null)
          return -1;

        /** NewsItem1 is alphabetical before NewsItem2 */
        else if (item2.getAuthor() != null)
          return 1;
      }

      /** Sort on Category */
      else if (sortOrderItem.equals("TABLE_HEADER_CATEGORY")) {

        /** Check if category is available */
        if (item1.getCategory() != null && item2.getCategory() != null) {
          int result = item1.getCategory().compareTo(item2.getCategory());
          if (result != 0)
            return result;
        }

        /** NewsItem1 is alphabetical before NewsItem2 */
        else if (item1.getCategory() != null)
          return -1;

        /** NewsItem1 is alphabetical before NewsItem2 */
        else if (item2.getCategory() != null)
          return 1;
      }

      /** Sort on Publisher */
      else if (sortOrderItem.equals("TABLE_HEADER_PUBLISHER")) {

        /** Check if publisher is available */
        if (item1.getPublisher() != null && item2.getPublisher() != null) {
          int result = item1.getPublisher().compareTo(item2.getPublisher());
          if (result != 0)
            return result;
        }

        /** NewsItem1 is alphabetical before NewsItem2 */
        else if (item1.getPublisher() != null)
          return -1;

        /** NewsItem1 is alphabetical before NewsItem2 */
        else if (item2.getPublisher() != null)
          return 1;
      }

      /** Sort on Feed Name */
      else if (sortOrderItem.equals("TABLE_HEADER_FEED")) {

        /** Check if newsfeed title is available */
        if (item1.getNewsfeedTitle() != null && item2.getNewsfeedTitle() != null) {
          int result = item1.getNewsfeedTitle().compareTo(item2.getNewsfeedTitle());
          if (result != 0)
            return result;
        }

        /** NewsItem1 is alphabetical before NewsItem2 */
        else if (item1.getNewsfeedTitle() != null)
          return -1;

        /** NewsItem1 is alphabetical before NewsItem2 */
        else if (item2.getNewsfeedTitle() != null)
          return 1;
      }
    }

    /** Per Default sort on Title */
    return item1.getTitle().compareTo(item2.getTitle());
  }

  /**
   * Gets the Hashtable of RSSNewsItems.
   * 
   * @return a Hashtable containing RSSNewsItems, may be null.
   */
  protected Hashtable getItems() {
    return items;
  }

  /**
   * Sets the Hashtable of RSSNewsItems.
   * 
   * @param someItems a Hashtable containing RSSNewsItems, may be null.
   */
  protected void setItems(Hashtable someItems) {
    items = someItems;
  }
}