package widget;

import java.awt.AWTEventMulticaster;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.PaintEvent;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;



/**
 * The abstract parent for simple Button objects
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public abstract class AbstractButton extends    Widget
   implements KeyListener, 
MouseListener
{
    protected ActionListener  actionListener;
    protected int             buttonType;


    public static final int   RECTANGLE          = 0;
    public static final int   ROUNDED_RECTANGLE  = 1;

    public static final int   LEFT               = 0;
    public static final int   CENTER             = 1;
    public static final int   RIGHT              = 2;

    public static final int   TOP                = 0;
    //                        CENTER             = 1;
    public static final int   BOTTOM             = 2;

    public static final int   NORMAL             = 0;
    public static final int   TOGGLE             = 1;





    /**
     * Default constructor
     */
    public AbstractButton()
    {
       super();
       actionListener = null;
    }





    /**
     * Add an ActionListener
     *
     * @param listener   The ActionListener to add
     */
    public void addActionListener(ActionListener listener)
    {
       // Add the listener to the existing multicast listener
       actionListener = AWTEventMulticaster.add(actionListener, listener);
    }



    /**
     * Get the action command associated with this Button
     *
     * @return  The action command
     */
    public String getActionCommand()
    {
       AbstractButtonModel      model;

       model = (AbstractButtonModel)(getModel());
       return model.getActionCommand();
    }




    /**
     * Get the button type
     *
     * @return  The button type
     */
    public int getButtonType()
    {
       return buttonType;
    }





    /**
     * Get the default icon Image associated with  the button
     *
     * @return   The Image
     */
    public Image getIcon()
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());
       return view.getIcon();
    }







    /**
     * Get the text on this Button
     *
     * @return  The text
     */
    public String getText()
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());
       return view.getText();
    }





    /**
     * Get the shape of this  Button
     *
     * @return  The shape
     */
    public int getShape()
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());
       return view.getShape();
    }




    /**
     * Handle keyPressed events (required by KeyListener)
     *
     * @param evt   The KeyEvent
     */
    public void keyPressed(KeyEvent evt)
    {
       AbstractButtonView          view;
       Rectangle                   r;
       int                         keyCode;


       view = (AbstractButtonView)(getView());


       keyCode = evt.getKeyCode();
       if ( (keyCode == KeyEvent.VK_SPACE) || 
            (keyCode == KeyEvent.VK_ENTER)    )
       {
          dispatchEvent(new MouseEvent(this,
                                       MouseEvent.MOUSE_PRESSED,
                                       0, 0, 0, 0, 1, false));

          r = getBounds();
          r.x = 0;
          r.y = 0;


          dispatchEvent(new PaintEvent(this,
                                       PaintEvent.PAINT,
                                       r
                           ));
          notifyActionListeners();
          pause(50);

          dispatchEvent(new MouseEvent(this,
                                       MouseEvent.MOUSE_RELEASED,
                                       0, 0, 0, 0, 1, false));
       }
    }





    /**
     * Handle keyReleased events (required by KeyListener)
     *
     * @param evt   The KeyEvent
     */
    public void keyReleased(KeyEvent evt)
    {
       // Ignore
    }





    /**
     * Handle keyTyped events (required by KeyListener)
     *
     * @param evt   The KeyEvent
     */
    public void keyTyped(KeyEvent evt)
    {
       // Ignore
    }







    /**
     * Handle mouseClicked events (required by MouseListener)
     *
     * @param evt   The event
     */
    public void mouseClicked(MouseEvent evt)
    {
       // Everything is handled by the mousePressed and
       // mouseReleased handlers
    }



    /**
     * Handle mouseEntered events (required by MouseListener)
     *
     * @param evt   The event
     */
    public void mouseEntered(MouseEvent evt)
    {
       // Handled by children that care
    }




    /**
     * Handle mouseExited events (required by MouseListener)
     *
     * @param evt   The event
     */
    public void mouseExited(MouseEvent evt)
    {
       // Handled by children that care
    }




    /**
     * Handle mousePressed events (required by MouseListener)
     *
     * @param evt   The event
     */
    public void mousePressed(MouseEvent evt)
    {
       AbstractButtonModel         model;
       AbstractButtonView          view;

       model  = (AbstractButtonModel)(getModel());
       view   = (AbstractButtonView)(getView());

       if (isEnabled())
       {
          requestFocus();

          if (buttonType == TOGGLE)
          {
             if (model.isSelected())
             {
                model.setSelected(false);

             }
             else
             {
                model.setSelected(true);
                view.setViewState(AbstractButtonView.DOWN);
             }
          }
          else
          {
             view.setViewState(AbstractButtonView.DOWN);
          }
       }
    }




    /**
     * Handle mouseReleased events (required by MouseListener)
     *
     * @param evt   The event
     */
    public void mouseReleased(MouseEvent evt)
    {
       AbstractButtonModel         model;
       AbstractButtonView          view;

       model  = (AbstractButtonModel)(getModel());
       view = (AbstractButtonView)(getView());


       if (isEnabled())
       {
          notifyActionListeners();
          if (buttonType == TOGGLE)
          {
             // Ignore
          }
          else
          {
             view.setViewState(AbstractButtonView.UP);
          }
       }
    }





    /**
     * Notify all ActionListener objects of an ActionEvent
     */
    public void notifyActionListeners()
    {
       AbstractButtonModel         model;
       ActionEvent                 ae;


       model = (AbstractButtonModel)(getModel());


       ae = new ActionEvent(this, 
                            ActionEvent.ACTION_PERFORMED, 
                            model.getActionCommand());

       if (actionListener != null)
       {
          actionListener.actionPerformed(ae);
       }
    }




    /**
     * Remove an ActionListener
     *
     * @param listener   The ActionListener to remove
     */
    public void removeActionListener(ActionListener listener)
    {
       // Remove the listener from the existing multicast listener
       actionListener = AWTEventMulticaster.remove(actionListener, listener);
    }




    /**
     * Set the action command associated with this Button
     *
     * @param ac    The action command
     */
    public void setActionCommand(String ac)
    {
       AbstractButtonModel      model;

       model = (AbstractButtonModel)(getModel());
       model.setActionCommand(ac);
    }




    /**
     * Set the button type (NORMAL or TOGGLE)
     *
     * @param type   The type
     */
    public void setButtonType(int type)
    {
       if ((type == NORMAL) || (type == TOGGLE)) buttonType = type;
    }






    /**
     * Set the Font
     *
     * @param font   The Font
     */
    public void setFont(Font font)
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());
       super.setFont(font);
       if (view != null) view.setTextSize(null);
    }




    /**
     * Set the horizontal position of the text
     *
     * @param hpos   The horizontal position (LEFT, CENTER, RIGHT)
     */
    public void setHorizontalTextPosition(int hpos)
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());
       if ((hpos >= LEFT) && (hpos <= CENTER))
       {
          view.setHorizontalTextPosition(hpos);
       }
    }





    /**
     * Set the default icon Image associated with  the button
     *
     * @param image   The Image
     */
    public void setIcon(Image image)
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());

       view.setIcon(image);
    }




    /**
     * Set the model associated with this component/Widget
     *
     * @param model    The model
     */
    public void setModel(AbstractButtonModel model)
    {
       // Nothing to do
    }







    /**
     * Set the shape of this Button
     *
     * @param shape    The shape (RECTANGLE, ROUNDED_RECTANGLE)
     */
    public void setShape(int shape)
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());
       if ((shape >= RECTANGLE) && (shape <= ROUNDED_RECTANGLE))
       {
          view.setShape(shape);
       }
    }






    /**
     * Set the text on this Button
     *
     * @param text    The text
     */
    public void setText(String text)
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());
       view.setText(text);
       view.setTextSize(null);
    }





    /**
     * Setup the event handlers for this Widget
     */
    public void setupEventHandlers()
    {
       super.setupEventHandlers();

       addKeyListener(this);
       addMouseListener(this);
    }






    /**
     * Set the vertical position of the text
     *
     * @param vpos   The vertical position (TOP, CENTER, BOTTOM)
     */
    public void setVerticalTextPosition(int vpos)
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());
       if ((vpos >= TOP) && (vpos <= BOTTOM))
       {
          view.setVerticalTextPosition(vpos);
       }
    }







    /**
     * Set the View for this component/Widget
     *
     * @param view  The view
     */
    public void setView(AbstractButtonView view)
    {
       // Nothing to do
    }





    /**
     * Set the view state (e.g., UP, DOWN)
     *
     * @param  The viewState
     */
    public void setViewState(int viewState)
    {
       AbstractButtonView       view;

       view = (AbstractButtonView)(getView());
       view.setViewState(viewState);
    }



}
