package net.soupgames.guimark2;

/**
 * GuiMark2 Vector in Java.
 * Version 1.0
 *
 * Written by Jesper Juul, www.jesperjuul.net
 * 
 * This is a quick port from HTML5/JavaScript to Java 1.5.
 * 
 *  Results on my 2007 Thinkpad T60p, running Windows XP, Java 1.6.0_20:
 *  HTML Firefox: 12 FPS
 *  Flash: 22 FPS
 *  Java 20 FPS
 *
 */
import java.applet.Applet;
import java.awt.BasicStroke;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Label;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferStrategy;
import java.util.Vector;

public class vector extends Applet implements Runnable, ActionListener {




	final static int W = 1200, H = 600, XPOS = 0, YPOS = 40;

	private Thread thread = null;
	private static final long serialVersionUID = 1882731086792923772L;


	MediaTracker mt;
	Label meterlabel;
	FPSMeter meter = new FPSMeter();
	Button starttestbutton;
	double fps;
	Canvas drawcanvas;


	private Label testresult;

	private BufferStrategy bufferstrategy;

	
	//Start timer at next update
	private Boolean starttest=false;
	
	
	int highestStock = 200;
	int totalMinutes = 480;
	float chartXSpread;
	float chartYSpread;
	Vector<StockVO> a = new Vector<StockVO>();
	Vector<StockVO> b = new Vector<StockVO>();
	Vector<StockVO> c = new Vector<StockVO>();
	Vector<StockVO> d = new Vector<StockVO>();
	Vector<StockVO> e = new Vector<StockVO>();


	@Override
	public synchronized void start() {

		if (thread == null) {
			thread = new Thread(this);
			thread.start();
		}
	}

	@Override
	public synchronized void stop() {
	}

	synchronized void initGraphics() {


		setLayout(null);

		Label title = new Label("GuiMark2 Java Vector Test");
		title.setBounds(getInsets().left + 10, 10 + getInsets().top, 300, 20);
		Font f = getFont();
		title.setFont(new Font(f.getName(), Font.BOLD, f.getSize()));
		add(title);

		meterlabel = new Label("FPS label");
		meterlabel.setBounds(getInsets().left + 400, 10 + getInsets().top, 200,
				20);
		add(meterlabel);

		testresult = new Label("");
		testresult.setBounds(getInsets().left + 600, 10 + getInsets().top, 200,
				20);
		add(testresult);

		starttestbutton = new Button("Start Test");
		starttestbutton.setBounds(getInsets().left + 800, 10 + getInsets().top,
				100, 20);
		add(starttestbutton);
		starttestbutton.addActionListener(this);


		drawcanvas = new Canvas();
		drawcanvas.setSize(W, H);
		drawcanvas.setLocation(XPOS + getInsets().left, YPOS + getInsets().top);
		add(drawcanvas);

		drawcanvas.createBufferStrategy(2);

		bufferstrategy = drawcanvas.getBufferStrategy();

	}
	
	synchronized void processFrame() {

		Graphics2D draw = (Graphics2D) bufferstrategy.getDrawGraphics();
		draw.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
		RenderingHints.VALUE_ANTIALIAS_ON);
		
		draw.setColor(new Color(0xffffff));
		draw.fillRect(0,0,W,H);

		draw.setColor(new Color(0x666666));

		double xCoord;
		double yCoord;
		for(int x=0; x<=totalMinutes; x+=40){
			xCoord = x*chartXSpread+0.5;
			draw.drawLine((int)xCoord, 0, (int)xCoord, H);
		}
		for(int y=0; y<=highestStock; y+=20){
			yCoord = y*chartYSpread+0.5;
			draw.drawLine(0,(int)yCoord, W, (int)yCoord);
		}

		fillStockData(a, 180);
		fillStockData(b, 140);
		fillStockData(c, 100);
		fillStockData(d, 60);
		fillStockData(e, 20);

		graphStockData(draw,a, b, 0xFF00FF, new Color(255, 176, 255, (int) (0.6*255)));
		graphStockData(draw,b, c, 0xFF0000, new Color(255, 176, 176, (int) (0.6*255)));
		graphStockData(draw,c, d, 0xFF6600, new Color(255, 216, 176, (int) (0.6*255)));
		graphStockData(draw,d, e, 0x0000FF, new Color(176, 176, 255, (int) (0.6*255)));
		graphStockData(draw,e, null, 0x00FF00, new Color(176, 255, 176, (int) (0.6*255)));
		
		// Buffer strategy version
		draw.dispose();
		bufferstrategy.show();

