package cnp.ew.charts;

import java.awt.*;
import cnp.ew.displayer.*;
import cnp.ew.lightweight.*;

public class Cp3DBarValueDisplayer extends CpAbstractOrientedDisplayer
{
    Color lineColor=Color.black;
    Color faceColor= Color.blue;
    Color horizontalSideColor=faceColor.darker();
    Color verticalSideColor=horizontalSideColor.darker();
    boolean shouldDrawEnd=true;
    Point slope;
    double value=50.0;
    CpValueAxisModel axisModel;

    /*
     * Draw a 3D ('barred') rectangle within the bounds of the rect defined by x, y, w, and h.
     */

     // TBD: Move this to a utilities class
    public static void drawBarRect(Graphics g, Color lineColor, Color faceColor, Color horizontalSideColor, Color verticalSideColor, int x, int y, int w, int h, Point slope, boolean drawHorzSide, boolean drawVertSide, boolean drawFace)
    {
        Polygon polygon;
        int horzX1, horzX2, horzX3, horzX4, horzY1, horzY2, horzY3, horzY4;
        int vertX1, vertX2, vertX3, vertX4, vertY1, vertY2, vertY3, vertY4;
        int faceTop, faceLeft;
        int slopeX, slopeY;



    // First, establish the orientation of the rect.  Negative x slope means the face is to the right
    // of the angled side; negative y slope means the face is above the angled bottom/top.


        slopeX = Math.abs(slope.x);
        slopeY = Math.abs(slope.y);
        if (slope.y > 0) {
            faceTop = y + slopeY;
            if (slope.x > 0) {
                faceLeft = x;
                horzX1 = x;
                horzY1 = y + slopeY;
                horzX2 = x + slopeX;
                horzY2 = y;
                horzX3 = x + w - 1;
                horzY3 = horzY2;
                horzX4 = x + w - slopeX - 1;
                horzY4 = horzY1;
                vertX1 = x + w - 1;
                vertY1 = y;
                vertX2 = x + w - slopeX - 1;
                vertY2 = y + slopeY;
                vertX3 = vertX2;
                vertY3 = y + h - 1;
                vertX4 = vertX1;
                vertY4 = y + h - slopeY - 1;
            } else {
                faceLeft = x + slopeX;
                horzX1 = x;
                horzY1 = y;
                horzX2 = x + slopeX;
                horzY2 = y + slopeY;
                horzX3 = x + w - 1;
                horzY3 = horzY2;
                horzX4 = x + w - slopeX - 1;
                horzY4 = horzY1;
                vertX1 = x;
                vertY1 = y;
                vertX2 = x + slopeX;
                vertY2 = y + slopeY;
                vertX3 = vertX2;
                vertY3 = y + h - 1;
                vertX4 = vertX1;
                vertY4 = y + h - slopeY - 1;
            }
        } else {
            faceTop = y;
            if (slope.x > 0) {
                faceLeft = x;
                horzX1 = x;
                horzY1 = y + h - slopeY - 1;
                horzX2 = x + slopeX;
                horzY2 = y + h - 1;
                horzX3 = x + w - 1;
                horzY3 = horzY2;
                horzX4 = x + w - slopeX - 1;
                horzY4 = horzY1;
                vertX1 = x + w - slopeX - 1;
                vertY1 = y;
                vertX2 = x + w - 1;
                vertY2 = y + slopeY;
                vertX3 = vertX2;
                vertY3 = y + h - 1;
                vertX4 = vertX1;
                vertY4 = y + h - slopeY - 1;
            } else {
                faceLeft = x + slopeX;
                horzX1 = x;
                horzY1 = y + h - 1;
                horzX2 = x + slopeX;
                horzY2 = y + h - slopeY - 1;
                horzX3 = x + w - 1;
                horzY3 = horzY2;
                horzX4 = x + w - slopeX - 1;
                horzY4 = horzY1;
                vertX1 = x;
                vertY1 = y + h - 1;
                vertX2 = x + slopeX;
                vertY2 = y + h - slopeY - 1;
                vertX3 = vertX2;
                vertY3 = y;
                vertX4 = vertX1;
                vertY4 = y + slopeY;
            }
        }

        if (drawFace) {
            g.setColor(faceColor);
            g.fillRect(faceLeft, faceTop, w - slopeX, h - slopeY);
        }

        if (drawHorzSide) {
            g.setColor(horizontalSideColor);
            polygon = new Polygon();
            polygon.addPoint(horzX1, horzY1);
            polygon.addPoint(horzX2, horzY2);
            polygon.addPoint(horzX3, horzY3);
            polygon.addPoint(horzX4, horzY4);
            polygon.addPoint(horzX1, horzY1);
            g.fillPolygon(polygon);
        }


        if (drawVertSide) {
            g.setColor(verticalSideColor);
            polygon = new Polygon();
            polygon.addPoint(vertX1, vertY1);
            polygon.addPoint(vertX2, vertY2);
            polygon.addPoint(vertX3, vertY3);
            polygon.addPoint(vertX4, vertY4);
            polygon.addPoint(vertX1, vertY1);
            g.fillPolygon(polygon);
        }

        g.setColor(lineColor);

        if (drawFace) {
            g.drawRect(faceLeft, faceTop, w - slopeX - 1, h - slopeY - 1);
        }

        if (drawHorzSide) {
            polygon = new Polygon();
            polygon.addPoint(horzX1, horzY1);
            polygon.addPoint(horzX2, horzY2);
            polygon.addPoint(horzX3, horzY3);
            polygon.addPoint(horzX4, horzY4);
            polygon.addPoint(horzX1, horzY1);
            g.drawPolygon(polygon);
        }

        if (drawVertSide) {
            polygon = new Polygon();
            polygon.addPoint(vertX1, vertY1);
            polygon.addPoint(vertX2, vertY2);
            polygon.addPoint(vertX3, vertY3);
            polygon.addPoint(vertX4, vertY4);
            polygon.addPoint(vertX1, vertY1);
            g.drawPolygon(polygon);
        }
    }

