/*
 * MyFirst solo Project Spring 2014
 * Matching Card Game
 */

package model;
import imagedata.Image;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observable;

/**
 * This class creates a deck of cards, shuffles it, and contains methods that allows the 
 * game's logic to run correctly.
 * 
 * @author Brian Dennis
 * @version 3-25-2014
 */
public class MatchingGame extends Observable {

    /** this array holds all of the characters that represent the values of the cards. */
    private final List<String> myCardValues;
    
    /** This list holds all of the cards that are created and made into a deck. */
    private final List<Card> myDeck;
    
    /** This List holds the two cards requesting to be compared. */
    private final List<Integer> myTwoCards;
    
    /** An object that holds information on a current matching process, the index and matching 
     * status of the card. */
    private final MatchingStatus myMatchingStatus;
    
    /** this integer keeps track of how many card are left on the playing field. */
    private int myCardsLeft;
    
    /**
     * This constructor initializes the list that holds the cards and calls createDeck() to
     * add the cards to the list.
     * 
     * @param theCardValues the values that will be made into cards
     */
    public MatchingGame(final List<String> theCardValues) {
        
        super();
        myCardValues = theCardValues;
        myDeck = new ArrayList<>();
        myMatchingStatus = new MatchingStatus();
        myTwoCards = new ArrayList<Integer>();
        createDeck();
    }
    
    /**
     * This method instantiates all of the cards in the deck, 52 in all, and then shuffles 
     * them.
     */
    private void createDeck() {
         
        for (final String value : myCardValues) {
            
            myDeck.add(new Heart(value));
            myDeck.add(new Club(value));
            myDeck.add(new Diamond(value));
            myDeck.add(new Spade(value));  
        }
        Collections.shuffle(myDeck);
        myCardsLeft = myDeck.size();
    }
    
    /**
     * This method returns the list that holds all of the cards.
     * 
     * @return the deck of cards
     */
    public List<Card> getDeck() {
        
        return myDeck;
    }
    
    /**
     * This method allows to card objects to be compared for equality by their corresponding 
     * values.
     * 
     * @param theIndex the index requested to be compared
     */
    public void compare(final int theIndex) {
        
        if (!myTwoCards.contains(theIndex)) {
            
            myTwoCards.add(theIndex);
            
            if (myTwoCards.size() == 2) {
                
                if (myDeck.get(myTwoCards.get(0)).getValue().equals(
                                                  myDeck.get(myTwoCards.get(1)).getValue())) {
                    
                    myMatchingStatus.setStatus(true);
                    myMatchingStatus.incrementMatchesMade();
                    myMatchingStatus.decrementMatchesLeft();
                    myCardsLeft -= 2;
                 
                } else {
                    
                    myMatchingStatus.setStatus(false);
                }
                myMatchingStatus.setIndex1(myTwoCards.get(0));
                myMatchingStatus.setIndex2(myTwoCards.get(1));
                myMatchingStatus.incrementTurnsTaken();
                setChanged();
                notifyObservers(myMatchingStatus);
                myTwoCards.clear();
            }
        }
    }
    
    /**
     * returns the object that stores the data necessary for updating the cards.
     * 
     * @return the matching status
     */
    public MatchingStatus getStatus() {
        
        return myMatchingStatus;
    }
    
    /** 
     * this method returns true when there are no more cards left, and therefore the game 
     * is over.
     * 
     * @return if the game is over or not
     */
    public boolean gameIsOver() {
        
        return myCardsLeft <= 0;
    }
    
    /**
     * This method returns a string variation of all of the cards held in the deck.
     * 
     * @return the string built by the StringBuilder
     */
    public String toString() {
        
        final StringBuilder sb = new StringBuilder();
        int countCards = 0;
        
        for (final Card card : myDeck) {
            
            countCards++;
            sb.append(countCards);
            sb.append(". ");
            sb.append(card.toString());
            sb.append('\n');
        }
        
        return sb.toString();
    }
}