/*******************************************************************************
 * Copyright (c) 2000, 2017 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
 *******************************************************************************/
package org.eclipse.test.performance.ui;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.test.internal.performance.data.Dim;

public class TimeLineGraph extends LineGraph{

    Hashtable<String, List<TimeLineGraphItem>> fItemGroups;

    public TimeLineGraph (String title, Dim dim) {
        super(title, dim);
        this.fItemGroups=new Hashtable<>();
    }

    @Override
    public void paint(Image im) {

        Rectangle bounds= im.getBounds();

        GC g= new GC(im);

        Point ee= g.stringExtent(this.fTitle);
        int titleHeight= ee.y;

        double maxItem= getMaxItem();
        double minItem= getMinItem();

        int max= (int) (Math.ceil(maxItem * (maxItem < 0 ? 0.8 : 1.2)));
        int min= (int) (Math.floor(minItem * (minItem < 0 ? 1.2 : 0.8)));

        String smin= this.fDimension.getDisplayValue(min);
        Point emin= g.stringExtent(smin);

        String smax= this.fDimension.getDisplayValue(max);
        Point emax= g.stringExtent(smax);

        int labelWidth= Math.max(emin.x, emax.x) + 2;

        int top= PADDING;
        int bottom= bounds.height - titleHeight - PADDING;
        int left= PADDING + labelWidth;

        //getMostRecent
        TimeLineGraphItem lastItem= getMostRecent(this.fItemGroups);
        int right=bounds.width - PADDING/2;
        if (lastItem!=null)
        	right= bounds.width - lastItem.getSize(g).x - PADDING/2;

        // draw the max and min values
        g.drawString(smin, PADDING/2+labelWidth-emin.x, bottom-titleHeight, true);
        g.drawString(smax, PADDING/2+labelWidth-emax.x, top, true);
        g.drawString("TIME (not drawn to scale)", (right-left)/3+PADDING+titleHeight,bottom-PADDING+(titleHeight*2), true);

        // draw the vertical and horizontal lines
        g.drawLine(left, top, left, bottom);
        g.drawLine(left, bottom, right, bottom);

        Color oldbg= g.getBackground();
        Color oldfg= g.getForeground();

        setCoordinates(right-left,left,bottom-top,max-min);

        Enumeration<List<TimeLineGraphItem>> _enum=this.fItemGroups.elements();
        Comparator<TimeLineGraphItem> comparator=new TimeLineGraphItem.GraphItemComparator();

        while (_enum.hasMoreElements()) {
 			List<TimeLineGraphItem> items = _enum.nextElement();
 			TimeLineGraphItem[] fItemsArray=items.toArray(new TimeLineGraphItem[items.size()]);
			Arrays.sort(fItemsArray,comparator);
			int lastx = 0;
			int lasty = 0;

			int n = fItemsArray.length;

			for (int i = 0; i < n; i++) {
				TimeLineGraphItem thisItem = fItemsArray[i];

				int yposition = thisItem.y;
				int xposition = thisItem.x;
				g.setLineWidth(1);

				g.setBackground(thisItem.color);
				g.setForeground(thisItem.color);

				if (thisItem.drawAsBaseline){
					g.setLineWidth(0);
					g.drawLine(xposition, yposition,right,yposition);
					g.drawLine(left,yposition,xposition, yposition);
    		    }

				if (i > 0) // don't draw for first segment
					g.drawLine(lastx, lasty, xposition, yposition);

				g.setBackground(thisItem.color);
				g.setForeground(thisItem.color);
			//	g.fillOval(xposition - 2, yposition - 2, 6, 6);
				g.fillRectangle(xposition - 2, yposition - 2, 5, 5);

				if (thisItem.isSpecial)
					g.drawRectangle(xposition -4, yposition - 4, 8, 8);

				if (this.fAreaBuffer == null)
					this.fAreaBuffer = new StringBuilder();

				this.fAreaBuffer.append("\r<area shape=\"circle\" coords=\""
						+ (xposition - 2) + ',' + (yposition - 2) + ',' + 5
						+ " alt=\"" + thisItem.title + ": "
						+ thisItem.description + "\"" + " title=\""
						+ thisItem.title + ": " + thisItem.description + "\">");

				int shift;
				if (i > 0 && yposition < lasty)
					shift = 3; // below dot
				else
					shift = -(2 * titleHeight + 3); // above dot
				if (thisItem.displayDescription) {
					g.drawString(thisItem.title, xposition + 2, yposition
							+ shift, true);
					g.drawString(thisItem.description, xposition + 2, yposition
							+ shift + titleHeight, true);
				}
				g.setBackground(oldbg);
				g.setForeground(oldfg);

				lastx = xposition;
				lasty = yposition;
			}
		}

        g.dispose();
    }

