package org.eclipse.stem.util.analysis.views;

/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.birt.chart.device.IDeviceRenderer;
import org.eclipse.birt.chart.exception.ChartException;
import org.eclipse.birt.chart.factory.Generator;
import org.eclipse.birt.chart.model.Chart;
import org.eclipse.birt.chart.model.ChartWithAxes;
import org.eclipse.birt.chart.model.attribute.Anchor;
import org.eclipse.birt.chart.model.attribute.AxisType;
import org.eclipse.birt.chart.model.attribute.Bounds;
import org.eclipse.birt.chart.model.attribute.ChartDimension;
import org.eclipse.birt.chart.model.attribute.ColorDefinition;
import org.eclipse.birt.chart.model.attribute.IntersectionType;
import org.eclipse.birt.chart.model.attribute.Position;
import org.eclipse.birt.chart.model.attribute.TickStyle;
import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl;
import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl;
import org.eclipse.birt.chart.model.component.Axis;
import org.eclipse.birt.chart.model.component.Series;
import org.eclipse.birt.chart.model.component.impl.SeriesImpl;
import org.eclipse.birt.chart.model.data.NumberDataSet;
import org.eclipse.birt.chart.model.data.SeriesDefinition;
import org.eclipse.birt.chart.model.data.TextDataSet;
import org.eclipse.birt.chart.model.data.impl.NumberDataSetImpl;
import org.eclipse.birt.chart.model.data.impl.SeriesDefinitionImpl;
import org.eclipse.birt.chart.model.data.impl.TextDataSetImpl;
import org.eclipse.birt.chart.model.impl.ChartWithAxesImpl;
import org.eclipse.birt.chart.model.layout.Legend;
import org.eclipse.birt.chart.model.layout.Plot;
import org.eclipse.birt.chart.model.type.BarSeries;
import org.eclipse.birt.chart.model.type.impl.BarSeriesImpl;
import org.eclipse.birt.chart.util.PluginSettings;
import org.eclipse.stem.util.analysis.Activator;
import org.eclipse.stem.util.analysis.Parameter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Widget;

/**
 * TimeSeriesCanvas is a subclass of {@link Canvas} suitable for chart drawings.
 */
public class EstimatorCanvas extends Canvas {

	protected IDeviceRenderer idr = null;

	/**
	 * This is the {@link Chart} that plots the relative values.
	 */
	protected Chart cm = null;

	//private EstimatorControl control = null;
	
	static ColorDefinition[] barColors = {ColorDefinitionImpl.RED(),
			ColorDefinitionImpl.BLUE(),
			ColorDefinitionImpl.ORANGE(),
			ColorDefinitionImpl.YELLOW(),
			ColorDefinitionImpl.GREEN(),
			ColorDefinitionImpl.PINK(),
			ColorDefinitionImpl.BLACK() };

	
	/**
	 * the chart title
	 */
	private static final String TITLE = "Estimated Parameters";
	
	/**
	 * the legend
	 */
	private static final String VALUES = "Parameter Values";
	private static final String VALUES_LOWER = "Value - Std.Dev.";
	private static final String VALUES_HIGHER = "Value + Std.Dev.";
	
	private static final boolean SHOW_STD_DEV = false;
	
	
	/**
	 * Collection of values for the X-SERIES bar labels
	 **/
	private static Vector<String> xAxisParameterNames = new Vector<String>();
	
	/**
	 * Collection of values for the Y-SERIES bars
	 **/
	private static ArrayList<Double> barValues = new ArrayList<Double>();
	private static NumberDataSet barOrthoValues;

	
	/**
	 * Collection of values for the Y-SERIES2 standard deviation lower and higher bars
	 **/
	private static ArrayList<Double> barStdDevLower = new ArrayList<Double>();
	private static ArrayList<Double> barStdDevHigher = new ArrayList<Double>();
	private static NumberDataSet barOrthoStdDevLower;
	private static NumberDataSet barOrthoStdDevHigher
	;

	/**
	 * Chart generator instance (reference to a singleton)
	 */
	Generator gr;

	Image imgChart = null;
	
