package cnp.ew.button;

import cnp.ew.displayer.*;
import cnp.ew.converter.*;
import cnp.ew.layout.*;
import java.awt.*;
import java.util.*;
import cnp.ew.text.*;
import cnp.ew.misc.*;
import cnp.ew.util.*;

public class CpLabeledImageButtonLc extends CpButtonLc
{
    public static final int IMAGE_IN=0;
    public static final int IMAGE_OUT=1;

    public static final int LABEL_LEFT=CpLabeledLayout.LABEL_LEFT;
    public static final int LABEL_RIGHT=CpLabeledLayout.LABEL_RIGHT;
    public static final int LABEL_TOP=CpLabeledLayout.LABEL_TOP;
    public static final int LABEL_BOTTOM=CpLabeledLayout.LABEL_BOTTOM;

    Object labelObject;
    CpToStringConverter converter;
    int labelOrientation=LABEL_BOTTOM;
    CpReadOnlyTextAreaLc labelLc;
    CpButtonImageLc imageLc;
    boolean shouldShiftWhenPressed=true;
    Color fillColor = Color.lightGray;


    public CpLabeledImageButtonLc()
    {
        if (shouldHaveBorder()) {
            setHasBorder(true);
        }
        CpLabeledLayout newLayout = new CpLabeledLayout();
        newLayout.setOrientation(labelOrientation);
        setLayout(newLayout);
    }

    public CpLabeledImageButtonLc(Object labelOrImageObject)
    {
        this();
        if (labelOrImageObject instanceof Image) {
            setImage((Image)labelOrImageObject);
        } else {
            setLabel(labelOrImageObject);
        }
    }

    public CpLabeledImageButtonLc(Object labelObject, Image image)
    {
        this();
        setImage(image);
        setLabel(labelObject);
    }

	public Object getCopy()
	{
	    // Fix
	    CpLabeledImageButtonLc copy = new CpLabeledImageButtonLc(labelObject);
	    copy.resize(size());
	    copy.setBackground(getBackground());
	    copy.setFont(getFont());
	    copy.setForeground(getForeground());
	    return copy;
	}


    public void setLabel(Object newLabelObject)
    {
        converter = CpDefaultToStringConverter.converterFor(newLabelObject);
        labelObject = newLabelObject;
        if (labelLc == null) {
            labelLc = new CpReadOnlyTextAreaLc();
            labelLc.setHorizontalAlignment(CpAlignable.ALIGN_CENTER);
            labelLc.setVerticalAlignment(CpAlignable.ALIGN_CENTER);
            labelLc.setSelectionExpansion(2);
            add(labelLc);
            ((CpLabeledLayout)getLayout()).setLabel(labelLc);
        }
        reconfigureLabel();
    }

    public Object getLabel()
    {
        return labelObject;
    }

    public void setImage(Image image)
    {
        if (imageLc == null) {
            createImageLc();
        }
        imageLc.notPressedOffImage = image;
        redisplayButton();
    }

    public void setImage(Image image, int imageType)
    {
        if (imageLc == null) {
            createImageLc();
        }

        basicSetImage(image, imageType);
        redisplayButton();
    }


    public void setLabelOrientation(int newOrientation)
    {
        labelOrientation = newOrientation;
        enableDamageRepair(false);
        ((CpLabeledLayout)getLayout()).setOrientation(labelOrientation);
        updateLabelAlignment();
        layout();
        enableDamageRepair(true);
        repaint();
    }

    void createImageLc()
    {
        imageLc = new CpButtonImageLc();
        imageLc.shouldShiftImage = shouldShiftWhenPressed;
        add(imageLc);
        ((CpLabeledLayout)getLayout()).setLabelee(imageLc);
    }

    public int getLabelOrientation()
    {
        return labelOrientation;
    }

    void basicSetImage(Image image, int imageType)
    {
        switch (imageType) {
        case IMAGE_IN:
            imageLc.pressedOffImage = image;
            break;
        case IMAGE_OUT:
            imageLc.notPressedOffImage = image;
            break;
        default:
            throw new IllegalArgumentException("Invalid image type");
        }
    }

    /**
     * This message is sent just before the button is redrawn as a result
     * of a change in visible state. Drawing is automatically disabled during this method.
     */
    void reconfigureImage()
    {
        if (isDisabled()) {
            imageLc.currentState = CpButtonImageLc.STATE_DISABLED_OFF;
        } else if (visiblyPressedIn()) {
            imageLc.currentState = CpButtonImageLc.STATE_PRESSED;
        } else {
            imageLc.currentState = CpButtonImageLc.STATE_NOT_PRESSED;
        }
    }

    void reconfigureLabel()
    {
        labelLc.setText(converter.convert(labelObject));
        labelLc.setShouldDisplayDisabled(isDisabled());
        if (visiblyPressedIn() && shouldShiftWhenPressed) {
            labelLc.setBorderMargin(new Insets(2, 2, -2, -2));
        } else {
            labelLc.setBorderMargin(new Insets(0, 0, 0, 0));
        }
    }


    boolean shouldHaveBorder()
    {
        return true;
    }

    void updateLabelAlignment()
    {
        if (labelLc == null) return;

        switch (labelOrientation) {
        case LABEL_LEFT:
            labelLc.setHorizontalAlignment(CpAlignable.ALIGN_RIGHT);
            break;
        case LABEL_RIGHT:
            labelLc.setHorizontalAlignment(CpAlignable.ALIGN_LEFT);
            break;
        case LABEL_TOP:
        case LABEL_BOTTOM:
            labelLc.setHorizontalAlignment(CpAlignable.ALIGN_CENTER);
            break;
        default:
            throw new IllegalArgumentException("Invalid label orientation");
        }

    }

    public void paint(Graphics g, Rectangle clipRect)
    {
        Rectangle boundingBox = bounds();
        g.setColor(getFillColor());
        g.fillRect(0, 0, boundingBox.width, boundingBox.height);
    }

    void reconfigure()
    {
        if (imageLc != null) {
            reconfigureImage();
        }
        if (labelLc != null) {
            reconfigureLabel();
        }
    }

    public Dimension preferredSize()
    {
        Dimension preferredSize = super.preferredSize();
        if (labelLc != null && shouldShiftWhenPressed) {
            // TBD: Find out why this needs to be 4 rather than 2. (has somethign to do with focus rects)
            preferredSize.width += 4; //2;
            preferredSize.height += 4; //2;
        }
        return preferredSize;
    }

    public void setShouldShiftWhenPressed(boolean shouldShiftWhenPressed)
    {
        this.shouldShiftWhenPressed = shouldShiftWhenPressed;
        if (imageLc != null) {
            imageLc.shouldShiftImage = shouldShiftWhenPressed;
        }
    }

    Color getFillColor()
    {
        if (fillColor == null) {
            return getBackground();
        } else {
            return fillColor;
        }
    }

    void setFillColor(Color aColor)
    {
        fillColor = aColor;
    }

    public boolean gotFocus()
    {
        if (labelLc != null) {
            labelLc.setShowFocus(true);
        } else {
            imageLc.setShowFocus(true);
        }
        return super.gotFocus();
    }

    public boolean lostFocus()
    {
        if (labelLc != null) {
            labelLc.setShowFocus(false);
        } else {
            imageLc.setShowFocus(false);
        }
        return super.lostFocus();
    }

}

