package cnp.ew.charts;

import cnp.ew.util.*;
import java.util.*;
import java.awt.*;

/**
 * Ted: the methods you'll want to set are below:
    - setChartLabel(String)
    - setValuesLabel(String)
    - setCategoriesLabel(String)
    - setDataSeriesList(Vector of CpDataSeries)
    - setCategories(Vector of String)

    Corresponding getters can be used as well, to fill in values.
    For the dataseries and categories, you can also ask for them

    by index, rather than for the entire vector:
    - CpDataSeries getDataSeriesForIndex(int)
    - String getCategoryForIndex(int)

  */
public class CpChartDataModel extends CpDefaultObservable
{
    Vector dataSeriesList = new Vector(5);
    Vector categories = new Vector(5);
    String chartLabel="";
    String seriesLabel="";
    String categoriesLabel="";

    public static final int CHANGED_DATA_SERIES=0;
    public static final int CHANGED_DATA_SERIES_VALUE=1;
    public static final int CHANGED_DATA_SERIES_LABEL=2;
    public static final int CHANGED_CATEGORIES=3;
    public static final int CHANGED_CATEGORY=4;
    public static final int CHANGED_SERIES_LABEL=5;
    public static final int CHANGED_CATEGORIES_LABEL=6;
    public static final int CHANGED_CHART_LABEL=7;

    public void setChartLabel(String newLabel)
    {
        boolean notify = !chartLabel.equals(newLabel);
        chartLabel = newLabel;

        if (notify) {
            notifyObservers(CHANGED_CHART_LABEL, chartLabel);
        }
    }

    public String getChartLabel()
    {
        return chartLabel;
    }

    public void setSeriesLabel(String newLabel)
    {
        boolean notify = !seriesLabel.equals(newLabel);
        seriesLabel = newLabel;

        if (notify) {
            notifyObservers(CHANGED_SERIES_LABEL, seriesLabel);
        }
    }

    public String getSeriesLabel()
    {
        return seriesLabel;
    }

    public void setCategoriesLabel(String newLabel)
    {
        boolean notify = !categoriesLabel.equals(newLabel);
        categoriesLabel = newLabel;

        if (notify) {
            notifyObservers(CHANGED_CATEGORIES_LABEL, categoriesLabel);
        }
    }

    public String getCategoriesLabel()
    {
        return categoriesLabel;
    }

    // Should be defined in Vector...
    boolean areListsEqual(Vector list1, Vector list2)
    {
        if (list1.size() != list2.size()) {
            return false;
        }
        for (int i = 0; i < list1.size(); i++) {
            if (!list1.elementAt(i).equals(list2.elementAt(i))) {
                return false;
            }
        }
        return true;
    }

    public void setDataSeriesList(Vector newList)
    {
        boolean notify = !areListsEqual(newList, dataSeriesList);
        dataSeriesList = newList;
        if (notify) {
            notifyObservers(CHANGED_DATA_SERIES, categoriesLabel);
        }
    }

    public void setCategory(int index, String newCategory)
    {
        if (!categories.elementAt(index).equals(newCategory)) {
            categories.setElementAt(newCategory, index);
            notifyObservers(CHANGED_CATEGORY, new Integer(index));
        }
    }

    public void setCategories(Vector newCategories)
    {
        boolean notify = !areListsEqual(categories, newCategories);
        categories = newCategories;
        if (notify) {
            notifyObservers(CHANGED_CATEGORIES);
        }
    }

    public void setValue(Point seriesAndCategory, double value)
    {
        getDataSeriesForIndex(seriesAndCategory.x).setValueForIndex(seriesAndCategory.y, value);
        notifyObservers(CHANGED_DATA_SERIES_VALUE, seriesAndCategory);
    }

    public double getValue(Point seriesAndCategory)
    {
        return getDataSeriesForIndex(seriesAndCategory.x).getValueForIndex(seriesAndCategory.y);
    }

    public void setDataSeriesLabel(int seriesIndex, String s)
    {
        getDataSeriesForIndex(seriesIndex).setLabelObject(s);
        notifyObservers(CHANGED_DATA_SERIES_LABEL, new Integer(seriesIndex));
    }

    public String getDataSeriesLabel(int seriesIndex)
    {
        return getDataSeriesForIndex(seriesIndex).getLabelObject();
    }

    public void dumpDataModel()
    {
        System.out.print("Categories: ");
        for (int i = 0; i < getCategoryCount(); i++) {
            System.out.print(categories.elementAt(i) + " ");
        }
        System.out.println("");
        for (int i=0; i < dataSeriesList.size(); i++) {
            System.out.println("DataSeries[" + i + "]");
            ((CpDataSeries)dataSeriesList.elementAt(i)).dumpValues();
        }
    }

    public void addDataSeries(CpDataSeries series)
    {
        dataSeriesList.addElement(series);
    }

    public Vector getDataSeriesList()
    {
        return dataSeriesList;
    }

    public CpDataSeries getDataSeriesForIndex(int index)
    {
        return (CpDataSeries)dataSeriesList.elementAt(index);
    }

    public int getDataSeriesCount()
    {
        return dataSeriesList.size();
    }

    public double getMaximumSeriesValue()
    {
        double maxValue = 0.0;

        for (int i = 0; i < dataSeriesList.size(); i++) {
            for (int j=0; j < getCategoryCount(); j++) {
                maxValue = Math.max(maxValue, getDataSeriesForIndex(i).getValueForIndex(j));
            }
        }
        return maxValue;
    }

    public double getTotalForCategoryIndex(int index)
    {
        double totalValue = 0.0;

        for (int i = 0; i < dataSeriesList.size(); i++) {
            totalValue += getDataSeriesForIndex(i).getValueForIndex(index);
        }
        return totalValue;
    }

    public double getPercentageValue(Point seriesAndCategory)
    {
        return getPercentageValue(seriesAndCategory.x, seriesAndCategory.y);
    }

    public double getPercentageValue(int dataSeriesIndex, int categoryIndex)
    {
        double totalForCategory = getTotalForCategoryIndex(categoryIndex);
        double value = getDataSeriesForIndex(dataSeriesIndex).getValueForIndex(categoryIndex);
        return value/totalForCategory;
    }

    public Vector getCategories()
    {
        return categories;
    }

    public int getCategoryCount()
    {
        return categories.size();
    }

    public String getCategoryForIndex(int index)
    {
        return (String)categories.elementAt(index);
    }

}