	/**
	 * Constructor.
	 * 
	 * @param parent
	 *            the SWT parent of the {@link Widget}
	 */
	public EstimatorCanvas(final Composite parent) {
		super(parent, SWT.DOUBLE_BUFFERED | SWT.BORDER);

		gr = Generator.instance();

		try {
			idr = PluginSettings.instance().getDevice("dv.SWT"); //$NON-NLS-1$			
		} catch (final ChartException pex) {
			Activator.logError("Problem initializing chart", pex); //$NON-NLS-1$
			return;
		}

		//control = (EstimatorControl) parent;

		Vector<String> xAxisParameters = new Vector<String>();
		xAxisParameters.add("beta");
		xAxisParameters.add("alpha");
		xAxisParameters.add("epsilon");
		xAxisParameters.add("gamma");
		
		//Map<String,Double> initMap = ModelParameters;
		//cm = createBarChart(initMap); 

		addPaintListener(new PaintListener() {
			public void paintControl(final PaintEvent pe) {
				if(cm == null) return;
				final Composite source = (Composite) pe.getSource();
				final org.eclipse.swt.graphics.Rectangle d = source
						.getClientArea();

				if(imgChart != null) imgChart.dispose();
				imgChart = new Image(source.getDisplay(), d);
				idr.setProperty(IDeviceRenderer.GRAPHICS_CONTEXT, new GC(
						imgChart));
				final Bounds bounds = BoundsImpl.create(d.x, d.y, d.width,
						d.height);
				bounds.scale(72d / idr.getDisplayServer().getDpiResolution());
				// BOUNDS MUST BE SPECIFIED IN POINTS

				try {
					gr.render(idr, gr.build(idr.getDisplayServer(), cm, bounds,
							null, null, null));
					pe.gc.drawImage(imgChart, d.x, d.y);
				} catch (final ChartException ce) {
					Activator.logError("Problem rendering chart", ce); //$NON-NLS-1$
				}

			} // paintControl
		} // PaintListener

		);

	} // EstimatorCanvas constructor

	/**
	 * * creates the chart
	 * @param barDataMap
	 * @return a bar chart
	 */
	@SuppressWarnings("deprecation")
	public static Chart createBarChart(Map<String,Parameter> barDataMap) {
		// Reset everything
		xAxisParameterNames.clear();
		barValues.clear();
		barStdDevLower.clear();
		barStdDevHigher.clear();
		
		// BAR CHARTS ARE BASED ON CHARTS THAT CONTAIN AXES
		ChartWithAxes cwaBar = ChartWithAxesImpl.create();
		cwaBar.getBlock().setBackground(ColorDefinitionImpl.WHITE());
		cwaBar.getBlock().getOutline().setVisible(true);
		cwaBar.setDimension(ChartDimension.TWO_DIMENSIONAL_WITH_DEPTH_LITERAL);

		// CUSTOMIZE THE PLOT
		Plot p = cwaBar.getPlot();
		p.getClientArea().setBackground(ColorDefinitionImpl.create(255, 255, 225));
		p.getOutline().setVisible(false);
		cwaBar.getTitle().getLabel().getCaption().setValue(TITLE);

		// CUSTOMIZE THE LEGEND
		Legend lg = cwaBar.getLegend();
		lg.getText().getFont().setSize(16);
		lg.getInsets().set(10, 5, 0, 0);
		lg.setAnchor(Anchor.NORTH_LITERAL);

		// CUSTOMIZE THE X-AXIS
		Axis xAxisPrimary = cwaBar.getPrimaryBaseAxes()[0];
		xAxisPrimary.setType(AxisType.TEXT_LITERAL);
		xAxisPrimary.getMajorGrid().setTickStyle(TickStyle.BELOW_LITERAL);
		xAxisPrimary.getOrigin().setType(IntersectionType.VALUE_LITERAL);
		xAxisPrimary.getTitle().setVisible(false);

		// CUSTOMIZE THE Y-AXIS
		Axis yAxisPrimary = cwaBar.getPrimaryOrthogonalAxis(xAxisPrimary);
		yAxisPrimary.getMajorGrid().setTickStyle(TickStyle.LEFT_LITERAL);
		yAxisPrimary.setType(AxisType.LINEAR_LITERAL);
		yAxisPrimary.getLabel().getCaption().getFont().setRotation(90);

				
		// populate from the map
		Set<String> keySet = barDataMap.keySet();
		String[] keys = new String[keySet.size()];
		Iterator<String> iter = keySet.iterator();
		int icount = 0;
		while(iter.hasNext()) {
			keys[icount] = iter.next();
			icount ++;
		}
		Arrays.sort(keys);
		for (int i = 0; i < keys.length; i++) {
			String paramName = keys[i];
			xAxisParameterNames.add(paramName);
			Double dValue = new Double(barDataMap.get(paramName).value);
			
			barStdDevLower.add(dValue);
			barValues.add(dValue);
			barStdDevHigher.add(dValue);
		}
		
		TextDataSet categoryValues = TextDataSetImpl.create(xAxisParameterNames);

		barOrthoValues = NumberDataSetImpl.create(barValues);
		barOrthoStdDevLower = NumberDataSetImpl.create(barStdDevLower);
		barOrthoStdDevHigher = NumberDataSetImpl.create(barStdDevHigher);

		// CREATE THE CATEGORY BASE SERIES
		Series seCategory = SeriesImpl.create();
		seCategory.setDataSet(categoryValues);
		
		// Create the first series of dataValues the ORTHOGONAL Value-Statndard deviations LOWER SERIES
		BarSeries bsLower = (BarSeries) BarSeriesImpl.create();
		bsLower.setSeriesIdentifier(VALUES_LOWER);
		bsLower.setDataSet(barOrthoStdDevLower);
		bsLower.setRiserOutline(null);
		bsLower.getLabel().setVisible(true);
		bsLower.setLabelPosition(Position.INSIDE_LITERAL);

		// Create the Values series of dataValues the ORTHOGONAL SERIES
		BarSeries bsValues = (BarSeries) BarSeriesImpl.create();
		bsValues.setSeriesIdentifier(VALUES);
		bsValues.setDataSet(barOrthoValues);
		bsValues.setRiserOutline(null);
		bsValues.getLabel().setVisible(true);
		bsValues.setLabelPosition(Position.INSIDE_LITERAL);
		
		// Create the THIRD series of dataValues the ORTHOGONAL Value+StdDev HIGHER SERIES
		BarSeries bsHigher = (BarSeries) BarSeriesImpl.create();
		bsHigher.setSeriesIdentifier(VALUES_HIGHER);
		bsHigher.setDataSet(barOrthoStdDevHigher);
		bsHigher.setRiserOutline(null);
		bsHigher.getLabel().setVisible(true);
		bsHigher.setLabelPosition(Position.INSIDE_LITERAL);

		// WRAP THE BASE SERIES IN THE X-AXIS SERIES DEFINITION
		SeriesDefinition sdX = SeriesDefinitionImpl.create();
		sdX.getSeriesPalette().update(0); // SET THE COLORS IN THE PALETTE
		xAxisPrimary.getSeriesDefinitions().add(sdX);
		sdX.getSeries().add(seCategory);

		if (SHOW_STD_DEV) {
			// One THE ORTHOGONAL VALUES-STD-DEV lower SERIES For the Y-AXIS SERIES DEFINITION
			SeriesDefinition sdYlower = SeriesDefinitionImpl.create();
			sdYlower.getSeriesPalette().update(1); // SET THE COLOR IN THE PALETTE
			yAxisPrimary.getSeriesDefinitions().add(sdYlower);
			sdYlower.getSeries().add(bsLower);
		}
		
		
		// Two THE ORTHOGONAL VALUES SERIES For the Y-AXIS SERIES DEFINITION
		SeriesDefinition sdY1 = SeriesDefinitionImpl.create();
		sdY1.getSeriesPalette().update(1); // SET THE COLOR IN THE PALETTE
		yAxisPrimary.getSeriesDefinitions().add(sdY1);
		sdY1.getSeries().add(bsValues);
		
		if (SHOW_STD_DEV) {
			// Three THE ORTHOGONAL VALUES+STDDEV Higher SERIES For the Y-AXIS SERIES DEFINITION
			SeriesDefinition sdYHigher = SeriesDefinitionImpl.create();
			sdYHigher.getSeriesPalette().update(1); // SET THE COLOR IN THE PALETTE
			yAxisPrimary.getSeriesDefinitions().add(sdYHigher);
			sdYHigher.getSeries().add(bsHigher);
		}
		
		
		return cwaBar;

	}// createBarChart
	
