package iDSS.xyGraph;

import java.util.*;
import java.awt.*;
import java.awt.*;
import java.awt.image.*;
import java.sql.Timestamp;
import java.awt.geom.*;
import java.text.DecimalFormat;
import java.beans.*;


import iDSS.*;
import iDSS.tidalData.*;
import iDSS.utils.*;
import iDSS.xyGraph.*;



public class Graph implements PropertyChangeListener {

    private GraphAxis xAxis,yAxis;
    private Hashtable dataSets;
    private Legend legend;
    private GraphicalDisplay2 graphDisplay;

    private long timeMin,timeMax;
    private double valueMin,valueMax;

    int legX1,legY1;

    private String valueFormatPattern;

    private String xAxisName = "Time";
    private String yAxisName = "Value";

    private Vector colorsVector;
    private final int MAX_NUMBER_OF_GRAPHS = 5;
    private int currentColorIndex;
    private String key;


    public Graph(GraphicalDisplay2 display,ClientDataSet aDataSet,Timestamp startDate,Timestamp endDate,Color color) {


        graphDisplay = display;

        colorsVector = new Vector();
        colorsVector.add(Color.black);
        colorsVector.add(Color.blue);
        colorsVector.add(Color.cyan);
        colorsVector.add(Color.green);
        colorsVector.add(Color.magenta);
        colorsVector.add(Color.orange);
        colorsVector.add(Color.pink);
        colorsVector.add(Color.red);
        colorsVector.add(Color.yellow);

        Vector aVector = new Vector();
        aVector.add(aDataSet);
        aVector.add(startDate);
        aVector.add(endDate);
        //aVector.add(color);

        if(currentColorIndex < (colorsVector.size()-1))
            currentColorIndex++;
        else
            currentColorIndex = 0;

        Color color2 = (Color)colorsVector.elementAt(currentColorIndex);
        aVector.add(color2);

        dataSets = new Hashtable();
        dataSets.put(aDataSet.getSqlString()+startDate.toString()+endDate.toString(),aVector);

        timeMin = startDate.getTime();
        timeMax = endDate.getTime();
        valueMin = aDataSet.getValueMin();
        valueMax = aDataSet.getValueMax();

        roundValues();

        legend = new Legend(aDataSet.getSqlString()+startDate.toString()+endDate.toString(),aDataSet.getStationName(),color2,0,0);


        drawGraph();

    } //public void Graph()






    public GraphicalDisplay2 getDisplay() {

        return graphDisplay;

    } //






    public void roundValues() {


        double limit = (valueMax-valueMin)/10;

        int numberOfZeros = 0;
        while(limit < 1) {
            limit = limit*10;
            numberOfZeros++;
        }



        String pattern = "0.";
        for(int i=0;i<numberOfZeros;i++)
            pattern = pattern.concat("0");


        valueFormatPattern = pattern;

        DecimalFormat form = new DecimalFormat(pattern);

        System.out.println("valueMin with formatting,  " + form.format(valueMin));
        
        limit = (valueMax-valueMin)/10;
        limit = (double) ((int) (limit*Math.pow(10.0,(double)numberOfZeros)))/Math.pow(10.0,(double)numberOfZeros);

        double num = ((int)(valueMin/limit))*limit;
        if (num<valueMin)
            valueMin = num;
        else
            valueMin = num-limit;


        //num = ((int)((valueMax-valueMin)/limit) + 1)*limit;
        num = ((int)(valueMax/limit) + 1)*limit;
        if (num>valueMax)
            valueMax = num;
        else
            valueMax = num+limit;


    } //public void roundValues()






