package cnp.ew.displayer;

import java.awt.*;
import cnp.ew.lightweight.*;

public class CpBoxedValueDisplayer extends CpAbstractOrientedValueDisplayer
{
    // Margin between boxes, and margin left and right (or above and below for vertical orientation)
    int boxMargin = 2;

    // Width (or height, for vertical orientation) of boxes
    int boxSize = 6;

    // margin above and below (or left and right for vertical orientation)
    int borderMargin = 2;

    Color boxColor = new Color(0, 0, 128);

    public void setColor(Color color)
    {
        boxColor = color;
    }

    public Color getColor()
    {
        return boxColor;
    }

    public void setBoxSize(int newBoxSize)
    {
        boxSize = newBoxSize;
    }

    public int getBoxSize()
    {
        return boxSize;
    }

    /**
     * Display the object using g in the rectangle defined
     * by x,y with width w and height h.
     */
    public void paintIn(CpLightweightComponent c, Graphics g, int x, int y, int w, int h)
    {
        int numBoxes, boxWidth, boxHeight, increment, startX, startY;

        switch (getOrientation()) {
        case ORIENT_LEFT_TO_RIGHT:
        // boxSize + boxMargin - 1 is for rounding up
            numBoxes = (w - (2 * boxMargin) + (boxSize + boxMargin - 1))  / (boxSize + boxMargin);
            boxWidth = boxSize;
            boxHeight = h - (2 * borderMargin);
            increment = boxSize + boxMargin;
            startX = x + boxMargin;
            startY = y + borderMargin;
            break;
        case ORIENT_RIGHT_TO_LEFT:
            numBoxes = (w - (2 * boxMargin) + (boxSize + boxMargin - 1))  / (boxSize + boxMargin);
            boxWidth = boxSize;
            boxHeight = h - (2 * borderMargin);
            increment = -(boxSize + boxMargin);
            startX = x + w - boxSize - boxMargin;
            startY = y + borderMargin;
            break;
        case ORIENT_TOP_TO_BOTTOM:
            numBoxes = (h - (2 * boxMargin) + (boxSize + boxMargin - 1)) / (boxSize + boxMargin);
            boxWidth = w - (2 * borderMargin);
            boxHeight = boxSize;
            increment = boxSize + boxMargin;
            startX = x + borderMargin;
            startY = y + boxMargin;
            break;
        case ORIENT_BOTTOM_TO_TOP:
            numBoxes = (h - (2 * boxMargin) + (boxSize + boxMargin - 1)) / (boxSize + boxMargin);
            boxWidth = w - (2 * borderMargin);
            boxHeight = boxSize;
            increment = -(boxSize + boxMargin);
            startX = x + borderMargin;
            startY = y + h - boxSize - boxMargin;
            break;
        default:
            throw new IllegalArgumentException("Invalid orientation");
        }

        numBoxes = (int)(numBoxes * getValuePercentage());

        g.setColor(c.getBackground());
        g.fillRect(x, y, w, h);
        if (boxColor != null) {
            g.setColor(boxColor);
        }

        for (int i=0; i < numBoxes; i++) {
            g.fillRect(startX, startY, boxWidth, boxHeight);
            switch (getOrientation()) {
            case ORIENT_LEFT_TO_RIGHT:
                startX += increment;
                boxWidth = Math.min(boxWidth, x + w - boxMargin - startX);
                break;
            case ORIENT_RIGHT_TO_LEFT:
                startX += increment;
                if (startX < x + boxMargin) {
                    boxWidth -= (x + boxMargin - startX);
                    startX = x + boxMargin;
                }
                break;
            case ORIENT_TOP_TO_BOTTOM:
                startY += increment;
                boxHeight = Math.min(boxHeight, y + h - boxMargin - startY);
                break;
            case ORIENT_BOTTOM_TO_TOP:
                startY += increment;
                if (startY < y + boxMargin) {
                    boxHeight -= (y + boxMargin - startY);
                    startY = y + boxMargin;
                }
                break;
            }
        }
    }

    public Dimension preferredSize(CpLightweightComponent c)
    {
        switch (getOrientation()) {
        case ORIENT_LEFT_TO_RIGHT:
        case ORIENT_RIGHT_TO_LEFT:
            return new Dimension((10 * (boxSize + boxMargin)) + (2 * boxMargin), (3 * boxMargin) + boxSize);
        case ORIENT_TOP_TO_BOTTOM:
        case ORIENT_BOTTOM_TO_TOP:
            return new Dimension((2 * boxMargin) + boxSize, (10 * (boxSize + boxMargin)) + (2 * boxMargin));
        default:
            throw new IllegalArgumentException("Invalid orientation");
        }
    }
}

