// War.java

import java.util.*;

// the Suit enumeration represents one of the four suits
enum Suit {
    Clubs,
    Hearts,
    Diamonds,
    Spades
}

// the Card class represents one standard playing card
class Card {
    private Suit suit;
    private int value;

    // create one playing card
    public Card(Suit s, int v) {
        suit = s;
        value = v;
    }

    // print the playing card to the terminal
    public void print() {
        // prints the value
        if (value == 11) System.out.print("Jack");
        else if (value == 12) System.out.print("Queen");
        else if (value == 13) System.out.print("King");
        else if (value == 14) System.out.print("Ace");
        else System.out.print(value);

        // print the suit
        System.out.print(" of ");
        System.out.println(suit);
    }

    // return the value
    public int getValue() {
        return value;
    }

    // compate this card to another one passed in:
    // return negative if this one is less
    // positive if more
    // zero if equal
    public int compareTo(Card other) { 
        if (value < other.value) {
            return -1;
        } else if (value > other.value) {
            return 1;
        } else {
            return 0;
        }
    } 
}


// the pile represents a pile of cards, you can add to the top
// or draw from the top - used for the players deck and discard
// and also the "pot" of cards to be won on a tie
class Pile {
    // the pile has up to 52 cards, but normally less than that
    private Card[] cards;
    private int count;

    // constructor - set it to an empty pile
    public Pile() {
        cards = new Card[52];
        count = 0;
    }

    // see how many cards there are?
    public int getCount() {
        return count;
    }

    // clear out this pile
    public void clear() {
        for (int i = 0; i < 52; i++) {
            cards[i] = null;
        }
        count = 0;
    }

    // take the next card off the pile and return it
    public Card draw() {
        Card top = cards[count - 1];
        cards[count - 1] = null;
        count--;
        return top;
    }

    // print all cards in this pile
    public void printAll() {
        for (Card c : cards) {
            c.print();
        }
    }

    // add a pile into this pile
    public void addPile(Pile other) {
        // copy each card into our array
        for (int i = 0; i < other.count; i++) {
            cards[count] = other.cards[i];
            count++;
        }
    }

    // add a single card onto this pile
    public void addCard(Card other) {
        cards[count] = other;
        count++;
    }

    // shuffle the pile of cards
    public void shuffle() {
        Random generator = new Random();

        // make multiple passes of swapping
        int num_passes = generator.nextInt(30) + 30;
        for (int passes = 0; passes < num_passes; passes++) {

            // do one pass of randomly sswapping some cards
            for (int i = 0; i < count; i++) {
                if (generator.nextInt(2) == 0) {
                    // choose a new index - but not the same one!
                    int new_index;
                    do {
                        // find new index of this
                        new_index = generator.nextInt(count);
                    } while (new_index == i);

                    // swap them
                    Card temp = cards[i];
                    cards[i] = cards[new_index];
                    cards[new_index] = temp;
                }
            } 
        }
    }
}


// the Player class represents one of the players of
// war whop has two piles of card used in playing
class Player {
    private Pile deck;
    private Pile discard;
    
    public Player() {
        deck = new Pile();
        discard = new Pile();
    }
    
    public void addToDeck(Card c) {
        deck.addCard(c);
    }
    
    public void addToDiscard(Card c) {
        discard.addCard(c);
    }
    
    // used to check for game over
    public boolean hasCards() {
        if (deck.getCount() + discard.getCount() > 0) {
            return true;
        } else {
            return false;
        }
    }
    
    // get total amount of cards left
    public int cardCount() {
        return deck.getCount() + discard.getCount();
    }
    
    // get the players top card
    public Card getNextCard() {
        // if we have cards in deck, play top one
        if (deck.getCount() > 0) {
            Card next = deck.draw();
            return next;
        } else {
            if (discard.getCount() == 0) {
                throw new IllegalStateException("Error: No card to play");
            } else {
                // cards in discard pile, but not the deck
                discard.shuffle();
                deck.addPile(discard);
                discard.clear();
                
                // draw from the deck now
                return deck.draw();
            }
        }
    }
}


