package j3deditor.bin.components;

import j3deditor.bin.util.Utilities;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import java.util.ArrayList;

import javax.swing.JPanel;


/**
 * Object that groups multiple <code>SimpleButton</code> objects
 * together into one button.
 * Inner <code>SimpleButton</code> objects are without images, they
 * only provide the functionality.
 *
 * @author Risto Seene
 * 
 * @see SimpleButton
 */
public class ComplexButton extends JPanel implements MouseListener{

	/** specifies that an image will be applied to the "default" state of this button. */
	public static final int NORMAL_IMAGE = 0;
	
	/** specifies that an image will be applied to the "disabled" state of this button. */
	public static final int DISABLED_IMAGE = 1;

	/** list of <code>SimpleButton</code> objects inside this button */
	private ArrayList<SimpleButton> buttons;

	/** list of images: 2 for every <code>SimpleButton</code> */
	private ArrayList<Image> images;


	/** specifies if this button is currently enabled */
	private boolean isEnabled = true;


	/** current background image of this button */
	private Image current;

	/** default background image of this button */
	private Image defaultImg = null;

	/** background image of this button when it's disabled */
	private Image offImg = null;


	/**
	 * Creates an instance of <code>ComplexButton</code>.
	 */
	public ComplexButton(){
		this.buttons = new ArrayList<SimpleButton>();
		this.images = new ArrayList<Image>();

		setOpaque(false);
		setLayout(null);
		addMouseListener(this);
	}


	/**
	 * Applies the given image to the specified state of this button.
	 * Loads the images from this applications JAR file.
	 *
	 * @param fileName
	 *	name of the image file
	 * @param type
	 *	type of the image: NORMAL_IMAGE, DISABLED_IMAGE
	 */
	public void setImage(String fileName, int type){
		if(type == 0){
			defaultImg = Utilities.image.getImage("buttons/" + fileName);
			current = defaultImg;
		} else if(type == 1){
			offImg = Utilities.image.getImage("buttons/" + fileName);
		}
	}
	
	
	 /**
	  * Applies the given image to the specified state of this button.
	  *
	  * @param image
	  *        image that will be applied to this button
	  * @param type
	  *        type of the image: NORMAL_IMAGE, DISABLED_IMAGE
	  */
	public void setImage(Image image, int type){
		if(type == 0){
			defaultImg = image;
			current = defaultImg;
		} else if(type == 1){
			offImg = image;
		}
	}


	/**
	 * Adds new hotspot to this button.
	 * Loads the images from this applications JAR file.
	 *
	 * @param button
	 *	<code>SimpleButton</code> object that acts as hotspot
	 * @param bounds
	 * 	bounds for this hotspot
	 * @param mOver
	 *	mouse over image for this hotspot
	 * @param mDown
	 *	mouse down image for this hotspot
	 */
	public void addHotSpot(SimpleButton button, Rectangle bounds, String mOver, String mDown){
		button.setBounds(bounds);
		add(button);
		buttons.add(button);
		images.add(Utilities.image.getImage("buttons/" + mOver));
		images.add(Utilities.image.getImage("buttons/" + mDown));
		button.addMouseListener(this);
	}
	
	
	 /**
	  * Adds new hotspot to this button.
	  *
	  * @param button
	  *        <code>SimpleButton</code> object that acts as hotspot
	  * @param bounds
	  *        bounds for this hotspot
	  * @param mOver
	  *        mouse over image for this hotspot
	  * @param mDown
	  *        mouse down image for this hotspot
	  */
	public void addHotSpot(SimpleButton button, Rectangle bounds, Image mOver, Image mDown){
	          button.setBounds(bounds);
		add(button);
		buttons.add(button);
		images.add(mOver);
		images.add(mDown);
		button.addMouseListener(this);
	}


	/**
	 * Enables/disables this button.
	 *
	 * @param enable
	 *	if <code>true</code> this button is enabled,
	 *	otherwise disabled
	 */
	public void setEnabled(boolean enable){
		this.isEnabled = enable;

		for(int i = 0; i < buttons.size(); i++){
			buttons.get(i).setEnabled(enable);
		}

		if(!enable && offImg != null){
			current = offImg;
		} else {
			current = defaultImg;
		}

		repaint();
	}


	/**
	 * Paints the background image of this button.
	 * 
	 * @param graphics
	 * 	<code>Graphics</code> object sent by method caller
	 */
	@Override
	protected void paintComponent(Graphics graphics){
		Graphics2D g = (Graphics2D)graphics;
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		super.paintComponent(g);

		g.drawImage(current, 0, 0, this);
	}


	/**
	 * Activates the hotspot in which bounds the mouse was pressed.
	 * 
	 * @param e
	 * 	<code>MouseEvent</code> sent by method caller
	 */
	public void mousePressed(MouseEvent e){
		if(isEnabled){
			activateButton(e.getSource(), 1);
		}
	}


	/**
	 * Restores the default state of this button.
	 * 
	 * @param e
	 *        <code>MouseEvent</code> sent by method caller
	 */
	public void mouseReleased(MouseEvent e){
		if(isEnabled){
			current = defaultImg;
			repaint();
		}

	}


	/**
	 * Not in use.
	 * 
	 * @param e
	 * 	<code>MouseEvent</code> sent by method caller
	 */
	public void mouseClicked(MouseEvent e){
	}


	/**
	 * Activates the hotspot in which bounds the cursor entered.
	 * 
	 * @param e
	 *        <code>MouseEvent</code> sent by method caller
	 */
	public void mouseEntered(MouseEvent e){
		if(isEnabled){
			activateButton(e.getSource(), 0);
		}
	}


	/**
	 * Restores the default state of this button.
	 * 
	 * @param e
	 *        <code>MouseEvent</code> sent by method caller
	 */
	public void mouseExited(MouseEvent e){
		if(isEnabled){
			current = defaultImg;
			repaint();
		}
	}


	/**
	 * Activates the specified hotspot.
	 *
	 * @param button
	 *	<code>SimpleButton</code> to be activated
	 * @param state
	 *	0 - mouse entered,
	 *	1 - mouse clicked
	 */
	private void activateButton(Object button, int state){
		if(button instanceof SimpleButton){
			for(int i = 0; i < buttons.size(); i++){
				if(buttons.get(i) == (SimpleButton)button){
					current = images.get(2 * i + state);
					repaint();
				}
			}
		}
	}

}
