import java.awt.*;
import java.applet.*;

public class HistoryGraph extends Canvas{
	int YMax, YMin;
	int XMax, XMin;
		// Big and little sizes of the graph.
	int LastX,LastY;
		// For drawing a line.
	int Margin=20;
	int[][] XPoints,YPoints;
	int[] LastPoint;
	int MaxPoints=100;
	boolean NeedsBlanking=false;
		// Set to be true if the background must be filled with white.
	String XLabel,YLabel;
		// What to label the sides.
	int NumGraphs=3;
	int CurrentGraph=0; 
	boolean[] DrawMe;
	Color[] GraphColors;
	int LastUpdatedPoint=-1;
		// To deal with unexpected drawing problems. 
		
	public HistoryGraph(int XMinimum,int XMaximum,int YMinimum, int YMaximum, int Pts){
		super();
		YMax=YMaximum;
		XMax=XMaximum;
		YMin=YMinimum;
		XMin=XMinimum;
		XPoints = new int[Pts][NumGraphs];
		YPoints=new int[Pts][NumGraphs];
		MaxPoints=Pts;
		LastPoint= new int[NumGraphs];
		
		CurrentGraph=0;
		DrawMe=new boolean[NumGraphs];
		GraphColors=new Color[NumGraphs];
		
		for (int i=0; i<NumGraphs; i++){
			DrawMe[i]=false;
			GraphColors[i]=Color.orange;
			LastPoint[i]=-1;
		}
		GraphColors[0]=new Color(241,96,67); 
		GraphColors[1]=new Color(241,166,112);
		GraphColors[2]=new Color(74,102,156);
 	}
	
	public void Cleanup(){
		// Get rid of the old points.
		Dimension d=this.size();
		NeedsBlanking=true;
		repaint();
	//	System.out.println("Running Cleanup in Graph.");
	}
	public Dimension preferredSize(){
		return(new Dimension(Margin+150,170));
	}
	
	public Dimension minimumSize(){
		return(new Dimension(Margin+150,170));
	}
	
	public void setXLabel(String s){
		XLabel=s;
	}
	
	public void setYLabel(String s){
		YLabel=s;
	}
	
	public void changeDays(int NewDays){
		int[][] tempXPoints,tempYPoints;

		if (NewDays>MaxPoints){
			tempXPoints=new int[NewDays][NumGraphs];
			tempYPoints=new int[NewDays][NumGraphs];
			for (int j=0; j<NumGraphs; j++){
				if (DrawMe[j]) {
					for (int i=0; i<NewDays; i++){
						tempXPoints[i][j]=XPoints[i][j];
						tempYPoints[i][j]=YPoints[i][j];
					}}}
			XPoints = tempXPoints;
			YPoints=tempYPoints;
		}
		MaxPoints=NewDays;
		NeedsBlanking=true;
		XMax=NewDays;
	}
	
	public void changeGraphs(){
		// Start a new graph. If you're going to change the number of days, DO IT FIRST!
		CurrentGraph++;
		if (CurrentGraph>=NumGraphs){
			CurrentGraph=0;
		}
		DrawMe[CurrentGraph]=true;
		LastPoint[CurrentGraph]=-1;
		LastUpdatedPoint=1;
	}
	 
