/*
 * Created on Nov 15, 2006
 *
 * various ways of viewing EDL files
 * 
 */
package com.meapsoft.visualizer;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;

import com.meapsoft.EDLFile;
import com.meapsoft.FeatFile;


/**
 * @author douglas repetto
 *
 */

public class BarGraphRenderer extends Renderer
{		
	JComboBox hOptions;
	JComboBox sOptions;
	
	double currXMulti = 0.0;
	double currHeight = 0.0;
	
	public BarGraphRenderer(FeatFile featFile, EDLFile eDLFile)
	{
		super(featFile, eDLFile, "BarGraph");
	}

	public BarGraphRenderer(Renderer r)
	{
		super(r);
		//have to do this so we're not stuck with invalid
		//multipliers from another renderer
		updateColorMultipliers();
	}

	public void draw(Graphics graphics, int width, int height)
	{	
		//System.out.println("width: " + width + " height: " + height);
		int numChunks = events.size();
		
		//set up scaling factors
		ChunkVisInfo lastChunk = (ChunkVisInfo) events.elementAt(numChunks - 1);
		double xMulti = width/(lastStartTime + lastChunk.length);
		 
		graphics.setColor(Color.white);
		graphics.fillRect(0,0,width,height);
		
		for (int i = 0; i < numChunks; i++)
		{
			ChunkVisInfo cVI = (ChunkVisInfo) events.elementAt(i);
			
			int[] featNum = {0};
			
			for (int j = 0; j < numFeatures; j++)
			{
				double features[] = cVI.getFeatures(featNum);
				double featureValue = features[0] - lowestFeatureValue[j];

				featNum[0] += elementsPerFeature[j];
				/*
				if (features[0] == highestFeatureValue[j])
					System.out.println("found hFV: " + features[0]);
				*/
				/*
				if (colorMapType == SQRT)
				{
					featureValue -= lowestFeatureValue[j];
					featureValue = Math.sqrt(featureValue);
				}
				else if (colorMapType == SQUARE)
				{
					featureValue -= lowestFeatureValue[j];
					featureValue *= featureValue;
				}
				*/
				double colorIndex = featureValue * colorMultipliers[j];
				Color extraColor;
				Color featureColor;
			
				if (cVI.selected)
				{
					extraColor = Color.white;
					featureColor = colormap.table[(int)colorIndex];
				}
				else
				{
					extraColor = Color.DARK_GRAY;
					featureColor = colormap.table[(int)colorIndex].darker().darker().darker();
				}
			
				int blipHeight = 0;//(int)(cVI.length * yMulti);
				double yMulti = 0.0;//(height/longestChunk)/numFeatures;

				int which = hOptions.getSelectedIndex();
				
				if (which == 0)
				{
					yMulti = (height/lastStartTime)/numFeatures;			
					blipHeight = (int)(Math.round(cVI.startTime * yMulti));
				}
				else if (which == 1)
				{
					yMulti = (height/lastStartTime)/numFeatures;
					blipHeight = (int)(Math.round(cVI.dstTime * yMulti));
				}
				else if (which == 2)
				{
					yMulti = (height/longestChunk)/numFeatures;
					blipHeight = (int)(Math.round(cVI.length * yMulti));
				}
				else if (which == 3)
				{
					yMulti = (height/(featureValueSpan[j]))/numFeatures;
					blipHeight = (int)(Math.round(featureValue * yMulti));
				}
				
				// + 1 is a kludge to avoid white bands
				int blipWidth = (int)(cVI.length * xMulti) + 1;
									
				//draw feats
				int x1 = (int)(Math.round(cVI.startTime * xMulti));
				//or draw EDL
				if (sOptions.getSelectedIndex() == 1)
					x1 = (int)(Math.round(cVI.dstTime * xMulti));

				int yOffset = Math.round((height/numFeatures) * j);
				int yTop = (height - yOffset) - (height/numFeatures);
				int yFeatStart = (height - yOffset) - blipHeight;
			
				//special drawing routine for multi-dimensional features
				if (elementsPerFeature[j] > 1)
				{
					//do background
					graphics.setColor(extraColor);
					graphics.fillRect(x1, yTop, blipWidth, height/numFeatures);
					//draw feature
					if (which == 3)
					{
						blipHeight = Math.round(height/numFeatures);
						kludgyMultiDimensionalDraw(x1, yTop,blipWidth,blipHeight,cVI, j, graphics);
					}
					else
						kludgyMultiDimensionalDraw(x1, yFeatStart,blipWidth,blipHeight,cVI, j, graphics);
				}
				else
				{
					//draw background
					graphics.setColor(extraColor);
					graphics.fillRect(x1, yTop, blipWidth, height/numFeatures);
					//draw feature
					graphics.setColor(featureColor);
					graphics.fillRect(x1, yFeatStart, blipWidth, blipHeight);
				}

				cVI.xFeat = x1;
				cVI.width = blipWidth;
			}
			cVI.height = height;
		}
		
		if (dragRect != null)
		{
			//System.out.println("drawing: " + dragRect.toString());
			graphics.setColor(Color.black);
			graphics.drawRect(dragRect.x, dragRect.y, dragRect.width, dragRect.height);
		}
		
		currXMulti = xMulti;
		currHeight = height;
	}
	
