/*
 * Created on Nov 22, 2004
 *
 * Utilizes Java Power Tools (JPT)
 * http://www.ccs.neu.edu/jpt/
 * 
 */

/**
 *Authored by Brandon Schory
 *
 *With help, inspiration, and code from Richard Rasala, Mike Battista, Ken Eimer, and Matt DeGennaro
 *
 */

import edu.neu.ccs.*;
import edu.neu.ccs.gui.*;
import edu.neu.ccs.util.*;
import java.awt.*;
import javax.swing.*;

public class BlackJack extends DisplayPanel implements JPTConstants{
	
    //Variable Declarations
	static boolean ok;
	static int CardsDealt;
	static Deck d;
	static int[] gamedeck;
	static Dealer dealer;
	static Player player;
	
	/** Establishes all aspects of the initial deal of the cards:
	 * - Sets the initial states of the DealerTotal and PlayerTotal fields
	 * - Deals the first 4 cards, starting with the player
	 * - Pauses the thread for half a second before each card to give the illusion of dealing
	 * - Passes the cards to the appropriate functions to handle them [DealerCards() and PlayerCards()]
	 * - Checks to see if either, or both, players have BlackJack and initializes EndGame3()
	 * - sets the boolean ok to true so that the functoin PlayerCards() knows that a card value of 21 is not BlackJack
	 * */
	protected static void Deal(){
		
	    DealerTotal.setViewState("?");
		
	    JPTUtilities.pauseThread(500);
		player.PlayerCards(d.deck[gamedeck[CardsDealt]]);
		CardsDealt += 1;
		
		JPTUtilities.pauseThread(500);
		dealer.DealerCards(d.deck[gamedeck[CardsDealt]]);
		CardsDealt += 1;
		
		JPTUtilities.pauseThread(500);
		player.PlayerCards(d.deck[gamedeck[CardsDealt]]);
		CardsDealt += 1;
		
		JPTUtilities.pauseThread(500);
		dealer.DealerCards(d.deck[gamedeck[CardsDealt]]);
		CardsDealt += 1;
		
		PlayerTotal.setViewState(player.total + "");

		if(player.total == 21 || dealer.total == 21){
			EndGame1();}
		
		ok = true;
	}
	
	/** Draws a card from the deck*/
	protected static Card DrawCard(){
		Card c = d.deck[gamedeck[CardsDealt]];
		CardsDealt += 1;
		return c;
	}
	
	/** End of game called when either the dealer or player has BlackJack
	 * Shows the Dealer's first card image if there are less than 5 cards
	 * Shows the Dealer's total
	 * Determines which player has BlackJack and set's the appropriate message
	 * If both have BlackJack, displays push message
	 * Disables Hit and Set actions
	 */
	protected static void EndGame1(){
		if(dealer.NumberOfCards < 5){
			DealerCards[0].setPaintable(new ImagePaintable(dealer.DealersFirst.image));
		}
		DealerTotal.setViewState(dealer.total + "");
		if(player.total == 21 && dealer.total == 21){MessageView.setViewState("Push, Nobody Wins.");}
		if(player.total == 21){MessageView.setViewState("Player has BlackJack!");}
		else{MessageView.setViewState("Dealer has BlackJack.");}
		Hit.setEnabled(false);
		Stay.setEnabled(false);
	}
	
	/** End of game called when the player or dealer busts
	 * Shows the Dealer's first card image if there are less than 5 cards
	 * Shows the Dealer's total
	 * Tell which Person busted
	 * Disables Hit and Set actions*/
	protected static void EndGame2(){
		if(dealer.NumberOfCards < 5){
			DealerCards[0].setPaintable(new ImagePaintable(dealer.DealersFirst.image));
		}
		DealerTotal.setViewState(dealer.total + "");
		if(Player.total > 21){
			MessageView.setViewState("Player Busts, Dealer wins.");
		}
		else{
			MessageView.setViewState("Dealer Busts, Player wins!");
		}
		Hit.setEnabled(false);
		Stay.setEnabled(false);
	}
	
