package cnp.ew.charts;

import cnp.ew.diagram.*;
import java.awt.*;
import cnp.ew.displayer.*;
import java.util.*;
import cnp.ew.lightweight.*;

public class CpChartLegendDisplayer implements CpDisplayable
{
    CpColorBoxDisplayer boxDisplayer = new CpColorBoxDisplayer();
    CpGeneralStringDisplayer textDisplayer;
    Vector dataSeriesList;

    // this should scale
    static int vertMargin = 6;
    static int boxMargin = 3;
    static int minExtraSpace = 10;

    public CpChartLegendDisplayer()
    {
        textDisplayer = new CpGeneralStringDisplayer();
        textDisplayer.setFont(new Font("Dialog", Font.PLAIN, 8));
    }

    public void setChartDataModel(CpChartDataModel dataModel)
    {
        dataSeriesList = dataModel.getDataSeriesList();
    }


    public void paintIn(CpLightweightComponent lc, Graphics g, int x, int y, int w, int h)
    {
        int startX, startY, boxSize;
        int numColumns, numRows, rowHeight, itemWidth, itemHeight, accumulatedWidth, extraSpace;
        Dimension textSize;
        CpDataSeries dataSeries;
        int numItems = dataSeriesList.size();
        Dimension [] preferredSizes = new Dimension[numItems];
        int i, j;


        itemHeight = 0;
        numColumns = 0;
        accumulatedWidth = 0;

        // First, cache the stringwidths
        boxSize = -1;
        for (i =0; i < numItems; i++) {
            dataSeries = (CpDataSeries)dataSeriesList.elementAt(i);
            textDisplayer.setText(dataSeries.getLabelObject());
            preferredSizes[i] = textDisplayer.preferredSize(lc);
            if (boxSize < 0) {
                boxSize = (int)(preferredSizes[i].height * 0.7);
            }
        }


        boolean foundFit = false;
        numColumns = numItems;
        int [] columnWidths = new int[numColumns];
        while (!foundFit) {
            for (i = 0; i < numColumns; i++) {
                columnWidths[i] = 0;
            }
            accumulatedWidth = 0;
            for (i = 0; i < numColumns; i++) {
                for (j=i; j < numItems; j+= numColumns) {
                    columnWidths[i] = Math.max(columnWidths[i], preferredSizes[j].width);
                }
                accumulatedWidth += columnWidths[i] + boxMargin + boxSize + minExtraSpace;
            }
            if (accumulatedWidth > w) {
                numColumns--;
                if (numColumns == 0) {
                    numColumns++;
                    foundFit = true;
                }
            } else {
                foundFit = true;
            }
        }


        // calculate the extra space between items
        extraSpace = w;
        for (i = 0; i < numColumns; i++) {
            extraSpace -= columnWidths[i] + boxSize + boxMargin;
        }

        extraSpace /= numColumns;

        itemHeight = preferredSizes[0].height;

        // always round numRows up
        numRows = (numItems + numColumns - 1) / numColumns;
        rowHeight = h / numRows;

        // don't use font ascent directly from the metrics; there's a
        // margin built into the displayer... Rethink this...
        int fontAscent = textDisplayer.getFontAscent(lc);

        int itemCount = 0;
        startY = y + (rowHeight - itemHeight)/2;
        for (i = 0; i < numRows; i++) {
            startX = Math.max(x + extraSpace/2, x + minExtraSpace/2);
            for (j=0; j < numColumns; j++) {
                if (itemCount < numItems) {
                    dataSeries = (CpDataSeries)dataSeriesList.elementAt(itemCount);
                    textDisplayer.setText(dataSeries.getLabelObject());
                    textSize = textDisplayer.preferredSize(lc);
                    boxDisplayer.setBoxColor(dataSeries.getColor());
                    boxDisplayer.paintIn(lc, g, startX, startY + fontAscent - boxSize, boxSize, boxSize);
                    textDisplayer.paintIn(lc, g, startX + boxSize + boxMargin, startY, x + w - startX - boxSize - boxMargin - minExtraSpace/2, textSize.height);
                    itemCount++;
                }

                startX += columnWidths[j] + boxSize + boxMargin + extraSpace;

            }
            startY += rowHeight;
        }
    }


    public void paintIn(CpLightweightComponent lc, Graphics g, Rectangle r)
    {
        paintIn(lc, g, r.x, r.y, r.width, r.height);
    }

    public Dimension preferredSize(CpLightweightComponent lc)
    {
        return new Dimension(0,0);
    }
}
