package cnp.ew.displayer;

import java.awt.*;
import cnp.ew.image.*;
import cnp.ew.lightweight.*;
import cnp.ew.util.*;
import java.util.*;

public class CpImageDisplayer implements CpModelDisplayable, CpAlignable
{
    Image image, grayedImage;
    int verticalAlignment=ALIGN_TOP;
    int horizontalAlignment=ALIGN_LEFT;
    Color backColor;
    boolean shouldDisplayDisabled=false;
    boolean displayScaled=false;

    // This is a hack solution to the problem of images not appearing the first time if they're scaled.
    Vector displayedDimensions = new Vector(3);

    public void setModel(Object o)
    {
        setImage((Image)o);
    }

    public Object getModel()
    {
        return getImage();
    }

    public void setImage(Image newImage)
    {
        image = newImage;
    }

    public void setShouldDisplayDisabled(boolean newShouldDisplayDisabled)
    {
        shouldDisplayDisabled = newShouldDisplayDisabled;
    }

    public boolean getShouldDisplayDisabled()
    {
        return shouldDisplayDisabled;
    }

    public void setDisplayScaled(boolean displayScaled)
    {
        this.displayScaled = displayScaled;
    }

    public boolean getDisplayScaled()
    {
        return displayScaled;
    }

    public void setBackColor(Color newColor)
    {
        backColor = newColor;
    }

    public Color getBackColor()
    {
        return backColor;
    }

    public void setVerticalAlignment(int newVerticalAlignment)
    {
        verticalAlignment = newVerticalAlignment;
    }

    public int getVerticalAlignment()
    {
        return verticalAlignment;
    }

    public void setHorizontalAlignment(int newHorizontalAlignment)
    {
        horizontalAlignment = newHorizontalAlignment;
    }

    public int getHorizontalAlignment()
    {
        return horizontalAlignment;
    }

    public void setImageUrl(CpLightweightComponent c, String urlString)
    {
        image = CpToolkit.getImage(urlString);
    }


    public Image getImage()
    {
        return image;
    }

    public void paintIn(CpLightweightComponent c, Graphics g, Rectangle r)
    {
        paintIn(c, g, r.x, r.y, r.width, r.height);
    }

    public void paintIn(CpLightweightComponent c, Graphics g, int x, int y, int w, int h)
    {
        int startX, startY, width, height;

        if (image == null) {
            g.setColor(Color.green);
            g.fillRect(x, y, w, h);
            return;
        }
        if (displayScaled) {
            startX = x;
            startY = y;
            width = w;
            height = h;
        } else {
            height = image.getHeight(CpToolkit.defaultComponent());
            width = image.getWidth(CpToolkit.defaultComponent());
            switch (horizontalAlignment) {
            case ALIGN_LEFT:
                startX = x;
                break;
            case ALIGN_CENTER:
                startX = x + ((w - width) / 2);
                break;
            case ALIGN_RIGHT:
                startX = x + w - width;
                break;
            default:
                throw new IllegalArgumentException("Invalid horizontal alignment");
            }

            switch (verticalAlignment) {
            case ALIGN_TOP:
                startY = y;
                break;
            case ALIGN_CENTER:
                startY = y + ((h - height) / 2);
                break;
            case ALIGN_BOTTOM:
                startY = y + h - height;
                break;
            default:
                throw new IllegalArgumentException("Invalid vertical alignment");
            }
        }

        if (backColor != null) {
            Color savedColor = g.getColor();
            g.setColor(backColor);
            g.fillRect(x, y, w, h);
            g.setColor(savedColor);
        }

        Image tempImage;
        if (shouldDisplayDisabled) {
            if (grayedImage == null) {
                grayedImage = CpImageGetter.getDefault().getGrayedImage(CpToolkit.defaultComponent(), image);
            }
            tempImage = grayedImage;
        } else {
            tempImage = image;
        }

        if (displayScaled) {
            g.drawImage(tempImage, startX, startY, width, height, CpToolkit.defaultComponent());
            // Hack to get around drawImage returning immediately, and not having the image rendered.
            if (!hasDisplayed(width, height)) {
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                }

                g.drawImage(tempImage, startX, startY, width, height, CpToolkit.defaultComponent());
            }
        } else {
            g.drawImage(tempImage, startX, startY, CpToolkit.defaultComponent());
        }
    }

    boolean hasDisplayed(int width, int height)
    {
        for (int i=0; i < displayedDimensions.size(); i++) {
            Dimension dim = (Dimension)displayedDimensions.elementAt(i);
            if (dim.width == width && dim.height == height) {
                return true;
            }
        }
        displayedDimensions.addElement(new Dimension(width, height));
        return false;
    }


    public Dimension preferredSize(CpLightweightComponent c)
    {
        if (image == null) {
            return new Dimension(0,0);
        }
        return new Dimension(image.getWidth(CpToolkit.defaultComponent()), image.getHeight(CpToolkit.defaultComponent()));
    }
}

