//MatchingGamePlayingArea.java

/**
 * Simulates a playing surface for a card game in which two players
 * "match cards" against each other.  
 * It is essentially two stacks of cards--one stack for each 
 * player--where each player plays a single card
 * on their stack at the same time.
 *
 * @see War
 * @see Snap
 *
 * @author Zach Tomaszewski
 * @version 25 Feb 2005
 */
public class MatchingGamePlayingArea {

  /*
   * TODO:
   * --constructor that sets player names (plus default that doesn't)
   * --protected getPlayer1Deck, etc.  Be very clear that the two decks
   *   must contain only PlayC's and must have the same number of cards!
   */

  /* assumed that both decks will always contain the same number of cards */
  private Deck player1 = new Deck();
  private Deck player2 = new Deck();
  private String player1name = "Player1";
  private String player2name = "Player2";
  

  
  /**
   * Adds two cards to this area, one on each player's stack.
   *
   * @param player1card  Card to add to player 1's stack
   * @param player1card  Card to add to player 2's stack   
   */
  public void add(PlayingCard player1card, PlayingCard player2card) {
    this.player1.push(player1card);
    this.player2.push(player2card);
  }

  /**
   * Clears the area and returns all the cleared cards in a single deck.
   * <p>
   * Cards from the two player's stacks are combined (alternating between
   * stacks, from the buttom of the stacks to the top, starting with
   * the bottom card of player 1's stack) into a single Deck of cards.
   * The two stacks of this area are emptied.
   * 
   * @return A deck of all the cards formerly in the players' stacks.
   */
  public Deck clear() {

    Deck combined = new Deck();
    //both stacks should have the same number of cards, 
    for (int i = 0; i < this.player1.size(); i++) {
      //copying from bottom and then clearing more efficient for Vector
      combined.push(this.player1.get(i));
      combined.push(this.player2.get(i));      
    }

    //got all the cards, so now clear
    this.player1.clear();
    this.player2.clear();
    
    return combined;
  }

  /**
   * Returns whether the top cards of the two stacks match.
   * That is, determines whether the top card of player 1's stack
   * has the same value (ignoring suit) as the top card of player 2's stack.
   */
  public boolean isMatch() {
    PlayingCard p1 = (PlayingCard) player1.peek();
    PlayingCard p2 = (PlayingCard) player2.peek();
    return (p1.equalsIgnoreSuit(p2));
  }

  /**
   * Returns a String of all the cards in this area.
   * Cards are given in order from the top of the stack (first) down
   * to the bottom of the stack (last).
   * <p>
   * Example:<br>
   * "Player1: 4h 9c 10d Ks<br>
   *  Player2: 10s 2c Kh 5d"
   */
  public String toString() {

    String result = player1name + ": ";
    //get player 1's cards
    for (int i = player1.size() - 1; i >= 0; i--) {
      result += player1.get(i).toString() + " ";
    }
    result += "\n";

    //get player 2's cards
    result += player2name + ": ";
    for (int i = player1.size() - 1; i >= 0; i--) {
      result += player2.get(i).toString() + " ";
    }
    result += "\n";

    return result;
  }

  /**
   * Returns a string of only the top cards of the two decks.
   * If empty, returns "   |   ".  The returned string is always
   * 7 characters long.
   * <p>
   * Examples: "4h | 9c ", "Jok|10c".
   */
  public String toStringTopCardsOnly() {
    if (this.player1.empty()) {
      return "   |   ";
    }else {
      StringBuffer result = new StringBuffer();
      String p1 = ((PlayingCard) this.player1.peek()).toString();
      result.append(p1);
      if (p1.length() < 3) { //must be 2, so add a space
        result.append(' ');
      }
      result.append('|');
      String p2 = ((PlayingCard) this.player2.peek()).toString();
      if (p2.length() < 3) { //must be 2, so add a space first
        result.append(' ');
      }
      result.append(p2);
      return result.toString();
    }
  }


  /**
   * Runs a few example tests, such as creating an area, adding
   * cards, printing it out, and clearing it.
   */
  public static void main(String[] args) {
    MatchingGamePlayingArea area = new MatchingGamePlayingArea();
    area.add(new PlayingCard(4, PlayingCard.HEARTS), 
             new PlayingCard(9, PlayingCard.CLUBS));
    area.add(new PlayingCard(10, PlayingCard.DIAMONDS), 
             new PlayingCard(PlayingCard.KING, PlayingCard.SPADES));

    System.out.println("Area with 4 cards played: ");             
    System.out.println(area.toString());

    System.out.println("Top cards only: ");             
    System.out.println(area.toStringTopCardsOnly());
    System.out.print("Top cards match? ");
    System.out.println(area.isMatch());
    
    System.out.println("\nAdding more cards.");
    area.add(new PlayingCard(8, PlayingCard.DIAMONDS), 
             new PlayingCard(8, PlayingCard.SPADES));

    System.out.println("Area with 6 cards played: ");             
    System.out.println(area.toString());

    System.out.println("Top cards only: ");             
    System.out.println(area.toStringTopCardsOnly());
    System.out.print("Top cards match? ");
    System.out.println(area.isMatch());
    
    System.out.println("\nClearing area.");
    Deck deck = area.clear();
    System.out.println("Area after clear: ");             
    System.out.println(area.toString());

    System.out.println("Top cards only: ");             
    System.out.println(area.toStringTopCardsOnly());
    System.out.println("Deck returned:");
    System.out.println(deck);
  }

}//end class