    public void addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp) {
    	addItem(groupName, name, description, value, col, display,	timestamp,false);
    }

    public void addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp,boolean isSpecial) {
 		addItem(groupName, name,description, value, col, display,
 				timestamp,isSpecial,false);
	}

    public void addItem(String groupName,String name, String description, double value, Color col, boolean display, long timestamp,boolean isSpecial,boolean drawBaseline) {
      	List<TimeLineGraphItem> items = this.fItemGroups.get(groupName);
  		if (this.fItemGroups.get(groupName) == null) {
  			items=new ArrayList<>();
  			this.fItemGroups.put(groupName, items);
  		}
  		items.add(new TimeLineGraphItem(name, description, value, col, display,
  				timestamp,isSpecial,drawBaseline));
    }

    @Override
    public double getMaxItem() {
    	Enumeration<List<TimeLineGraphItem>> _enum=this.fItemGroups.elements();
        double maxItem= 0;
    	while (_enum.hasMoreElements()) {
			List<TimeLineGraphItem> items = _enum.nextElement();
			for (int i = 0; i < items.size(); i++) {
				TimeLineGraphItem graphItem = items.get(i);
				if (graphItem.value > maxItem)
					maxItem = graphItem.value;
			}
		}
        if (maxItem == 0)
            return 1;
        return maxItem;
    }

    @Override
    public double getMinItem() {
       	Enumeration<List<TimeLineGraphItem>> _enum = this.fItemGroups.elements();
		double minItem = getMaxItem();

		while (_enum.hasMoreElements()) {
			List<TimeLineGraphItem> items = _enum.nextElement();
			for (int i = 0; i < items.size(); i++) {
				TimeLineGraphItem graphItem = items.get(i);
				if (graphItem.value < minItem)
					minItem = graphItem.value;
			}
		}
        if (minItem == 0)
            return -1;
        return minItem;
    }

    private TimeLineGraphItem getMostRecent(Hashtable<String, List<TimeLineGraphItem>> lineGraphGroups) {
		Enumeration<List<TimeLineGraphItem>> _enum = lineGraphGroups.elements();
		long mostRecentTimestamp = 0;
		TimeLineGraphItem mostRecentItem = null;

		while (_enum.hasMoreElements()) {
			List<TimeLineGraphItem> items = _enum.nextElement();
			for (int i = 0; i < items.size(); i++) {
				if (items.size() == 1)
					return items.get(i);
				else {
					TimeLineGraphItem graphItem = items.get(i);
					if (graphItem.timestamp > mostRecentTimestamp) {
						mostRecentTimestamp = graphItem.timestamp;
						mostRecentItem = items.get(i);
					}
				}
			}
		}
		return mostRecentItem;
	}

    private void setCoordinates(int width, int xOffset, int height, int yValueRange){

        List<TimeLineGraphItem> mainGroup=this.fItemGroups.get("main");
        List<TimeLineGraphItem> referenceGroup=this.fItemGroups.get("reference");

        Comparator<TimeLineGraphItem> comparator=new TimeLineGraphItem.GraphItemComparator();

        TimeLineGraphItem[] fItemsArray=mainGroup.toArray(new TimeLineGraphItem[mainGroup.size()]);
		Arrays.sort(fItemsArray,comparator);

		int n = mainGroup.size();
		int xIncrement=width/n;
		double max=getMaxItem()*1.2;
//		double min=getMinItem()*0.8;

		for (int i = 0; i < n; i++) {
			TimeLineGraphItem thisItem = fItemsArray[i];
			thisItem.setX(xOffset + (i * xIncrement));
			thisItem.setY((int)(PADDING+((max-thisItem.value) * (height)/(yValueRange))));

			}

		if (referenceGroup==null)
			return;

		n = referenceGroup.size();
		for (int i = 0; i < n; i++) {
			 TimeLineGraphItem thisItem = referenceGroup.get(i);
			 if (thisItem.timestamp==-1)
				 thisItem.setX(xOffset + (i * (width/n)));
			 else
				 setRelativeXPosition(thisItem,mainGroup);

			 thisItem.setY((int)(PADDING+((max-thisItem.value) * (height)/(yValueRange))));

		}
    }


	private void setRelativeXPosition (TimeLineGraphItem thisItem, List<TimeLineGraphItem> items){
			Comparator<TimeLineGraphItem> comparator=new TimeLineGraphItem.GraphItemComparator();
			TimeLineGraphItem[] fItemsArray=items.toArray(new TimeLineGraphItem[items.size()]);
			Arrays.sort(fItemsArray,comparator);

			TimeLineGraphItem closestPrecedingItem=null;
			long minimumTimeDiffPreceding=thisItem.timestamp;

			TimeLineGraphItem closestFollowingItem=null;
			long minimumTimeDiffFollowing=thisItem.timestamp;

			for (int i=0;i<fItemsArray.length;i++){
				TimeLineGraphItem anItem=fItemsArray[i];
				long timeDiff=thisItem.timestamp-anItem.timestamp;

				 if (timeDiff>0&&timeDiff<minimumTimeDiffPreceding){
					 closestPrecedingItem=anItem;
				 	minimumTimeDiffPreceding=thisItem.timestamp-anItem.timestamp;
				 }
				 if (timeDiff<=0&&Math.abs(timeDiff)<=minimumTimeDiffFollowing){
					 closestFollowingItem=anItem;
					 minimumTimeDiffFollowing=thisItem.timestamp-anItem.timestamp;
				 }
			}
			if (closestFollowingItem==null && closestPrecedingItem!=null)
				thisItem.setX(closestPrecedingItem.x);

			else if (closestFollowingItem!=null && closestPrecedingItem==null)
				thisItem.setX(closestFollowingItem.x);
			else{
			    if (closestFollowingItem == null || closestPrecedingItem == null) {
			      throw new RuntimeException("closestFollowingItem or closestPrecedingItem was unexpectedly null. Program error?");
			    }
				long timeRange=closestFollowingItem.timestamp-closestPrecedingItem.timestamp;

				int xRange=closestFollowingItem.x-closestPrecedingItem.x;
				double increments=(xRange*1.0)/timeRange;

				thisItem.setX((int)(Math.round((thisItem.timestamp-closestPrecedingItem.timestamp)*increments)+closestPrecedingItem.x));
			}
	}
}
