package ps2.playingcards;


import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.ImageIcon;



/**
 * Represents one of the four suits (Hearts, Spades, Diamonds, Clubs) that appear
 * on a playing card.  This class is immutable.
 */
public final class CardSuit implements Comparable {


	 //
	 // CONSTANTS
	 //

	 // The 4 acceptable card suits.

	 /**
	  * The suit of clubs.
	  */
	 public static final CardSuit CLUBS = new CardSuit("club");

	 /**
	  * The suit of diamonds.
	  */
	 public static final CardSuit DIAMONDS = new CardSuit("diamond");

	 /**
	  * The suit of spades.
	  */
	 public static final CardSuit SPADES = new CardSuit("spade");

	 /**
	  * The suit of hearts.
	  */
	 public static final CardSuit HEARTS = new CardSuit("heart");



	 // Rankings of the suits.

	 /**
	  * A list that ranks the suits in order from highest suit to lowest suit.  The highest ranked suit
	  * is HEARTS, followed in order by SPADES, DIAMONDS, and CLUBS.
	  */
	 public static final List SUITS =
		  Collections.unmodifiableList(Arrays.asList(new CardSuit[] {HEARTS, SPADES, DIAMONDS, CLUBS}));



	 //
	 // MEMBER VARIABLES
	 //

	 /**
	  * The name of this suit.
	  */
	 private final String name;

	 /**
	  * A small icon representing this suit.  This will be initialized lazily.
	  */
	 private ImageIcon smallSuitIcon = null;

	 /**
	  * A large icon representing this suit.  This will be initialized lazily.
	  */
	 private ImageIcon largeSuitIcon = null;



	 //
	 // METHODS
	 //

	 //-------------------------------------------
	 /**
	  * Creates a new card suit.
	  *
	  * @param suitName the name of this suit
	  *
	  *
	  * @requires <code>suitName</code> be one of "heart", "spade", "diamond", or "club"
	  * @modifies this
	  * @effects  creates a new <code>CardSuit</code> object
	  */
	 private CardSuit(String suitName) {
		  if (suitName == null) {
				throw new NullPointerException();
		  }

          name = suitName + "s";
	 }


	 //-------------------------------------------
	 /**
	  * Returns the small icon representing this suit.
	  *
	  * @return the small icon representing this suit
	  *
	  *
	  * @requires nothing
	  * @modifies nothing
	  * @effects  returns the small icon representing this suit
	  */
	 public ImageIcon getSmallIcon() {
         if(smallSuitIcon == null) {
             String nameWithoutS = name.substring(0, name.length() - 1);
             URL url = ClassLoader.getSystemResource("ps2/images/" + nameWithoutS + ".gif");
             smallSuitIcon = new ImageIcon(url);
         }
         return smallSuitIcon;
	 }


	 //-------------------------------------------
	 /**
	  * Returns the large icon representing this suit.
	  *
	  * @return the large icon representing this suit
	  *
	  *
	  * @requires nothing
	  * @modifies nothing
	  * @effects  returns the large icon representing this suit
	  */
	 public ImageIcon getLargeIcon() {
         if(largeSuitIcon == null) {
             String nameWithoutS = name.substring(0, name.length() - 1);
             URL url = ClassLoader.getSystemResource("ps2/images/" + nameWithoutS + "_large.gif");
             largeSuitIcon = new ImageIcon(url);
         }
         return largeSuitIcon;
	 }


	 //-------------------------------------------
	 /**
	  * Returns the name of this suit.
	  *
	  * @return the name of this suit
	  *
	  *
	  * @requires nothing
	  * @modifies nothing
	  * @effects  returns the name of this suit
	  */
	 public String getName() {
		  return name;
	 }


	 //-------------------------------------------
	 /**
	  * Compares this card suit with the specified card suit for order.
	  *
	  * @param o  the Object to be compared
	  * @return   a negative integer, zero, or a positive integer if this CardSuit
	  *           is less than, equal to, or greater than the specified CardSuit,
	  *           respectively
	  * @exception ClassCastException if the specified object's type is not CardSuit
	  * @exception NullPointerException if the specified object is null
	  *
	  *
	  * @requires nothing
	  * @modifies nothing
	  * @effects  <ul>
	  *             <li>If <code>o</codE> is null, throws a <code>NullPointerException</code></li>
	  *             <li>If <code>o</code> is not an instance of CardSuit, throws a
	  *                 <code>ClassCastException</code></li>
	  *             <li>Returns a negative integer, zero, or a positive integer if this
	  *                 <code>CardSuit</code> is less than, equal to, or greater than the
	  *                 specified <code>CardSuit</code>, respectively</li>
	  *           </ul>
	  */
	 public int compareTo(Object o) {
	     
	     if (o == null)
		 throw new NullPointerException();
	     
	     // Remember the "higher ranked" suits appear first in the array (i.e. at lower indicies).
	     return (0 - (SUITS.indexOf(this) - SUITS.indexOf((CardSuit)o)));
	 }


	 //-------------------------------------------
	 /**
	  * Returns a description of this suit.
	  *
	  * @return a description of this suit
	  *
	  *
	  * @requires nothing
	  * @modifies nothing
	  * @effects  returns a description of this suit
	  */
	 public String toString() {
		  return getName();
	 }

}