    public void drawGraph() {



        int canvasX = graphDisplay.getCanvasX();
        int canvasY = graphDisplay.getCanvasY();


        BufferedImage image = graphDisplay.getCanvas();

        if(image == null)
            System.out.println("image is null");

        Graphics2D g = (Graphics2D) image.getGraphics();

        g.setColor(Color.black);


        int xMin = Math.min(canvasX/10,50);
        int yMin = Math.min(canvasY/10,50);
        int xMax = canvasX-xMin;
        int yMax = canvasY-yMin;

        int graphWidth = xMax-xMin;
        int graphHeight = yMax-yMin;

        g.drawRect(xMin,yMin,graphWidth,graphHeight);

        int numberOfTicsX = Math.max(canvasX/200,2);
        int numberOfTicsY = Math.max(canvasY/100,2);


        Vector xLabels = new Vector();

        long timeTicDiff = (timeMax-timeMin)/(long)(numberOfTicsX-1);

        for(int i=0;i<numberOfTicsX;i++) {
            long labelLong = timeMin+(long)i*timeTicDiff;
            Timestamp date = new Timestamp(labelLong);
            xLabels.add(date.toString());

        } //for(imt i=o;i<numberOfTicsX;i++)


        Vector yLabels = new Vector();

        double valueTicDiff = (valueMax-valueMin)/(double)(numberOfTicsY-1);

        DecimalFormat form = new DecimalFormat(valueFormatPattern);

        for(int i=0;i<numberOfTicsY;i++) {
            double label = valueMin+(double)i*valueTicDiff;
            String aString = form.format(label);
            yLabels.add(aString);
        } //for(imt i=o;i<numberOfTicsX;i++)


        xAxis = new GraphAxis(xAxisName,xLabels,xMin,yMax,xMax,yMax,Color.black);
        xAxis.drawXAxis(g);

        yAxis = new GraphAxis(yAxisName,yLabels,xMin,yMax,xMin,yMin,Color.black);
        yAxis.drawYAxis(g);

        legend.setX(xMin+10);
        legend.setY(yMax-10);

        drawEachGraph(g,xMin,yMin,xMax,yMax);

        legend.drawLegend(g);

        graphDisplay.refreshCanvas(image);

    }//public void drawGraph()




    public void drawEachGraph(Graphics g,int xMin,int yMin,int xMax,int yMax) {


        Enumeration graphs = dataSets.elements();
        Enumeration colors = colorsVector.elements();

        while(graphs.hasMoreElements()) {

            Vector vector = (Vector) graphs.nextElement();
            ClientDataSet currentDataSet = (ClientDataSet) vector.elementAt(0);
            Timestamp startDate = (Timestamp) vector.elementAt(1);
            Timestamp endDate = (Timestamp) vector.elementAt(2);
            Color currentColor = (Color) vector.elementAt(3);

            Vector dataVector = currentDataSet.getRowsOfDataVector(startDate,endDate);

            int xPoints[] = new int[dataVector.size()];
            int yPoints[] = new int[dataVector.size()];

            for(int i=0;i<dataVector.size();i++) {
                Vector currentRow = (Vector) dataVector.elementAt(i);

                Timestamp timestamp = (Timestamp) currentRow.elementAt(0);
                double value = (double) Double.parseDouble(currentRow.elementAt(1).toString());

                long aLong = timestamp.getTime();
                long bLong = ((long)(aLong-timeMin))*((long)(xMax-xMin))/((long)(timeMax-timeMin))+(long)xMin;

                xPoints[i] = (int)bLong;

                yPoints[i] = (int)((double) (yMax-yMin)*(valueMax-value)/(valueMax-valueMin)+(double)yMin);


            } //for(int i=0;i<dataVector.size();i++)

            g.setColor(currentColor);
            g.drawPolyline(xPoints,yPoints,xPoints.length);

        } //while(graphs.hasMoreElements())


    } //public void drawEachGraph(Graphics g)




    public void addToGraph(ClientDataSet dataset,Timestamp start,Timestamp end,Color color) {


        if(dataSets.size() < MAX_NUMBER_OF_GRAPHS) {

            Vector aVector = new Vector();
            aVector.add(dataset);
            aVector.add(start);
            aVector.add(end);

            if(currentColorIndex < (colorsVector.size()-1))
                currentColorIndex++;
            else
                currentColorIndex = 0;

            color = (Color)colorsVector.elementAt(currentColorIndex);
            aVector.add(color);

            dataSets.put(dataset.getSqlString()+start.toString()+end.toString(),aVector);

            timeMin = Math.min(start.getTime(),timeMin);
            timeMax = Math.max(end.getTime(),timeMax);
            valueMin = Math.min(dataset.getValueMin(),valueMin);
            valueMax = Math.max(dataset.getValueMax(),valueMax);

            roundValues();

            legend.addToLegend(dataset.getSqlString()+start.toString()+end.toString(),dataset.getStationName(),color);

            graphDisplay.clearBuffer();

            drawGraph();

        } //if();

    } //public void addToGraph(ClientDataSet dataset,Timestamp start,Timestamp end,Color color)




    public void propertyChange(PropertyChangeEvent evt) {

        if (evt.getPropertyName().equals(IDSSAppConstants.drawGraph)) {

            drawGraph();

        } //if (evt.getPropertyName().equals(IDSSAppConstants.drawGraph))



    } //public void propertyChange(PropertyChangeEvent evt)




} //public class Graph