	public void update(Graphics g){
		//paint(g);
		
		Color oldColor;
		Dimension d=this.size();
		double Yscale = ((double)(d.height - 2*Margin))/((double)(YMax-YMin));
		double Xscale=((double)(d.width-2*Margin))/((double)(XMax-XMin));
		oldColor=g.getColor();
		if (NeedsBlanking){
			g.setColor(Color.white);
			g.fillRect(0,0,d.width, d.height);
		//	System.out.println("Blanking: width="+d.width+" height="+d.height+" CurrentGraph="+CurrentGraph+"Last Point:"+LastPoint[CurrentGraph]);
			NeedsBlanking=false;
			
			int CurrentGraphColor;
			for (int j=0; j<NumGraphs; j++){
				CurrentGraphColor=CurrentGraph-j;
				if (CurrentGraphColor<0) {CurrentGraphColor +=NumGraphs;}
			g.setColor(GraphColors[CurrentGraphColor]);
			if ((DrawMe[j]) && (j!=CurrentGraph)) {
			//	System.out.println("Updating j="+j+" value="+CurrentGraphColor);
				for (int i=1; i<=LastPoint[j]; i++){
		 	//System.out.println("Updating Point:"+i+" X:"+((int)(Margin+(Xscale*(XPoints[i][j] - XMin))))+" Y:"+ (int)(Margin+(Yscale*(YMax-YPoints[i]))));
				g.drawLine((int)(Margin+(Xscale*(double)(XPoints[i-1][j] - XMin))), 
						(int)(Margin+(Yscale*(double)(YMax-YPoints[i-1][j]))),
						(int)(Margin+(Xscale*(double)(XPoints[i][j] - XMin))), 
						(int)(Margin+(Yscale*(double) (YMax-YPoints[i][j]))));
				}
			}
		}
		}
		g.setColor(Color.black);

		g.drawLine((int)Margin ,(int)(Margin+Yscale*(YMax-0)),(int)(Margin+(Xscale*(XMax-XMin))),(int)(Margin+ Yscale*(YMax-0)));
		g.drawLine((int)(Margin+(Xscale*(0-XMin))),(int)(Margin),(int)(Margin+(Xscale*(0-XMin))),(int)(Margin+Yscale*(YMax-YMin)));
		g.drawString(""+YMax,0,(int)(Margin));
		g.drawString(""+YMin,0,(int)(Margin+Yscale*(YMax-YMin)));
		g.drawString(""+XMin,(int)Margin,(int)(Margin+12+Yscale*(YMax-YMin)));
		g.drawString(""+XMax,(int)(Margin+(Xscale*(XMax-XMin))),(int)(12+Margin+Yscale*(YMax-YMin)));
		
		if (LastPoint[CurrentGraph]>=LastUpdatedPoint) {
			g.setColor(GraphColors[0]);
		// 	System.out.println("Updating Point:"+LastPoint[CurrentGraph]+" X:"+((int)(Margin+(Xscale*(XPoints[LastPoint[CurrentGraph]][CurrentGraph] - XMin))))+" Y:"+ (int)(Margin+(Yscale*(YMax-YPoints[LastPoint[CurrentGraph]][CurrentGraph]))));
			for (int kk=LastUpdatedPoint;kk<=LastPoint[CurrentGraph];kk++){
			g.drawLine((int)(Margin+(Xscale*(double)(XPoints[kk-1][CurrentGraph] - XMin))), 
						(int)(Margin+(Yscale*(double)(YMax-YPoints[kk-1][CurrentGraph]))),
						(int)(Margin+(Xscale*(double)(XPoints[kk][CurrentGraph] - XMin))), 
						(int)(Margin+(Yscale*(double) (YMax-YPoints[kk][CurrentGraph]))));
			
	 		}
	 		LastUpdatedPoint=LastPoint[CurrentGraph];
	 		g.setColor(oldColor);
		}
		} 
	 