		updatePerformance();
	}

	private void graphStockData(Graphics2D draw, Vector<StockVO> topData, Vector<StockVO> bottomData, int line,
			Color fill) {
		StockVO stock;
		float  xCoord;
		float yCoord;
		int i = 0;
		
	
		GeneralPath path = 
			new GeneralPath(GeneralPath.WIND_EVEN_ODD, topData.size()+100);
		path.moveTo(0,0);
		
		stock = topData.get(i);
		xCoord = stock.minute*chartXSpread;
		yCoord = H-stock.value*chartYSpread;
		path.lineTo(xCoord, yCoord);

		while(++i < topData.size()){
			stock = topData.get(i);
			xCoord = stock.minute*chartXSpread;
			yCoord = H-stock.value*chartYSpread;
			path.lineTo(xCoord, yCoord);
		}

		draw.setColor(new Color(line));
		draw.setStroke(new BasicStroke(2,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
	   draw.draw(path);

	   
		if(bottomData != null){
			i = bottomData.size();
			while(--i > -1){
				stock = bottomData.get(i);
				xCoord = stock.minute*chartXSpread;
				yCoord = H-stock.value*chartYSpread;
				path.lineTo(xCoord, yCoord);
			}
		}else
		
		{
			path.lineTo(W, H);
			path.lineTo(0, H);
		}
		draw.setColor(fill);
		draw.fill(path);
		
	}

	void updatePerformance() {
		meter.increment();
		if (testRunning) {
			continueTest();
		}
		meterlabel.setText("Current: " + meter.getFramerate() + " fps");
	}

	// test runner
	long testBegin = 0;
	Vector<Long> testData = new Vector<Long>();

	boolean testRunning = false;

	synchronized void startTest() {
		testBegin = System.currentTimeMillis();
		testRunning = true;
		// testData = [];
		testData.removeAllElements();
		testresult.setText("Running...");
	}

	synchronized void continueTest() {
		long time = System.currentTimeMillis();
		testData.add(time);
		if (time - testBegin > 10000) {
			testRunning = false;
			double output = ((double) testData.size() / (double) (time - testBegin)) * 1000;
			testresult.setText("Test Average: " + meter.formatNumber(output)
					+ " fps");
		}
	}

	class FPSMeter {
		String sampleFPS = "0";
		long lastSampledTime = 0;
		int sampleFrames = 0;

		int sampleDuration = 500;

		void increment() {
			sampleFrames++;
		}

		String getFramerate() {
			double diff = System.currentTimeMillis() - lastSampledTime;
			if (diff >= sampleDuration) {
				double rawFPS = sampleFrames / (diff / 1000);
				sampleFPS = formatNumber(rawFPS);
				sampleFrames = 0;
				lastSampledTime = System.currentTimeMillis();
			}
			return sampleFPS;
		}

		String formatNumber(double rawFPS) {
			// format as XX.XX
			return "" + Math.floor(rawFPS * 100) / 100;
		}
	}

	long startTime = System.currentTimeMillis();

	synchronized long getTimer() {
		return System.currentTimeMillis() - startTime;
	}

	public void run() {
		setupData();

		initGraphics();
		while (true) {
			processFrame();
	
			synchronized(starttest)
			{
				if (starttest)
				{
					starttest=false;
				startTest();
				}
			}
		}
	}

	private void setupData() {
		chartXSpread = (float)W/totalMinutes;
		chartYSpread = (float)H/highestStock;
	}

	void fillStockData(Vector<StockVO> data, int region){
		int diff = 15;
		int low = region-(diff/2);
		int i = 0;
		StockVO stock;
		
		if(data.size() == 0){
			while(i <= totalMinutes){
				stock = new StockVO(i, (float) (Math.random()*diff+low));
				data.add(stock);
				i++;
			}
		}else{
			while(i <= totalMinutes){
				stock = data.elementAt(i);
				stock.minute--;
				i++;
			}
			stock = data.firstElement();
			data.removeElementAt(0);
			stock.minute = totalMinutes;
			stock.value = (float) (Math.random()*diff+low);
			data.add(stock);
		}
	}
	
	//additional classes
	class StockVO
	{
		int minute;
		float value;
		
		StockVO (int minute, float value){
		this.minute = minute;
		this.value = value;
		}
	}


	// When a button is pushed
	public  void actionPerformed(ActionEvent evt) {
		if (evt.getSource() == starttestbutton) {
			synchronized(starttest)
			{
				starttest=true;
			}
		}

	}
	
	}



