/*
 * Created on Dec 8, 2004
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package jone;

import java.applet.Applet;
//import java.awt.Graphics;

import java.awt.*;

import javax.swing.*;
import java.awt.geom.Rectangle2D;
import java.util.GregorianCalendar;
import java.util.Random;
import java.awt.*;
import java.awt.image.*;
import java.io.*;

import javax.imageio.*;
import javax.swing.*;

/**
/**
 * @author brian
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class FitnessPlotPanel extends JPanel {
	
	private int width = 300;
	private int height = 200;
	private int xStart= 15;
	private int yStart = 35;
	private int totalTimeSteps = 0;
	private int currentTimeStep = 1;
	private int maxTimeStepsToDisplay = 50;
	private int maxFitnessValueToDisplay = 200;
	private int minFitnessValueToDisplay = 0;
	private int numToDisplay = 1;
	private int lastBestSheep = 0;
	private int lastBestWolf = 0;
	private BufferedImage bi;
	private int freqOfPrinting = 200;
	private int numprints = 0;
	private int runNum;
	private static FitnessPlotPanel defaultInstance;
	public static FitnessPlotPanel getInstance()
	{
		if(defaultInstance == null) {
			defaultInstance = new FitnessPlotPanel();
			if(Arena.hasPermissions) {
				defaultInstance.bi = new BufferedImage(defaultInstance.width(), 
						defaultInstance.height(), BufferedImage.TYPE_INT_RGB);   
				Graphics2D g2d = (Graphics2D) defaultInstance.bi.getGraphics();
				g2d.setBackground(Color.white);
				g2d.setStroke(new BasicStroke(5));
				g2d.setColor(Color.white);
				g2d.fillRect(0,0,300,200);
			}
			Random rand = RandomSingleton.getDefaultInstance();
			defaultInstance.runNum = rand.nextInt(100);
			
		}
		return defaultInstance;
	}
	public void paint(Graphics g)
    {
    	super.paint(g);
    	Graphics2D g2d = (Graphics2D) g;	
    }
	
	/*public Graphics getGraphics()
	{
		return bi.getGraphics();
	}*/
	public void clearArea(Graphics g)
	{
		//clear and redraw the border
		if(g != null) {
			// check getX
			try {
				if(Arena.hasPermissions && this.currentTimeStep == this.maxTimeStepsToDisplay &&
						this.totalTimeSteps/freqOfPrinting > numprints) {
					
					//((GregorianCalendar.getInstance()).()).toString()
					File file = new File("D:\\nntest\\test" + 
							this.runNum + 
							"-" + this.numprints + ".jpeg");
					file.createNewFile();
					ImageIO.write(bi,"jpeg",file);
					if(true /* Arena.debug */) {
						File file2 = new File("D:\\nntest\\test" + 
								defaultInstance.runNum + 
								"-" + defaultInstance.numprints + ".txt");
						try {
							BufferedWriter out = new BufferedWriter(new FileWriter(file2));
							out.write(Arena.getInstance().printSummary() + "\n");
							out.write("range of fitness is: " + (this.totalTimeSteps-this.maxTimeStepsToDisplay)
									+ " to " + this.totalTimeSteps + "\n");
							out.write("fitness max = " + this.maxFitnessValueToDisplay + " fitness min = " 
									+ this.minFitnessValueToDisplay + "\n");
							
							out.flush();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					//gbi.clearRect(2,2,width()-4,height()-3);
					numprints++;
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(Arena.hasPermissions) {
				Graphics gbi = bi.getGraphics();
				if(gbi != null) {
						gbi.setColor(Color.white);
						gbi.fillRect(0,0,300,200);
				}
			}
			g.clearRect(2,2,width()-4,height()-3);
		}
		
		this.currentTimeStep = 1;
		//g.clearRect(1,1,1,1);
		//g.drawRect(0,0,width-1,height-1);
	}
	public int width() 
	{
		return width;
	}
	public int height()
	{
		return height;
	}
	public int startX()
	{
		return xStart;
	}
	public int startY()
	{
		return yStart;
	}
	
	public void setMinFitnessWindow(int min)
	{
		this.minFitnessValueToDisplay = min;
		this.clearArea(this.getGraphics());
	}
	public void setMaxFitnessWindow(int max)
	{
		this.maxFitnessValueToDisplay = max;
		this.clearArea(this.getGraphics());
	}
	
	public void setMaxTimeStepsWindow(int timesteps)
	{
		this.maxTimeStepsToDisplay = timesteps;
		this.clearArea(this.getGraphics());
	}
	
	public int getMinFitnessWindow()
	{
		return this.minFitnessValueToDisplay;
	}
	
	public int getMaxFitnessWindow()
	{
		return this.maxFitnessValueToDisplay;
	}
	
	public int getMaxTimeStepsWindow()
	{
		return this.maxTimeStepsToDisplay;
	}
	public void nextTimeStepLine(FitnessGraphInfo fitness)
	{
		if(fitness == null) {
			return;
		}
		Graphics2D g2d = (Graphics2D)this.getGraphics();
		Graphics2D g2dbi = null;
		if(this.bi != null) {
			g2dbi = (Graphics2D) bi.getGraphics();
		}
		/*if(newBestSheep > this.maxFitnessValueToDisplay) {
			newBestSheep = this.maxFitnessValueToDisplay;
		}
		if(newBestSheep < this.minFitnessValueToDisplay) {
			newBestSheep = this.minFitnessValueToDisplay;
		}
		if(newBestWolf > this.maxFitnessValueToDisplay) {
			newBestWolf = this.maxFitnessValueToDisplay;
		}
		if(newBestWolf < this.minFitnessValueToDisplay) {
			newBestWolf = this.minFitnessValueToDisplay;
		}*/
		
		if(this.currentTimeStep == this.maxTimeStepsToDisplay)
		{
			this.clearArea(g2d);
			
			/* draw fitness based on color */
		}
		
		
		int range = (this.maxFitnessValueToDisplay - this.minFitnessValueToDisplay);
		int x, xold, y, yold;
		
		x = (int) Math.round(this.width * (1.0*this.currentTimeStep/this.maxTimeStepsToDisplay)); 
		
		xold = (this.currentTimeStep == 1) ? 0 : (int) 
				Math.round(this.width * (1.0*(this.currentTimeStep-1)/this.maxTimeStepsToDisplay)); ;
		if(fitness.BestSheep != null) {
			g2d.setPaint(Color.blue);
			y = (int) Math.round(height() * 
					 (1 - (1.0*fitness.bestSheepFitness/range)));
			yold = (int) Math.round(height() * 
					 (1 - (1.0*this.lastBestSheep/range)));
			g2d.drawLine(xold,yold,x,y);
			String age = fitness.bestSheepAge + "";
			g2d.drawChars(age.toCharArray(),0,age.toCharArray().length,
					x,y);
			if(g2dbi != null) {
				g2dbi.setPaint(Color.blue);
				g2dbi.drawLine(xold,yold,x,y);
				g2dbi.drawChars(age.toCharArray(),0,age.toCharArray().length,
						x,y); 
			}
			this.lastBestSheep = fitness.bestSheepFitness;
		}
		if(fitness.BestWolf != null) {
			y = (int) Math.round(height() * 
					 (1 - (1.0*fitness.bestWolfFitness/range)));
			yold = (int) Math.round(height() * 
					 (1 - (1.0*this.lastBestWolf/range)));
			this.lastBestWolf = fitness.bestWolfFitness;
			g2d.setPaint(Color.RED);
			
			g2d.drawLine(xold,yold,x,y);
			String age = fitness.bestWolfAge + "";
			g2d.drawChars(age.toCharArray(),0,age.toCharArray().length,
					x,y);
			if(g2dbi != null) {
				g2dbi.setPaint(Color.RED);
				g2dbi.drawLine(xold,yold,x,y);
				g2dbi.drawChars(age.toCharArray(),0,age.toCharArray().length,
						x,y);
			}
		}
		this.currentTimeStep++;
		this.totalTimeSteps++;
	}
	
	public void nextTimeStep(int [][] fitness,Color [] animalColors, int numPopulations) 
	{
		Graphics2D g2d = (Graphics2D) this.getGraphics();
		
		
		if(this.currentTimeStep == this.maxTimeStepsToDisplay)
		{
			this.clearArea(this.getGraphics());
			
			/* draw fitness based on color */
		}
		int x = (int) Math.round(this.width * (1.0*this.currentTimeStep/this.maxTimeStepsToDisplay)); 
		int y;
		g2d.setStroke(new BasicStroke(2));
		for(int i = 0; i < numPopulations; i++) {	
			g2d.setPaint(animalColors[i]); 
			int jth;
			for(int j = 0; j < fitness[i].length && j < this.numToDisplay; j++) {
				jth = fitness[i].length-1-j;
				if(fitness[i][jth] > this.maxFitnessValueToDisplay || fitness[i][jth] < 0)
					continue;
				
				if(fitness[i][jth] == 0)
					continue;
				else {
					 y = (int) Math.round(height() * 
					 (1 - (1.0*fitness[i][jth]/this.maxFitnessValueToDisplay))); 
						
				}
				//g2d.drawRect(5,5,10,10);
				g2d.drawRect(x+2,y,2,2);
				if(Arena.debug)
				{
					//System.out.println("x is " + x + " y is " + y);
					//System.out.println("i is " + i + "fitness is " + fitness[i][j]);
					//Arena.logger.debug("printing sheep at x = " + x + " y = " + y);
				}
				
				
				
				
			}
		}
		this.currentTimeStep++;
		this.totalTimeSteps++;
	}
}