	public void paint(Graphics g){
		Color oldColor=g.getColor();
		Dimension d=this.size();
		
		
		double Yscale = ((double)(d.height - 2*Margin))/((double)(YMax-YMin));
		double Xscale=((double)(d.width-2*Margin))/((double)(XMax-XMin)); 
		int CurGraphColor;
		if (NeedsBlanking){
			g.setColor(Color.white);
			g.fillRect(0,0,d.width, d.height);
			NeedsBlanking=false;
			 
			int CurrentGraphColor;
			for (int j=0; j<NumGraphs; j++){
				CurrentGraphColor=CurrentGraph-j;
				if (CurrentGraphColor<0) {CurrentGraphColor +=NumGraphs;}
			g.setColor(GraphColors[CurrentGraphColor]);
			if ((DrawMe[j]) && (j!=CurrentGraph)) {
		//		System.out.println("Updating j="+j+" value="+Math.abs((j-CurrentGraph) % NumGraphs));

				for (int i=1; i<=LastPoint[j]; i++){
		 	//System.out.println("Updating Point:"+i+" X:"+((int)(Margin+(Xscale*(XPoints[i][j] - XMin))))+" Y:"+ (int)(Margin+(Yscale*(YMax-YPoints[i]))));
				g.drawLine((int)(Margin+(Xscale*(double)(XPoints[i-1][j] - XMin))), 
						(int)(Margin+(Yscale*(double)(YMax-YPoints[i-1][j]))),
						(int)(Margin+(Xscale*(double)(XPoints[i][j] - XMin))), 
						(int)(Margin+(Yscale*(double) (YMax-YPoints[i][j]))));
				}
			}
		}
		}
		g.setColor(Color.black);

		
		g.drawString(""+YMax,0,(int)(Margin));
		g.drawString(""+YMin,0,(int)(Margin+Yscale*(YMax-YMin)));
		g.drawString(""+XMin,(int)Margin,(int)(Margin+12+Yscale*(YMax-YMin)));
		g.drawString(""+XMax,(int)(Margin+(Xscale*(XMax-XMin))),(int)(12+Margin+Yscale*(YMax-YMin)));
		
		
	//	System.out.println("Xs:"+Xscale+" Ys:"+Yscale+" LastPoint:"+LastPoint+" Max:"+MaxPoints);
		g.drawLine((int)Margin ,(int)(Margin+Yscale*(YMax-0)),(int)(Margin+(Xscale*(XMax-XMin))),(int)(Margin+ Yscale*(YMax-0)));
		g.drawLine((int)(Margin+(Xscale*(0-XMin))),(int)(Margin),(int)(Margin+(Xscale*(0-XMin))),(int)(Margin+Yscale*(YMax-YMin)));
		int CurrentGraphColor;
		for (int j=0; j<NumGraphs; j++){
			CurrentGraphColor=CurrentGraph-j;
				if (CurrentGraphColor<0) {CurrentGraphColor +=NumGraphs;}
			g.setColor(GraphColors[CurrentGraphColor]);
			
			if (DrawMe[j])  {
	//			System.out.println(" For Painting, DrawMe["+j+"] is true. LastPoint="+Math.abs((j-CurrentGraph) % NumGraphs));
		//	 	System.out.println("NumGraphs="+NumGraphs);
				for (int i=1; i<=LastPoint[j]; i++){
				//System.out.println("Point:"+i+" X:"+((int)(Margin+(Xscale*(XPoints[i][j] - XMin))))+" Y:"+ (int)(Margin+(Yscale*(YMax-YPoints[i][j]))));
				g.drawLine((int)(Margin+(Xscale*(double)(XPoints[i-1][j] - XMin))), 
						(int)(Margin+(Yscale*(double)(YMax-YPoints[i-1][j]))),
						(int)(Margin+(Xscale*(double)(XPoints[i][j] - XMin))), 
						(int)(Margin+(Yscale*(double) (YMax-YPoints[i][j]))));
				}
			}
		}
			g.setColor(oldColor);
	
		}
		
	public void addPoint(int x,int y){
		//Adds a new point to the graph.
		LastPoint[CurrentGraph]++;
		if (LastPoint[CurrentGraph]<=MaxPoints){
			if (x>XMax){
				XPoints[LastPoint[CurrentGraph]][CurrentGraph]=XMax;
			} else if (x<XMin) {
				XPoints[LastPoint[CurrentGraph]][CurrentGraph]=XMin;
			} else {
				XPoints[LastPoint[CurrentGraph]][CurrentGraph]=x;
			};
			if (y>YMax){
				YPoints[LastPoint[CurrentGraph]][CurrentGraph]=YMax;
			} else if (y<YMin) {
				YPoints[LastPoint[CurrentGraph]][CurrentGraph]=YMin;
			} else {
				YPoints[LastPoint[CurrentGraph]][CurrentGraph]=y;
			};
		}
	}
	
}
	

