import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.*;
import java.awt.Image;
import javax.swing.*;



/**
 * n-puzzle with sliding images
 * @author Owen Astrachan
 */
public class PuzzleApplet extends JApplet implements PuzzleView
{
    public void init()
    {
	myControl = new PuzzleController();
	PuzzleModel pmodel = new PuzzleModel(myControl, getNumDivisions());
	doInitialize(pmodel, getImageName());
    }

    /**
     * Create a gui with a model and an image (image optional)
     * @param imageSource is null or the url/file for an image
     * @param model is the model for this view
     */
    public void doInitialize(PuzzleModel model, String imageSource)
    {
	JPanel panel = new JPanel(new BorderLayout());
	
	myControl.addView(this);
	myModel = model;
	myUndo = new JButton("undo");
	myUndo.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e)
		{
		    myControl.undoMove();		    
		}
	    });
	setEnabledUndo(false);
	
	myText = new JTextField(20);
	myButtonPanel = new ButtonPanel(myModel.getSize(), imageSource);
	panel.add(myButtonPanel, BorderLayout.CENTER);
	panel.add(myText,        BorderLayout.SOUTH);
	panel.add(myUndo,        BorderLayout.NORTH);
	
	setContentPane(panel);
	setVisible(true);
    }
    
    public void showText(String text)
    {
	myText.setText(text);
    }
    
    public void setEnabledUndo(boolean value)
    {
	myUndo.setEnabled(value);
    }
    
    public void showGrid(int[] list)
    {
	myButtonPanel.setGrid(list);	
    }
    
    private String getImageName ()
    {
	// allow user to give puzzle image in HTML file
	String puzzleName = getParameter("image");
	if (puzzleName == null) {
	    puzzleName = OUR_DEFAULT_IMAGE;
	}
	return puzzleName;
    }
    
    private int getNumDivisions ()
    {	
	// allow user to give puzzle image in HTML file
	int gridSize = 2;
	try {
	    gridSize = Integer.parseInt(getParameter("divisions"));
	}
	catch (Exception e) {
	    gridSize = OUR_DEFAULT_GRID;
	}
	return gridSize;
    }

    
    private PuzzleController myControl;
    private PuzzleModel myModel;
    private JTextField  myText;
    private ButtonPanel myButtonPanel;
    private JButton     myUndo;
    
    private static final int OUR_WIDTH  = 500;
    private static final int OUR_HEIGHT = 500;

    private static final String OUR_DEFAULT_IMAGE = "ola.gif";
    private static final int    OUR_DEFAULT_GRID  = 5;
    

    class ButtonPanel extends JPanel
    {
	private JButton myButtons[];

	/**
	 * Create a button panel consisting of nButtons per side
	 * of a square (total # buttons is nButtons*nButtons) using
	 * the designated imageSource (if not null). 
	 * @param nButtons is the number of buttons PER SIDE
	 * @param imageSource is the source of the image for this panel
	 */
	
	ButtonPanel(int nButtons, String imageSource)
	{
	    // construct superclass and make button array
	    super(new GridLayout(nButtons,nButtons));
	    myButtons = new JButton[nButtons*nButtons];

	    // load the image if one is specified
	    Image image = null;
	    if (imageSource != null) {
		image = ImageFactory.getImage(this, imageSource);
	    }

	    // make listeners for buttons in panel
	    // first one to show text in this GUI
	    ActionListener textDisplayer = new ActionListener(){
		    public void actionPerformed(ActionEvent e)
		    {
			showText(e.getActionCommand());
		    }
		};

	    // make listener to do the move chosen by user
	    ActionListener moveMaker = new ActionListener(){
		    public void actionPerformed(ActionEvent e)
		    {
			int val = Integer.parseInt(e.getActionCommand());
			myControl.makeMove(new PuzzleMove(val));
		    }
		};
	    
	    makeButtons(image,textDisplayer,moveMaker);
	}

	/**
	 * Makes the buttons for this GUI/view. The number
	 * of buttons is determined my the size of the array
	 * myButtons. This helper function takes some of
	 * the busy work out of the ButtonPanel constructor.
	 */
	private void makeButtons(Image image,
				 ActionListener textDisplayer,
				 ActionListener moveMaker)
	{
	    for(int k=0; k < myButtons.length; k++) {
		
		String label = ""+k;
		String iLabel = label;
		if (k == myButtons.length-1) {
		    iLabel = PuzzleConsts.BLANK;
		}
		Icon icon;
		if (image == null) {
		    icon = new PlainPuzzleIcon(iLabel,
					       myControl.getModelSize());
		}
		else {
		    icon = 
			new ImagePuzzleIcon(image,
					    iLabel,
					    myControl.getModelSize());
		}
		// create button with icon
		myButtons[k] = new JButton(icon);
		myButtons[k].setActionCommand(label);
		myButtons[k].addActionListener(textDisplayer);
		myButtons[k].addActionListener(moveMaker);

		add(myButtons[k]);
	    }
	}

	/**
	 * Set all the buttons by re-displaying them all
	 * in the right order. First we remove all the components
	 * in this panel (that's the buttons). Then we add the
	 * buttons to this panel in the right order based on what
	 * the ordering of the buttons in the model is.
	 * Finally, we revalidate so the buttons are shown (GUI
	 * will redraw as a result of the revalidate).
	 */	
	public void setGrid(int list[])
	{
	    removeAll();
	    for(int k=0; k < list.length; k++) {
		add(myButtons[list[k]]);
	    }
	    revalidate();
	}

    }

}