	/**
	 * refreshes (some of) the data in the bar chart by key values
	 * @param barDataMap All parameters
	 */
	public static void refresh(Map<String,Parameter> barDataMap) {
		Iterator<String> iter = barDataMap.keySet().iterator();
		while(iter.hasNext()) {
			String key = iter.next();
			int icount = xAxisParameterNames.indexOf(key);
			if (icount >= 0) {
				double value = barDataMap.get(key).value;
				
				// and the higher/lower values
				double deviation = barDataMap.get(key).stddev;
				Double lower = new Double(value-deviation);
				Double higher = new Double(value + deviation);
				
				barValues.set(icount,new Double(value));
				barStdDevLower.set(icount,lower);
				barStdDevHigher.set(icount,higher);
			}
			
		}// while have keys
	}// refresh
	
	/**
	 * The method which gets the {@link EstimatorCanvas}' reports list, and
	 * draws it on the {@link EstimatorCanvas}.
	 * @param barDataMap Parameter map
	 * 
	 */
	public void draw(Map<String,Parameter> barDataMap) {
		cm = EstimatorCanvas.createBarChart(barDataMap);
		//refresh(barDataMap);

		if (!this.isDisposed()) {
			redraw();
		}
	} // paintControl

	/**
	 * Disposes the Color objects
	 */
	@Override
	public void dispose() {
		super.dispose();
	}

	
} // TimeSeriesCanvas
