import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

public class MiniGame {
	public static final int COLUMNS = 7;

	private ArrayList<Card> stock_ = new ArrayList<Card>();
	private ArrayList<Card> waste_ = new ArrayList<Card>();
	private ArrayList<ArrayList<Card>> columns_ =
	    new ArrayList<ArrayList<Card>>();
	private String lastError_ = "";

	public MiniGame ( long seed ) {
		String[] suits = { "♥", "♦", "♣", "♠" };
		for ( int s = 0 ; s < suits.length ; s++ ) {
			for ( int rank = 1 ; rank <= 13 ; rank++ ) {
				stock_.add(new Card(rank,suits[s]));
			}
		}
		Collections.shuffle(stock_,new Random(seed));
		for ( int c = 0 ; c < COLUMNS ; c++ ) {
			ArrayList<Card> column = new ArrayList<Card>();
			for ( int n = 0 ; n <= c ; n++ ) {
				column.add(stock_.remove(stock_.size() - 1));
			}
			columns_.add(column);
		}
	}

	/**
	 * Turns over the top stock card, or recycles the waste when the stock is
	 * empty.
	 */
	public void drawFromStock () {
		if ( stock_.isEmpty() ) {
			while ( !waste_.isEmpty() ) {
				stock_.add(waste_.remove(waste_.size() - 1));
			}
		} else {
			waste_.add(stock_.remove(stock_.size() - 1));
		}
	}

	/**
	 * Moves the waste card onto a column if the rules allow it; otherwise sets
	 * getLastError().
	 */
	public boolean moveWasteTo ( int column ) {
		Card moving = getWasteTop();
		Card target = getColumnTop(column);
		if ( moving == null ) {
			lastError_ = "There is no card on the waste pile.";
			return false;
		}
		if ( target == null && moving.getRank() != 13 ) {
			lastError_ = "Only a king can go on an empty column.";
			return false;
		}
		if ( target != null ) {
			if ( target.isRed() == moving.isRed() ) {
				lastError_ =
				    "Colors must alternate: " + moving + " can't go on " + target + ".";
				return false;
			}
			if ( moving.getRank() != target.getRank() - 1 ) {
				lastError_ = "The card must be one lower: " + moving + " can't go on "
				    + target + ".";
				return false;
			}
		}
		columns_.get(column).add(waste_.remove(waste_.size() - 1));
		lastError_ = "";
		return true;
	}

	public Card getWasteTop () {
		if ( waste_.isEmpty() ) {
			return null;
		}
		return waste_.get(waste_.size() - 1);
	}

	public Card getColumnTop ( int column ) {
		ArrayList<Card> cards = columns_.get(column);
		if ( cards.isEmpty() ) {
			return null;
		}
		return cards.get(cards.size() - 1);
	}

	public int getStockSize () {
		return stock_.size();
	}

	public String getLastError () {
		return lastError_;
	}
}
