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

/**
 * A class that represents GUI objects for playing the game of Snakes &
 * Ladders.
 * @author Derek Bridge 666 d.bridge@cs.ucc.ie
 */
public class SLGUI
   extends JPanel
{
/* =======================================================================
       CONSTRUCTORS
   =======================================================================
*/
    /**
     * Allocates a new GUI.
     * @param theController the gui's controller
     * @param theWidth the board width (num of cols)
     * @param theHeight the board height (num of rows)
     * @param theStart the starting square
     */
    public SLGUI(SLController theController,
        int theWidth, int theHeight, Square theStart)
    {   controller = theController;
        setLayout(new BorderLayout());
        add(createBoardPanel(theWidth, theHeight, theStart), 
            BorderLayout.CENTER);
        add(createControlPanel(), BorderLayout.SOUTH);
    }

/* =======================================================================
       PUBLIC INTERFACE
   =======================================================================
*/

/* --Public constants-------------------------------------------------- */

    /**
     * The text on the dice button.
     */
    public static final String DICE = "DICE";

    /**
     * The text on the new button.
     */
    public static final String NEW = "NEW GAME";

/* --Setters----------------------------------------------------------- */

    /**
     * Enables the GUI for user input.
     */
    public void enable()
    {   diceBtn.setEnabled(true);
    }

    /**
     * Disables the GUI for user input.
     */
    public void disable()
    {   diceBtn.setEnabled(false);
    }

    /**
     * Displays some text after the user has rolled the dice and
     * before the computer rolls.
     * @param theRoll the user's throw
     * @param theInitialNum the user's previous square
     * @param theFinalNum the user's new square
     * @param userHasWon whether the user has won
     */
    public void showUserOutcome(int theRoll, int theInitialNum,
        int theFinalNum, boolean userHasWon)
    {   msg1Lbl.setText("You rolled a " + theRoll + 
           "! This takes you from square " + theInitialNum +
           " to square " + theFinalNum + ".");
        msg2Lbl.setText(
           (userHasWon ? "You have won! Well done!" :
               "It's my turn. Please click on the dice to roll for me."));
        repaint();
    }

    /**
     * Displays some text after the computer has rolled the dice and
     * before the user rolls.
     * @param theRoll the computer's throw
     * @param theInitialNum the computer's previous square
     * @param theFinalNum the computer's new square
     * @param computerHasWon whether the computer has won
     */
    public void showComputerOutcome(int theRoll, int theInitialNum,
        int theFinalNum, boolean computerHasWon)
    {   msg1Lbl.setText("I rolled a " + theRoll + 
           "! I moved from square " + theInitialNum +
           " to square " + theFinalNum + ".");
        msg2Lbl.setText(
           (computerHasWon ? "I win! You played well. Thanks!" :
           "It's your turn. Click on the dice to roll."));
        repaint();
    }

    /**
     * Displays some text for the start of a new game.
     */
    public void showGameStart()
    {   msg1Lbl.setText("You can start. Click on the dice to roll.");
        msg2Lbl.setText("   ");
        repaint();
    }

/* =======================================================================
       HELPER METHODS
   =======================================================================
*/

    /**
     * Creates a panel containing the board.
     * @param theWidth the board width (num of cols)
     * @param theHeight the board height (num of rows)
     * @param theStart the starting square
     */
    private JPanel createBoardPanel(int theWidth, int theHeight,
        Square theStart)
    {   JPanel p = new JPanel();
        p.setBackground(Color.black);
        GridBagLayout gbl = new GridBagLayout();
        GridBagConstraints gbc = new GridBagConstraints();
        p.setLayout(gbl);
        gbc.fill = GridBagConstraints.BOTH;
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.insets = new Insets(2, 2, 2, 2);
        int i = theHeight - 1;
        int j = 0;
        boolean leftToRight = true;
        Square current = theStart;
        Color currentColour = Color.yellow;
        do
        {   SLSquareGUI squareGUI = new SLSquareGUI(current);
            squareGUI.setBackground(currentColour);
            if (currentColour.equals(Color.yellow))
            {   currentColour = Color.pink;
            }
            else
            {   currentColour = Color.yellow;
            }
            addComp(squareGUI, p, gbl, gbc, i, j, 1, 1, 1, 1);
            current = current.getNext();
            if (leftToRight)
            {   if (j == theWidth - 1)
                {   i--;
                    leftToRight = false;
                }
                else
                {   j++;
                }
            }
            else // right to left
            {   if (j == 0)
                {   i--;
                    leftToRight = true;
                }
                else
                {   j--;
                }
            }
        } while (current != null);
        return p;
    }

    /**
     * Creates a panel containing buttons for running the game.
     * @return the panel
     */
    private JPanel createControlPanel()
    {   JPanel p = new JPanel();
        p.setBackground(Color.white);
        GridBagLayout gbl = new GridBagLayout();
        GridBagConstraints gbc = new GridBagConstraints();
        p.setLayout(gbl);
        gbc.fill = GridBagConstraints.NONE;
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.insets = new Insets(10, 10, 10, 10);
        diceBtn = new JButton(DICE);
        diceBtn.setEnabled(false);
        diceBtn.setBackground(Color.magenta);
        diceBtn.setForeground(Color.white);
        diceBtn.addActionListener(controller);
        addComp(diceBtn, p, gbl, gbc, 0, 0, 1, 1, 1, 1);
        newBtn = new JButton(NEW);
        newBtn.setBackground(Color.cyan);
        newBtn.setForeground(Color.white);
        newBtn.addActionListener(controller);
        addComp(newBtn, p, gbl, gbc, 0, 1, 1, 1, 1, 1);
        msg1Lbl = new JLabel("Click on the New Game button to begin.");
        addComp(msg1Lbl, p, gbl, gbc, 1, 0, 1, 2, 1, 1);
        msg2Lbl = new JLabel("   ");
        addComp(msg2Lbl, p, gbl, gbc, 2, 0, 1, 2, 1, 1);
        return p;
    }

   /**
    * Utility method for adding components to a container using
    * grid bag layout constraints.
    *
    * @param comp the component being added.
    * @param cont the container we're adding to.
    * @param gbl the layout manager.
    * @param gbc the layout manager's constraints object.
    * @param row the row we're positioning in.
    * @param col the column we're positioning in.
    * @param numRows the number of rows this component is to span.
    * @param numCols the number of columns this component is to span.
    * @param weightx horizontal resize weight.
    * @param weighty vertical resize weight.
    */
   private void addComp(Component comp, Container cont, GridBagLayout gbl,
      GridBagConstraints gbc, int row, int col, int numRows, int numCols,
      double weightx, double weighty)
   {  gbc.gridx = col;
      gbc.gridy = row;
      gbc.gridwidth = numCols;
      gbc.gridheight = numRows;
      gbc.weightx = weightx;
      gbc.weighty = weighty;

      cont.add(comp, gbc);
   }

/* =======================================================================
       INSTANCE VARIABLES & CLASS VARIABLES
   =======================================================================
*/
    /**
     * The controller
     */
    private SLController controller;

    /**
     * The label for displaying part of what's going on.
     */
    private JLabel msg1Lbl;

    /**
     * The label for displaying the rest of what's going on.
     */
    private JLabel msg2Lbl;

    /**
     * The button for rolling the dice.
     */
    private JButton diceBtn;

    /**
     * The button for starting a new game
     */
    private JButton newBtn;
}
