package sim.util;

import java.awt.*;
import java.awt.image.FilteredImageSource;
import java.awt.event.*;

import gjt.image.BlackAndWhiteFilter;
import gjt.Util;

import sim.MainWindow;
import sim.GuiFileLink;

public class SimButton extends Component
{
    private boolean isDisabled = false;
	private boolean armed = false;
	private boolean focused = false;
	private boolean raised = true;
	
	private Color normalBack;
	
    private Dimension prefSize = new Dimension(0,0);
	
    private Image image, disabledImage;
	
	private SimButtonListener listener = null;
	private ActionListener actionListener = null;
	
	public SimButton(Image image, String help, long wait)
	{
		super();
		
		this.image = image;
		
		BlackAndWhiteFilter bwFilter = new BlackAndWhiteFilter();
        FilteredImageSource fis = new FilteredImageSource(this.image.getSource(), bwFilter);
        Util.waitForImage(this, this.disabledImage = MainWindow.MAIN_WINDOW.createImage(fis));
		this.normalBack = MainWindow.BACKGROUND;
		
		this.addMouseListener(new BubbleListener(this, help, wait));
	}
	
	public SimButton(String fileName, String help, long wait)
	{
		this(GuiFileLink.getImage(fileName), help, wait);
	}
	
	
	public void update(Graphics g)
	{
		super.paint(g);
	}
	
	public void activate()
	{
		this.listener.activate(this);
	}
	
	public void arm()
	{
		this.listener.arm(this);
	}
	
	public void disarm()
	{
		this.listener.disarm(this);
	}
	
	public void setArmed(boolean armed)
	{
		this.armed = armed;
	}
	
	public boolean isArmed()
	{
		return armed;
	}
	
	public void processActionEvent()
	{
		if(actionListener != null)
		{
			this.actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "ImageButton Action"));
		}
		
		this.setArmed(false);
	}
	
	public void setListener(SimButtonListener l)
	{
		if(this.listener != null)
		{
			this.removeMouseListener(listener);
			this.removeMouseMotionListener(listener);
		}
		
		this.listener = l;
		this.actionListener = l;
		this.addMouseListener(this.listener);
		this.addMouseMotionListener(this.listener);
	}
	
    public Dimension getMinimumSize()
	{ 
		return prefSize;
    }
	
    public Dimension getPreferredSize()
	{ 
        this.prefSize.width  = this.image.getWidth (this) + 2;
        this.prefSize.height = this.image.getHeight(this) + 2;
		
        return this.prefSize;  
	}
	
    public boolean isRaised()
	{ 
		return this.raised;    
	}
	
	public void setRaised(boolean update)
	{
		this.raised = true;
		if(this.isVisible() && update)
			this.repaint();
	}
	
	public void setRaised()
	{
		this.setRaised(true);
	}
	
    public boolean isInset()
	{ 
		return !this.raised;
	}
	
	public void setInset(boolean update)
	{
		this.raised = false;
		if(this.isVisible() && update)
			this.repaint();
	}
	
	public void setInset()
	{
		this.setInset(true);
	}
	
    public void setEnabled(boolean enable)
	{ 
		super.setEnabled(enable);
		
		this.isDisabled = !enable;
		
		if(this.isVisible()) 
			this.repaint();
	}
	
    public void setSize(int w, int h)
	{ 
		this.setBounds(this.getLocation().x, this.getLocation().y, w, h);
	}
	
    public void setBounds(int x, int y, int w, int h)
	{ 
		super.setBounds(x ,y ,w, h);
	}
	
    public void paint(Graphics g)
	{
		Dimension size = this.getSize();
		Color brush = this.normalBack.brighter();
			
		if(!this.focused && !this.raised)
			g.setColor(new Color((this.normalBack.getRed() + brush.getRed()) / 2, (this.normalBack.getBlue() + brush.getBlue()) / 2, (this.normalBack.getGreen() + brush.getGreen()) / 2));
		else
			g.setColor(this.normalBack);
		
		g.fillRect(0, 0, size.width, size.height);
		
		if(this.focused && this.raised)
		{
			g.setColor(brush);
			g.drawLine(0, 0, size.width, 0);
			g.drawLine(0, 0, 0, size.height);
			
			g.setColor(this.normalBack.darker());
			g.drawLine(0, size.height - 1, size.width, size.height - 1);
			g.drawLine(size.width - 1, 0, size.width - 1, size.height);
		}
		else if(!this.raised)
		{
			g.setColor(this.normalBack.darker());
			g.drawLine(0, 0, size.width, 0);
			g.drawLine(0, 0, 0, size.height);
			
			g.setColor(brush);
			g.drawLine(0, size.height - 1, size.width, size.height - 1);
			g.drawLine(size.width - 1, 0, size.width - 1, size.height);
		}
		
		Image image = this.isEnabled() ? this.image : this.disabledImage;
		int offset = this.raised ? 1 : 2;
		Dimension pSize = this.getPreferredSize();
        g.drawImage(image, (size.width - pSize.width) / 2 + offset, (size.height - pSize.height) / 2 + offset, this);
    }
	
	public void paintRaised()
	{
		this.raised = true;
		this.repaint();
	}
	
	public void paintInset()
	{
		this.raised = false;
		this.repaint();
	}
	
	public void paintEntered()
	{
		this.focused = true;
		
		if(this.raised)
		{
			Dimension size = this.getSize();
			Graphics g = this.getGraphics();
			
			g.setColor(this.normalBack.brighter());
			g.drawLine(0, 0, size.width, 0);
			g.drawLine(0, 0, 0, size.height);
			
			g.setColor(this.normalBack.darker());
			g.drawLine(0, size.height - 1, size.width, size.height - 1);
			g.drawLine(size.width - 1, 0, size.width - 1, size.height);
			
			g.dispose();
		}
		else
			this.repaint();
	}
	
	public void paintExited()
	{
		this.focused = false;
		
		if(this.raised)
		{
			Dimension size = this.getSize();
			Graphics g = this.getGraphics();
			
			g.setColor(this.normalBack);
			g.drawLine(0, 0, size.width, 0);
			g.drawLine(0, 0, 0, size.height);
			
			g.drawLine(0, size.height - 1, size.width, size.height - 1);
			g.drawLine(size.width - 1, 0, size.width - 1, size.height);
			
			g.dispose();
		}
		else
			this.repaint();
	}
}