	public void kludgyMultiDimensionalDraw(int x, int y, int w, int h,
											ChunkVisInfo cVI, int featNum, Graphics graphics)
	{			
		int numElements = elementsPerFeature[featNum];

		int startElement = 0;
		
		for (int i = 0; i < featNum; i++)
			startElement += elementsPerFeature[i];

		double yIncr = (double)h/numElements;
		
		//System.out.println("x: " + x + " Oy: " + y + " w: " + w + " h: " + h +
		//	" featNum: " + featNum + " numElements: " + numElements + 
		//	" elementNum: " + elementNum + " yIncr: " + yIncr);

		for (int i = startElement; i < startElement + numElements; i++)
		{
			int[] fN = {i};
			double featureValue = cVI.getFeatures(fN)[0];

			featureValue -= lowestFeatureValue[featNum];

			double colorIndex = featureValue * colorMultipliers[featNum];
			
			Color c = colormap.table[(int)colorIndex];
			
			if (!cVI.selected)
				c = c.darker().darker().darker();
				
			graphics.setColor(c);
			
			int yLocal = (int)(Math.round((y + h) - (i * yIncr)));
	
			int miniBlipHeight = (int)(Math.round(yIncr));
			if (miniBlipHeight == 0)
				miniBlipHeight = 1;
			
			//System.out.println("eN: " + elementNum + " x: " + x + " yLocal: " + yLocal + " w: " + w + " miniBlipHeight: " + miniBlipHeight);
			
			graphics.fillRect(x, yLocal, w, miniBlipHeight);
		}
		
	}
	
	public Vector getChunkVisInfosForPoint(Point p)
	{
		Vector chunks = new Vector();
		
		for (int i = 0; i < events.size(); i++)
		{
			ChunkVisInfo c = (ChunkVisInfo) events.elementAt(i);
			if (p.x >= c.xFeat && p.x <= (c.xFeat + c.width))
			{
				chunks.add(c);
			}
		}

		return chunks;
	}
		
	public int getFeatureNumberForPoint(Point p)
	{
		int featureNumber = -1;
		
		if (featFile != null)
		{
			int graphHeight = (int)(currHeight/numFeatures);
			
			for (int i = 0; i < numFeatures; i++)
			{
				int low = (int)(currHeight - (i * graphHeight)) - graphHeight;
				int high = (int)(currHeight - (i * graphHeight));
				if (p.y >= low && p.y <= high)
					featureNumber = i;
			}
		}
		return featureNumber;
	}
	