// the "main" class for the program
public class War {

    // make standard 52-card pile
    public static Pile makeStandardPile() {
        // make an empty pile of cards
        Pile cards = new Pile();

        // for each suit
        for (Suit s : Suit.values()) { 
            // for each value
            for (int v = 2; v <= 14; v++) {
                //add this card
                Card next = new Card(s, v);
                cards.addCard(next);
            }
        }
        return cards;
    }

    // perform one round of play
    public static void round(Player p1, Player p2) {
        // start pot as empty
        Pile pot = new Pile();

        // keep going until done
        boolean done = false;
        while (!done) {
            // draw a card from each player
            Card p1_card = p1.getNextCard();
            Card p2_card = p2.getNextCard();
            
            System.out.print("Player 1 threw a ");
            p1_card.print();
            System.out.print("Player 2 threw a ");
            p2_card.print();

            // if one player won, give them all the cards and we are done
            if (p1_card.compareTo(p2_card) < 0) {
                System.out.println("Player 2 takes the round.");
                // p2 wins round
                p2.addToDiscard(p1_card);
                p2.addToDiscard(p2_card);
                // p2 gets pot
                while (pot.getCount() > 0) {
                    p2.addToDiscard(pot.draw());
                }
                done = true;
            } else if (p1_card.compareTo(p2_card) > 0) {
                System.out.println("Player 1 takes the round.");
                // p1 wins round
                p1.addToDiscard(p1_card);
                p1.addToDiscard(p2_card);
                // p1 gets pot
                while (pot.getCount() > 0) {
                    p1.addToDiscard(pot.draw());
                }
                done = true;
            } else {
                // it's a tie!!!!!

                // add the two cards to the pot
                pot.addCard(p1_card);
                pot.addCard(p2_card);

                // check flip cards for p1
                int flipsp1 = 3;
                if (p1.cardCount() == 0) {
                    // p1 has no cards!!!!!
                    return;
                }
                if (p1.cardCount() < 4) {                
                    flipsp1 = p1.cardCount() - 1;
                }
                
                // check flip cards for p2
                int flipsp2 = 3;
                if (p2.cardCount() == 0) {
                    return;
                }
                if (p2.cardCount() < 4) {
                    flipsp2 = p2.cardCount() - 1;
                }
                
                // figure out how may cards to actually flip
                int flips;
                if (flipsp1 < flipsp2) {
                    flips = flipsp1;
                } else {
                    flips = flipsp2;
                }


                // actually do the flipping
                for (int i = 0; i < flips; i++) {
                    pot.addCard(p1.getNextCard());
                    pot.addCard(p2.getNextCard());
                }
            }
        }
    }

    // the main function
    public static void main(String args[]) {
        // initalize the deck and the two players
        Pile deck = makeStandardPile();
        Player player1 = new Player();
        Player player2 = new Player();

        // shuffle the cards
        deck.shuffle();

        // deal out the cards
        for (int i = 0; i < 52; i++) {
            // pick the next card
            Card c = deck.draw();

            // give to either player1 or player2
            if (i % 2 == 0) {
                player1.addToDeck(c);
            } else {
                player2.addToDeck(c);
            }
        }

        // player until someone runs out of cards
        int round = 1;
        while (player1.hasCards() && player2.hasCards()) {
            round(player1, player2);
            System.out.printf("After round %d, Player 1 has %d cards, and player 2 has %d.\n\n",
                    round, player1.cardCount(), player2.cardCount());
            round++;
        }
        
        // check for winner
        if (player1.cardCount() > player2.cardCount()) {
            System.out.println("Player 1 has won!");
        } else if (player2.cardCount() > player1.cardCount()) {
            System.out.println("Player 2 has won!");
        } else {
            System.out.println("BOth players have " + player1.cardCount() +
                    " cards?????????????");
        }
    }
}