import java.io.*;

/**
 * A deck of playing cards.
 */

public class ListDeck implements Deck {

    private TwoEndedList deck = new LinkedTwoEndedList();
    
    /**
     * Read in the deck of cards from `stream'.
     *
     * @param MyStreamTokenizer stream the input stream for
     *        card names.
     */

    public void loadDeck(MyStreamTokenizer in) throws 
        IOException {        
        
        while(true) {
            int tokenType = in.nextToken();
            if(tokenType == MyStreamTokenizer.EOF)
                break;
            deck.addBack(new Card(in.sval));
            in.flushLine();
        }
    }
    
    /**
     * Randomly reorder the cards in my deck.
     *
     * @param MyRandom randomStream a stream of random
     *        numbers.
     */
 
     public void shuffle(MyRandom randomStream) {
    
        for(int shuffles=0; shuffles<3; shuffles++) {
        
        TwoEndedList newDeck = new LinkedTwoEndedList();
        
        int r;
        while(deck.size() > 0) {
        
            r = randomStream.nextInt();
            for(int i=0; i<r; i++) {
                if(deck.size() == 0) {
                    break;
                }
                newDeck.addBack(dealTop());
            }
            
            r = randomStream.nextInt();
            for(int i=0; i<r; i++) {
                if(deck.size() == 0) {
                    break;
                }
                newDeck.addBack(dealBottom());
            }
            
        }
        
        deck = newDeck;
        
        }
    }
    
    /**
     * Return the top card in my deck.
     * Precondition: My deck is not empty.
     *
     * @return Card the top card in my deck.
     */

    public Card topCard() {
    
        return (Card) deck.getFirst();
    }
    
    /**
     * Return the bottom card in my deck.  
     * Precondition: My deck is not empty.
     *
     * @return Card the bottom card in my deck.
     */

    public Card bottomCard() {
    
        return (Card) deck.getLast();
    }
    
    /**
     * Remove and return the bottom card in my deck.
     * Precondition: My deck is not empty.
     *
     * @return Card the bottom card in my deck.
     */

    public Card dealBottom() {
    
        return (Card) deck.removeLast();
    }
    
    /**
     * Remove and return the top card in my deck.
     * Precondition: My deck is not empty.
     *
     * @return Card the top card in my deck.
     */

    public Card dealTop() {
    
        return (Card) deck.removeFirst();
    }
    
    /**
     * Returns the number of cards remaining in my deck.
     *
     * @return int the number of cards remaining in my deck.
     */
 
    public int remainingCards() {
    
        return deck.size();
    }
    
    /**
     * Deal the cards in my deck to the players.  That is, print `players' columns 
     * showing what cards each of the players gets.
     *
     * @param int players the number of players, ie. the number of columns.
     */

    public void deal(int players) {
    
        while(deck.size() > 0) {
        
            for(int i=0; i < players && deck.size() > 0; i++) {
            
                System.out.print(dealTop().toString());
            } 
        System.out.println();
        } 
    }
}