// Arup Guha
// 11/17/09
// CollectionOfUnoCards Class for AP Computer Science Assignment: Uno
// Edited on 12/12/2015 for Junior Knights

import java.util.*;

public class CollectionOfUnoCards {

	final public static int MAXCARDS = 72;
	private ArrayList<UnoCard> cards;

	public CollectionOfUnoCards() {
		cards = new ArrayList<UnoCard>();
	}

	// Tries to add c to this collection. Adds c if and only if there aren't already 72 cards in the collection.
	// Returns true if c was added, false otherwise.
	public boolean addCard(UnoCard c) {

		// Don't allow us to add this card if we're full.
		if (cards.size() == MAXCARDS)
			return false;

		// It's okay to add the card.
		cards.add(c);
		return true;
	}

	// If the collection is non-empty, this removes and returns the last card (top) from the collection. If the
	// collection is already empty, null is returned.
	public UnoCard removeFromTop() {

		// This is how we indicate that there's no card to return.
		if (cards.size() == 0)
			return null;

		// Remove and return the card.
		return cards.remove(cards.size()-1);
	}

	// If the collection is non-empty, this removes and returns the card at location index. If the
	// collection is already empty, null is returned.
	public UnoCard remove(int index) {

		// The invalid case here.
		if (index < 0 || index >= cards.size())
			return null;

		// This is the card to remove.
		return cards.remove(index);
	}

	// This clears what is currently in the collection and fills it with a deck of Uno cards,
	// with two copies of each card.
	public void makeDeck() {

		// This clears our deck!
		cards.clear();

		// Making 2 copies of each card.
		for (int i=0; i<2; i++)

			// Go through each color.
			for (int j=0; j<4; j++)

				// Go through each number.
				for (int k=1; k<=9; k++)
					cards.add(new UnoCard(j,k));

	}

	// Shuffles this deck by randomly picking two cards and swapping them, 200 times.
	public void shuffle() {

		Random r = new Random();

		// Repeat 200 times.
		for (int i=0; i<200; i++) {

			// Choose two random cards.
			int c1 = r.nextInt(cards.size());
			int c2 = r.nextInt(cards.size());

			// Swap these two cards.
			UnoCard temp = cards.get(c1);
			cards.set(c1, cards.get(c2));
			cards.set(c2, temp);
		}
	}

	// Returns a string representation of this collection. Just print out each card in a numbered list,
	// as it's stored in the deck.
	public String toString() {

		// We're going to have to build this String, piece by piece.
		String answer = "";

		// Add one line at a time to this string, for each card.
		for (int i=0; i<cards.size(); i++)
			answer = answer + i+". " + cards.get(i) + "\n";

		// Now we have the String representation of the whole group.
		return answer;
	}

	// Returns the number of cards.
	public int getNumCards() {
		return cards.size();
	}

	// Returns the card at the top of this collection.
	public UnoCard getTopCard() {
		if (cards.size() == 0)
			return null;
		return cards.get(cards.size()-1);
	}

	// Returns true iff there's any card in this collection that can be played
	// on top of c.
	public boolean canPlay(UnoCard c) {

		// Try to find a card in our collection that can be played on c.
		for (int i=0; i<cards.size(); i++)
			if (cards.get(i).canPlay(c))
				return true;

		// If we get here, no card was found.
		return false;
	}

	// Returns the in position index.
	public UnoCard getCard(int index) {
		if (index >= cards.size() || index < 0)
			return null;
		return cards.get(index);
	}

	public static void main(String[] args) {

		CollectionOfUnoCards mine = new CollectionOfUnoCards();
		mine.addCard(new UnoCard(0,4));
		mine.addCard(new UnoCard(0,7));
		mine.addCard(new UnoCard(1,3));
		mine.addCard(new UnoCard(1,5));
		mine.addCard(new UnoCard(1,9));
		mine.addCard(new UnoCard(2,4));
		mine.addCard(new UnoCard(3,1));
		System.out.println("I now have: ");
		System.out.println(mine);

		System.out.println("Removing the top card: "+mine.removeFromTop());
		System.out.println("Removing the card at index 3: "+mine.remove(3));
		if (mine.remove(5) == null) System.out.println("There is no card at index 5.");

		// So we can see what we really have.
		System.out.println("I now have: ");
		System.out.println(mine);

		// Try out the can play method.
		UnoCard extra1 = new UnoCard(1,6);
		UnoCard extra2 = new UnoCard(3,2);
		if (mine.canPlay(extra1)) System.out.println("I can play on the card: "+extra1);
		if (mine.canPlay(extra2)) System.out.println("I can play on the card: "+extra2);
	}
}