	/** Determines the winner, if any
	 * Shows the Dealer's first card image if there are less than 5 cards
	 * Shows the Dealer's total
	 * Sets view to diplay who wins, or if there's a push (tie)
	 * disables Hit and Stay actions
	 */
	protected static void FinalStep(){
		if(dealer.NumberOfCards < 5){
			DealerCards[0].setPaintable(new ImagePaintable(dealer.DealersFirst.image));
		}
		DealerTotal.setViewState(dealer.total + "");
		if(dealer.total > player.total){
			MessageView.setViewState("Dealer Wins.");}
		else if(player.total > dealer.total){MessageView.setViewState("Player Wins!");}
		else{MessageView.setViewState("Push, Nobody Wins.");}	
		Hit.setEnabled(false);
		Stay.setEnabled(false);
	}
	
	/** Construction of the GUI*/
	
	//Variable Declarations	
	JButton hitAction;
	JButton stayAction;
	JButton newAction;
	JButton exitAction;
	JPTFrame frame;
	int width;
	static TextFieldView PlayerTotal;
	static TextFieldView DealerTotal;
	static TextFieldView MessageView;
    JPTFrame Tframe;
    TablePanel dealertilepanel;
    TablePanel playertilepanel;
    TablePanel textpanel;
    TablePanel playerpanel;
    TablePanel dealerpanel;
    TablePanel ButtonPanel;
    TablePanel viewPanel;
    public Color blankgreen = new Color(0, 175, 0);
    public static ImageTile[] PlayerCards;
	public static ImageTile[] DealerCards;
   	InputMap IMap;
	ActionMap AMap;
	
	/** Creates an action for a button that gives the player a new card*/
	protected static SimpleAction Hit =
	    new SimpleAction("Hit") {
	    	public void perform() {
	    	    player.PlayerCards(DrawCard());
            }
        };
     
     /** Creates an action for a button that ends the players turn and initializes DealerAI()*/
     protected static SimpleAction Stay =
    	    new SimpleAction("Stay") {
    	    	public void perform() {
    	    	    dealer.DealerAI();
                }
    	};
    	
    	/** Creates an action for a button that closes the old game and creates a new one*/
    	protected SimpleAction New = 
    		new SimpleAction("New Game") {
    		public void perform() {
    			new BlackJack();
    			frame.dispose();
    		}
    	};
    	
    	/** Creates an action that allows Deal() to be enacted from a threaded action*/
    	protected SimpleAction DealCards = 
    		new SimpleAction("DealCards") {
    		public void perform() {
    		Deal();
    		}
    	};
    	
    	/** Creates the threaded action that deals the cards for a new game*/
    	protected ThreadedAction DealCardsThreaded = 
    		new ThreadedAction(DealCards);
    	
    	/** Binds Keys to actions*/
    	private void bindKey(char key, Action action) {
    		IMap.put(KeyStroke.getKeyStroke(key), String.valueOf(key));
    		AMap.put(String.valueOf(key), action);
    	}
    	
    	/** Binds Keys to actions*/
    	private void bindKey(String key, Action action) {
    		IMap.put(KeyStroke.getKeyStroke(key), key);
    		AMap.put(key, action);
    	}
    	   
    	/** Creates the panels which hold the player and dealer card images and initializes MakeGUI()*/
    	private void GenerateFullGUI(){
    	
		//Create Image Tile Arrays for player and dealer
    	    PlayerCards = new ImageTile[4];
		DealerCards = new ImageTile[4];
		
		/** Creates the blank tiles for the dealer's card images*/
		for(int i = 0; i < 4; i++)
			DealerCards[i] = new ImageTile(null, blankgreen, 71, 96, true);
		
		/** Creates the blank tiles for the player's card images*/
		for(int i = 0; i < 4; i++)
			PlayerCards[i] = new ImageTile(null, blankgreen, 71, 96, true);
		
		/** Creates the panels for the card images*/
		dealertilepanel = new TablePanel(DealerCards, 10, 10, CENTER);
		playertilepanel = new TablePanel(PlayerCards, 10, 10, CENTER);
		
		MakeGUI();
    	}
    