	public String getFeatureNameForPoint(Point p)
	{
		String featureName = "i don't know!";
		
		int whichFeature = getFeatureNumberForPoint(p);
		
		if (whichFeature != -1)
		{
			String fullFeatureName = (String) featFile.featureDescriptions.elementAt(whichFeature);
			//we're splitting on "." but have to use an escape sequence!
			String[] chunks = fullFeatureName.split("\\.");
			featureName = chunks[chunks.length-1];
		}
			
		return featureName;	
	}

	public double getFeatureValueForPoint(Point p)
	{
		double value = 0.0;
		
		int whichFeature = getFeatureNumberForPoint(p);
		
		if (whichFeature != -1)
		{
			for (int i = 0; i < events.size(); i++)
			{
				ChunkVisInfo cVI = (ChunkVisInfo) events.elementAt(i);
					
				if (p.x >= cVI.xFeat && p.x <= (cVI.xFeat + cVI.width))
				{
					int[] featNum = {0};
					
					for (int j = 0; j < whichFeature; j++)
						featNum[0] += elementsPerFeature[j];
					value = cVI.getFeatures(featNum)[0];
					return value;
				}
			}
		}
		
		return value;
	}
	
	public void rangeFilterSelectionChanged()
	{
	}
	
	public void setDragRect(Rectangle r, boolean dS)
	{
		dragRect = r;
		dragShift = dS;
		
		if (!dragShift)
		{
			selectNone();
		}
		
		for (int i = 0; i < events.size(); i++)
		{
			ChunkVisInfo cVI = (ChunkVisInfo)events.elementAt(i);
			Rectangle chunkRect = null;
			
			if (sOptions.getSelectedIndex() == 0)
			{
				chunkRect = new Rectangle(cVI.xFeat, cVI.yFeat, cVI.width, cVI.height);
			}
			else
			{
				chunkRect = new Rectangle(cVI.xEDL, cVI.yEDL, cVI.width, cVI.height);
			}
			if ((dragRect.x >= chunkRect.x && 
				dragRect.x <= chunkRect.x + chunkRect.width) ||
				(dragRect.x + dragRect.width >= chunkRect.x && 
				dragRect.x + dragRect.width <= chunkRect.x + chunkRect.width) ||
				(dragRect.x <= chunkRect.x && 
				dragRect.x + dragRect.width >= chunkRect.x + chunkRect.width))
				cVI.selected = true;
		}
		
		dragRect = null;
		dragShift = false;
		
		drawingPanel.repaint();	
	}
	/*
	public void actionPerformed(ActionEvent arg0)
	{		
		Object source = arg0.getSource();
		String command = arg0.getActionCommand();
		
		super.actionPerformed(arg0);
	}
	*/
	public JPanel buildGUI(Color bgColor)
	{
		
		JPanel panel = super.buildGUI(bgColor);
		
		JPanel hSPanel = new JPanel();
		hSPanel.setBackground(bgColor);
		hSPanel.setLayout(new BoxLayout(hSPanel, BoxLayout.Y_AXIS));
		
		JLabel hCL = new JLabel("height: ");
		hCL.setBackground(bgColor);
		hSPanel.add(hCL);
		
		String[] heightOptions = {"start time", "dest time", "length", "feature value"};
		
		hOptions = new JComboBox(heightOptions);
		hOptions.setBackground(bgColor);
		hOptions.setActionCommand("hOptions");
		hOptions.setSelectedIndex(2);
		hOptions.addActionListener(this);
		hSPanel.add(hOptions);
		
		JLabel sCL = new JLabel("show: ");
		sCL.setBackground(bgColor);
		hSPanel.add(sCL);
		
		String[] showOptions = {"feat file", "EDL file"};
		
		sOptions = new JComboBox(showOptions);
		sOptions.setBackground(bgColor);
		sOptions.setActionCommand("sOptions");
		sOptions.addActionListener(this);
		hSPanel.add(sOptions);
		
		controlsPanel.add(hSPanel);
		
		return panel;
	}


}



