//package arpClasses.Drawing;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
 *     Canvas for road map include all the map function
 *     @author Alan Sheung Chi Mak
 */
public class DrawingCanvas extends Canvas {
   int currentRangeX;
   int currentRangeY;
   double scale;
   public int xmin,ymin,xmax,ymax;
   
   PolyLine polyline;
   Vector data;
   Vector result;
   
   public DrawingCanvas(Vector p) {
   	this.data = p;
    xmax = shapeExtractor.XMAX;
    ymax = shapeExtractor.YMAX;
    xmin = shapeExtractor.XMIN;
    ymin = shapeExtractor.YMIN;
   	updateScale();
   }	

    // Paint all the agents
   public void paint(Graphics g) {
   	//long startTime = System.currentTimeMillis();
   	Font f = new Font("SansSerif", Font.PLAIN, 8);
   	  g.setFont(f);
   	  FontMetrics fm=g.getFontMetrics();
      PolyLine record;
      String name = "";
      int [] box;
      for (int i =1;i<33144;i++){
      	record = (PolyLine)data.elementAt(i);
      	box =record.getBox();
      	if(!(box[2]<xmin)||(box[0]>xmax)||(box[3]<ymin)||(box[1]>ymax)){
      	  if(record.getLevel()==2){       //motorway or highway
      		  g.setColor(Color.red);
      	  }
      	  else if(record.getLevel()==1){
      		  g.setColor(Color.orange);       //normal road
      	  }
      	  else{
      	  	g.setColor(Color.green);
      	  }
      	  name=record.getName();
      	
      	  g.drawPolyline(scaleX(record.getXs()),scaleY(record.getYs()),record.getNumPoints());
      	  if(xToIC(box[2])-xToIC(box[0])>fm.stringWidth(name)){
      		  g.setColor(Color.black);
          		//System.out.println(name);
      		  g.drawString(name,xToIC((box[2]+box[0])/2)-fm.stringWidth(name)/2,yToIC((box[1]+box[3])/2));
      		  //g.drawString(name,xToIC(record.getCentreX())-fm.stringWidth(name)/2,yToIC(record.getCentreY())-fm.getHeight()/2);
      	  }
      	}
      	
      }
      g.setColor(Color.black);
      for (int i =33144;i<data.size();i++){
      	record = (PolyLine)data.elementAt(i);
      	g.drawPolyline(scaleX(record.getXs()),scaleY(record.getYs()),record.getNumPoints());
      	
      }
      if(result!=null){
      	Integer id;
        g.setColor(Color.blue);
        for (int i=0;i<result.size();i++){
        	id = (Integer)result.elementAt(i);
      	  record = (PolyLine)data.elementAt(id.intValue());
      	  g.drawPolyline(scaleX(record.getXs()),scaleY(record.getYs()),record.getNumPoints());
      	}
      }
      //mapInterface.export();
      //long runTime = System.currentTimeMillis() - startTime;
      //System.out.println("runTime = " + runTime);
   }
   
   public int[] scaleX(int[] input){
   	int[] x = new int[input.length];       
      for (int i =0;i<input.length;i++){
      	x[i] = xToIC(input[i]);
      }
      return x;
   }
   private int xToIC(int x){
   	   return (int)((x-xmin)/scale);
   }
   public int[] scaleY(int[] input){
   	int[] y = new int[input.length];       
      for (int i =0;i<input.length;i++){
      	   y[i] = yToIC(input[i]);	
      }
      return y;
   }
   private int yToIC(int y){
   	   return (int)((currentRangeY-y+ymin)/scale);
   }
   public void zoonIn(){
   	int[] box = new int[4];
   	int dX = currentRangeX/4;
   	int dY = currentRangeY/4;
   	xmin += dX;
   	ymin += dY;
   	xmax -= dX;
   	ymax -= dY;
   	//System.out.println("xmax ="+xmax+" ; ymax ="+ymax);
   	updateScale();
   }
   public void zoonOut(){
   	int dX = currentRangeX/2;
   	int dY = currentRangeY/2;
   	xmin -= dX;
   	if(xmin<shapeExtractor.XMIN){
   		xmin=shapeExtractor.XMIN;
   	}
   	ymin -= dY;
   	if(ymin<shapeExtractor.YMIN){
   		ymin=shapeExtractor.YMIN;
   	}
   	xmax += dX;
   	if(xmax>shapeExtractor.XMAX){
   		xmax = shapeExtractor.XMAX;
   	}
   	ymax += dY;
   	if(ymax>shapeExtractor.YMAX){
   		ymax = shapeExtractor.YMAX;
   	}
      updateScale();
   }
   public void reset(){
   	xmax = shapeExtractor.XMAX;
      ymax = shapeExtractor.YMAX;
      xmin = shapeExtractor.XMIN;
      ymin = shapeExtractor.YMIN;
      updateScale();
   }
   public void viewCity(){
   	  xmin = 2655000;
   	  xmax = 2682000;
      ymin = 6465000;
      ymax = 6492000;
      updateScale();
   }
   public void toEast(){
   	xmax += currentRangeX/2;
   	if(xmax>shapeExtractor.XMAX){
   		xmax = shapeExtractor.XMAX;
   	}
   	xmin = xmax - currentRangeX;
   	updateScale();
   }
   public void toWest(){
   	xmin -= currentRangeX/2;
   	if(xmin<shapeExtractor.XMIN){
   		xmin = shapeExtractor.XMIN;
   	}
   	xmax = xmin + currentRangeX;
   	updateScale();
   }
   public void toNorth(){
   	ymax += currentRangeY/2;
   	if(ymax>shapeExtractor.YMAX){
   		ymax = shapeExtractor.YMAX;
   	}
   	ymin = ymax - currentRangeY;
   	updateScale();
   }
   public void toSouth(){
   	ymin -= currentRangeY/2;
   	if(ymin<shapeExtractor.YMIN){
   		ymin = shapeExtractor.YMIN;
   	}
   	ymax = ymin + currentRangeY;
   	updateScale();
   }
   public void focusArea(int x, int y){
      int centreX=xmin + (int)(x*scale);
   	  int centreY=ymin - (int)(y*scale) + currentRangeY;
   	  System.out.println("currentX ="+centreX+" currentY ="+centreY);
   	  //System.out.println("xmin ="+xmin+" ;xmax ="+xmax);
   	  xmin = centreX - currentRangeX/2;
   	  xmax = centreX + currentRangeX/2;
      ymin = centreY - currentRangeY/2;
   	  ymax = centreY + currentRangeY/2;
   	  //System.out.println("xmin ="+xmin+" ;xmax ="+xmax);
   	  updateScale();
   } 
   public void updateScale(){
   	int width=getWidth(); int height = getHeight();
   	currentRangeX = xmax - xmin;
    currentRangeY = ymax - ymin;
    if(width==0)
    	width=470;
    if(height==0)
    	height=470;
    //System.out.println("width ="+width);	
    scale = max(1.0*currentRangeX/width,1.0*currentRangeY/height);
    
    //ymax = ymin - (int)(height*scale) + currentRangeY;
    //System.out.println("currentX ="+currentRangeX+" ;currentY ="+currentRangeY);
    //System.out.println("us "+xmin+";"+ymin+";"+xmax+";"+ymax);
    repaint();
    //xmax = xmin + (int)(width*scale);
    //currentRangeX = xmax - xmin;
   }
   private double max(double a, double b){
   	if(a>b)   	
   	  return a;
   	else
   	  return b;
   }//end method max
   public void setResult(Vector result){
   	  this.result=result;
   }
      
}