    		/** Builds the GUI*/
	    private void MakeGUI(){
	    	
	    /** Creates the buttons*/
    		hitAction = new JButton(Hit);
    		stayAction = new JButton(Stay);
    		newAction = new JButton(New);
    	    	
    		/** Creates the panel that holds the player's total*/
    	    	playerpanel = 
    	    		new TablePanel(
    	    				new Object[][]{
    	    						{"Player Total", PlayerTotal}
    	    				}, 10, 10, CENTER);
    	    	
    	    	/** Creates the panel that holds the dealer's total*/
    	    	dealerpanel = 
    	    		new TablePanel(
    	    				new Object[][]{
    	    						{"Dealer Total", DealerTotal}
    	    				}, 10, 10, CENTER);
    		
    	    	/** Creates the panel that holds the player's total, dealer's total, and messages*/
    		textpanel = 
    	    		new TablePanel(
    	    				new Object[]{dealerpanel, MessageView, playerpanel}, VERTICAL, 10, 10, CENTER);
    	    	
    		/** Creates the panel that holds the buttons*/
    	    ButtonPanel
			= new TablePanel(new Object[]{ hitAction, stayAction, newAction}, HORIZONTAL, 10, 10, CENTER);
    	   
    	   /** Creates the main panel that holds everything */
    	   viewPanel = 
    	    		new TablePanel(
    	    				new Object[]{dealertilepanel, textpanel, playertilepanel, ButtonPanel}, VERTICAL, 10, 10, CENTER);
    		
    	   /** Creates the Input and Output maps for the key bindings*/
    	   	IMap = viewPanel.getInputMap(JComponent.WHEN_FOCUSED);
    		AMap = viewPanel.getActionMap();
    		
    		/** Binds the keys to the actions, accounts for any state of the shift key*/
    		bindKey('h', Hit);
    		bindKey('H', Hit);
    		bindKey('s', Stay);
    		bindKey('S', Stay);
    		bindKey('n', New);
    		bindKey('N', New);
    		
    		/** Sets the blackground colors for all of the panels and buttons*/
    		dealertilepanel.setBackground(Colors.Green);
    		playertilepanel.setBackground(Colors.Green);
    		playerpanel.setBackground(Colors.Green);
    		dealerpanel.setBackground(Colors.Green);
    		textpanel.setBackground(Colors.Green);
    		ButtonPanel.setBackground(Colors.Green);
    		viewPanel.setBackground(Colors.Green);
    		hitAction.setBackground(Colors.Green);
    		stayAction.setBackground(Colors.Green);
    		newAction.setBackground(Colors.Green);
    		
    		/** Disables ability to type in PlayerTotal, DealerTotal, and MessageView fields*/
    		PlayerTotal.setEditable(false);
    		DealerTotal.setEditable(false);
    		MessageView.setEditable(false);
 	}

  	/** The constructor that makes a new BlackJack game*/
    	public BlackJack() {
    		ok = false;
    		CardsDealt = 0;
    		d = new Deck();
    		gamedeck = d.shuffle();
    		dealer = new Dealer();
    		player = new Player();
    		width = TextFieldView.getSampleWidth("Tie, player wins by default.");
    		PlayerTotal = new TextFieldView();
    		DealerTotal = new TextFieldView();
    		MessageView = new TextFieldView("Welcome to BlackJack!", width);
    		Hit.setEnabled(true);
    		Stay.setEnabled(true);
    		GenerateFullGUI();
    		Halo halo = new Halo(viewPanel, 10, 10);
    		halo.setBackground(Colors.Green);
    		frame = JPTFrame.createQuickJPTFrame("BlackJack", halo);
    		DealCardsThreaded.actionPerformed(null);
    	}
   	   	   	
    	public static void main(String[] args) {
        // LookAndFeelTools.adjustAllDefaultFontSizes(2);
    		new BlackJack();
	}
    	
}