    public void setValue(double newValue)
    {
        value = newValue;
    }

    public double getValue()
    {
        return value;
    }

    public void setAxisScale(CpValueAxisModel newScale)
    {
        axisModel = newScale;
    }

    public void setShouldDrawEnd(boolean newShouldDrawEnd)
    {
        shouldDrawEnd = newShouldDrawEnd;
    }

    public boolean getShouldDrawEnd()
    {
        return shouldDrawEnd;
    }

    public void setSlope(Point newSlope)
    {
        slope = newSlope;
    }

    public Point getSlope()
    {
        return slope;
    }

    public void setFaceColor(Color newColor)
    {
        faceColor = newColor;
        setHorizontalSideColor(newColor.darker());
        setVerticalSideColor(horizontalSideColor.darker());
    }

    public Color getFaceColor()
    {
        return faceColor;
    }

    public void setHorizontalSideColor(Color newColor)
    {
        horizontalSideColor = newColor;
    }

    public Color getHorizontalSideColor()
    {
        return horizontalSideColor;
    }

    public void setVerticalSideColor(Color newColor)
    {
        verticalSideColor = newColor;
    }

    public Color getVerticalSideColor()
    {
        return verticalSideColor;
    }

    public void setLineColor(Color newColor)
    {
        lineColor = newColor;
    }

    public Color getLineColor()
    {
        return lineColor;
    }

    public void paintIn(CpLightweightComponent lc, Graphics g, int x, int y, int w, int h)
    {
        switch (getOrientation()) {
        case ORIENT_LEFT_TO_RIGHT:
            int barWidth = (int)(w * axisModel.getPercentageForValue(value));
            drawBarRect(g, lineColor, faceColor, horizontalSideColor, verticalSideColor, x + w - barWidth, y, barWidth, h, slope, true, shouldDrawEnd, true);
            break;
        case ORIENT_BOTTOM_TO_TOP:
            int slopeY = Math.abs(slope.y);
            int heightWithout3D = h - slopeY;

            int barHeight = (int)(heightWithout3D * axisModel.getPercentageForValue(value));
            drawBarRect(g, lineColor, faceColor, horizontalSideColor, verticalSideColor, x, y + h - barHeight - slopeY, w, barHeight + slopeY, slope, shouldDrawEnd, true, true);
            break;
        }
    }

    public Dimension preferredSize(CpLightweightComponent lc)
    {
        return new Dimension(0, 0);
    }
}

