/*
 * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
 *
 * This file is part of PeerfactSim.KOM.
 * 
 * PeerfactSim.KOM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * PeerfactSim.KOM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PeerfactSim.KOM.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package de.tud.kom.p2psim.impl.topology.views.visualization.ui;

import java.util.HashMap;
import java.util.Map.Entry;

import org.jfree.data.xy.YIntervalSeries;

import de.tud.kom.p2psim.impl.analyzer.metric.MetricAnalyzer;
import de.tudarmstadt.maki.simonstrator.api.MessageWithDisasterType.MessageDisasterType;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric.MetricUnit;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric.MetricValue;

public class DisasterMetricChartAdapter implements MetricPlotAdapter {

	/** the overall metric */
	private final Metric metric;

	/** the average of all {@link MessageDisasterType} */
	private MetricValue<Number> avg = null;

	private YIntervalSeries avgSeries = null;

	/** each type of {@link MessageDisasterType} */
	private HashMap<MessageDisasterType, MetricValue<Number>> subMsgTypeValues;

	private HashMap<YIntervalSeries, MetricValue<Number>> subMsgTypeSeries;

	public DisasterMetricChartAdapter(Metric metric, PlottingView view,
			int maxItems) {
		this.metric = metric;

		// fill subMsgTypeValues
		if (metric.isOverallMetric()) {
			MetricValue<?> mv = metric.getOverallMetric();
			avg = (MetricValue<Number>) mv;

			subMsgTypeValues = new HashMap<>();
			for (MessageDisasterType type : MessageDisasterType.values()) {
				Metric emergencyM = MetricAnalyzer
						.getMetric(metric.getName() + type);
				if (emergencyM != null && emergencyM.isOverallMetric())
					subMsgTypeValues.put(type, emergencyM.getOverallMetric());
			}
		}

		// fill series
		if (avg != null) {
			XYChart chart = view.createPlot(
					metric.getName() + " -- " + metric.getDescription(),
					"Average");

			avgSeries = chart.getDataset().getSeries(0);
			if (maxItems > 0)
				avgSeries.setMaximumItemCount(maxItems);

			subMsgTypeSeries = new HashMap<>();
			for (Entry<MessageDisasterType, MetricValue<Number>> e : subMsgTypeValues
					.entrySet()) {
				YIntervalSeries tempSerie = new YIntervalSeries(e.getKey());
				if (maxItems > 0)
					tempSerie.setMaximumItemCount(maxItems);

				chart.getDataset().addSeries(tempSerie);
				subMsgTypeSeries.put(tempSerie, e.getValue());
			}
		}
	}

	@Override
	public void refresh() {
		double seconds = (double) Time.getCurrentTime() / (double) Time.SECOND;

		if (avgSeries != null) {
			double avgVal = scaledValue(avg);
			if (avg.isValid())
				avgSeries.add(seconds, avgVal, avgVal, avgVal);
		}

		for (Entry<YIntervalSeries, MetricValue<Number>> series : subMsgTypeSeries
				.entrySet()) {
			double tempVal = scaledValue(series.getValue());
			if (series.getValue().isValid())
				series.getKey().add(seconds, tempVal, tempVal, tempVal);
		}
	}

	/**
	 * For {@link Time}.
	 * 
	 * @param mv
	 * @return
	 */
	private double scaledValue(MetricValue<Number> mv) {
		if (metric.getUnit() == MetricUnit.TIME) {
			return mv.getValue().doubleValue() / Time.SECOND;
		}
		return mv.getValue().doubleValue();
	}

}
