
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Napoleon extends JFrame {

	private Tomb    tomb    = new Tomb() ;
	private Talon   talon   = new Talon() ;
	private Discard discard = new Discard() ;

	private Card emptyCard = new Card() ;

	private Container container = getContentPane() ;
	private JButton label[] = new JButton[9] ;
	private JButton discButton = new JButton() ;
	private JButton moveButton = new JButton("next" ) ;
	private JButton talnButton = new JButton() ;

	private boolean firstMove = true ;

	private Napoleon() {
		super( "Napoleon" ) ;


		container.setLayout( new GridLayout(4,3) );

		for ( int i = 0 ; i < 9 ; i++) {
			label[i] = new JButton() ;
			label[i].setIcon( new ImageIcon("cards/0.png") ) ;
			container.add( label[i] ) ;
		}
		container.add( discButton ) ;
		discButton.setIcon( new ImageIcon("cards/0.png") ) ;
		container.add( moveButton ) ;
		container.add( talnButton ) ;
		talnButton.setIcon( new ImageIcon("cards/deck.png") ) ;

		ButtonHandler handler = new ButtonHandler() ;
		discButton.addActionListener( handler ) ;
		moveButton.addActionListener( handler ) ;
		talnButton.addActionListener( handler ) ;

		setSize( 600, 600 );
		setVisible( true );
	}


	private class ButtonHandler implements ActionListener {
		public void actionPerformed ( ActionEvent e ) {
			if ( e.getSource() == moveButton ) {
				if (firstMove) {
					dealFour() ;
					firstMove = false ;
				} else if ( noMoveFromEdgeToCornerSpot() )
					if ( noMoveFromDiscardToAnySpot() )
						if ( noDealNextCard() ) {
							String result ;
							if ( discard.isEmpty() )
								result = "You won!";
							else
								result = "You lost!" ;
							JOptionPane.showMessageDialog(null,result,"Game over",JOptionPane.PLAIN_MESSAGE) ;
					}
			} else if ( e.getSource() == discButton ) {
				String output = "" ;
				for ( int i = discard.getLength()-1 ; i >=0 ; i-- )
					output += discard.cardAt(i).getValue() + " of " + discard.cardAt(i).getSuit() + "\n" ;
				JScrollPane jOutput = new JScrollPane( new JTextArea(output,10,10) ) ;
				JOptionPane.showMessageDialog(null,jOutput,"Discard Pile",JOptionPane.PLAIN_MESSAGE) ;
			} else if ( e.getSource() == talnButton ) {
				String output = "" ;
				for ( int i = talon.getLength()-1 ; i >=0 ; i-- )
					output += talon.cardAt(i).getValue() + " of " + talon.cardAt(i).getSuit() + "\n" ;
				JScrollPane jOutput = new JScrollPane( new JTextArea(output,10,10) ) ;
				JOptionPane.showMessageDialog(null,jOutput,"Talon",JOptionPane.PLAIN_MESSAGE) ;
			}
		}
	}


	private void dealFour() {
		for ( int i = 5 ; i <= 8 ; i++ ) {
			Card card = talon.popCard() ;
			tomb.set( card, i ) ;
			label[Tomb.getMap(i)].setIcon( new ImageIcon(card.getPNG()) ) ;
		}
	}


	//Tries to make one and only one move from discard to empty tomb spot.  False if successful, true otherwise.
	private boolean noMoveFromDiscardToAnySpot() {
		Card iCard, dCard ;

		if ( discard.isEmpty() ) return true ;

		for ( int i = 1 ; i <= 4 ; i++ )
			if ( isOneMore(discard.topCard(),tomb.get(i)) ) {  //If jCard is null, then isOneMore returns false.
				dCard = discard.popCard() ;
				discButton.setIcon( new ImageIcon(discard.topCard().getPNG()) ) ;
				tomb.set( dCard, i ) ;
				label[Tomb.getMap(i)].setIcon( new ImageIcon(dCard.getPNG()) ) ;
				return false ;
			}

		if ( isOneLess(discard.topCard(),tomb.get(9)) ) {
			dCard = discard.popCard() ;
			discButton.setIcon( new ImageIcon(discard.topCard().getPNG()) ) ;
			tomb.set( dCard, 9 ) ;
			label[Tomb.getMap(9)].setIcon( new ImageIcon(dCard.getPNG()) ) ;
			return false ;
		}
	
		for ( int i = 5 ; i <= 8 ; i++ )
			if ( tomb.isEmpty(i) ) {
				dCard = discard.popCard() ;
				discButton.setIcon( new ImageIcon(discard.topCard().getPNG()) ) ;
				tomb.set( dCard, i ) ;
				label[Tomb.getMap(i)].setIcon( new ImageIcon(dCard.getPNG()) ) ;
				return false ;
			}

		return true ;
	}


	// Tries to make one and only one move from edge spots.  False if successful, true otherwise.
	private boolean noMoveFromEdgeToCornerSpot() {
		Card iCard, jCard ;

		for ( int i = 5 ; i <= 8 ; i++ ) {
			iCard = tomb.get(i) ;

			for ( int j = 1 ; j <= 4 ; j++ ) {
				jCard = tomb.get(j) ;
				if ( isOneMore(iCard,jCard) ) {  //If iCard is null, then isOneMore returns false.
					tomb.set( iCard, j ) ;
					label[Tomb.getMap(j)].setIcon( new ImageIcon(iCard.getPNG()) ) ;
					tomb.set( emptyCard, i ) ;
					label[Tomb.getMap(i)].setIcon( new ImageIcon(emptyCard.getPNG()) ) ;
					return false ;
				}
			}

			jCard = tomb.get(9) ;
			if ( isOneLess(iCard,jCard) ) {
				tomb.set( iCard, 9 ) ;
				label[Tomb.getMap(9)].setIcon( new ImageIcon(iCard.getPNG()) ) ;
				tomb.set( emptyCard, i ) ;
				label[Tomb.getMap(i)].setIcon( new ImageIcon(emptyCard.getPNG()) ) ;
				return false ;
			}
		}

		return true ;
	}


	// Tries to deal one more card to the discard pile.  False if successful, true otherwise.
	private boolean noDealNextCard() {
		if ( talon.isEmpty() )
			return true ;
		else {
			Card card = talon.popCard() ;
			discard.pushCard( card ) ;
			discButton.setIcon( new ImageIcon(card.getPNG()) ) ;
			if (talon.isEmpty() ) talnButton.setIcon( new ImageIcon( "cards/0.png" ) ) ;
			return false ;
		}
	}


	private boolean isOneMore( Card aCard, Card bCard ) {
		String aValue = aCard.getValue() ;
		String bValue = bCard.getValue() ;

		boolean isMore =
			( aValue.equals("seven") && bValue.equals("empty") ) ||
			( aValue.equals("eight") && bValue.equals("seven") ) ||
			( aValue.equals("nine")  && bValue.equals("eight") ) ||
			( aValue.equals("ten")   && bValue.equals("nine")  ) ||
			( aValue.equals("jack")  && bValue.equals("ten")   ) ||
			( aValue.equals("queen") && bValue.equals("jack")  ) ||
			( aValue.equals("king")  && bValue.equals("queen") ) ;

		return isMore ;
	}

	private boolean isOneLess( Card aCard, Card bCard ) {
		String aValue = aCard.getValue() ;
		String bValue = bCard.getValue() ;

		boolean isLess =
			( aValue.equals("ace")   && bValue.equals("two")   ) ||
			( aValue.equals("two")   && bValue.equals("three") ) ||
			( aValue.equals("three") && bValue.equals("four")  ) ||
			( aValue.equals("four")  && bValue.equals("five")  ) ||
			( aValue.equals("five")  && bValue.equals("six")   ) ||
			( aValue.equals("six")   && bValue.equals("ace")   ) ||
			( aValue.equals("six")   && bValue.equals("empty") ) ;

		return isLess ;
	}

	public static void main( String args[] ) {
		Napoleon game = new Napoleon();
		game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
	}

}


