
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.geom.Point2D;


import java.io.*;
import java.util.ArrayList;

public class Node 
{

	public static int    		RADIUS = 50;
    private String              label;
    private Point2D             location;
    private ArrayList<EdgeObj>  incidentEdges;
    private boolean             selected;
    private boolean				loopback_status;
    private boolean				reset_status;
    
    private Color				state_color;
    private Color				text_color;
    private String 				expression;
    private boolean				visible_name;
    private boolean				visible_expression;
    
    
    // static pour le chargement d'un fichier
    private  LoopbackObj 		loop_obj;
 //   private ArrayList<LoopbackObj>  loopback;
    
    public Node() 
    { 
    	this("", new Point2D.Double(0,0)); 
    	
    	this.state_color = Color.BLACK;
    	this.text_color = Color.BLACK;
    }
    
    public Node(String aLabel) 
    { 
    	this(aLabel, new Point2D.Double(0,0) {}); 
    	
    	this.state_color = Color.BLACK;
    	this.text_color = Color.BLACK;
  	}

    public Node(Point2D aPoint)
    { 
    	this("", aPoint);
    	
    	this.state_color = Color.BLACK;
    	this.text_color = Color.BLACK;
   	}
    
    public Node(double x, double y) 
    { 
    	this("", new Point2D.Double(x,y)); 
    	
    	this.state_color = Color.BLACK;
    	this.text_color = Color.BLACK;
   	}
    
    public Node(String aLabel, Point2D aPoint) 
    {
        label = aLabel;
        location = aPoint;
        incidentEdges = new ArrayList<EdgeObj>();
        selected = false;
        loopback_status = false;
        reset_status = false;
        
        expression = "not define";
        visible_name = true;
        visible_expression = true;
                
    	this.state_color = Color.BLACK;
    	this.text_color = Color.BLACK;
    	
        int radius = 50;
        int x1  = (int) (location.getX() - RADIUS);
        int y1  = (int) (location.getY() - RADIUS);
        int x2  = (int) (location.getX() + RADIUS);
        int y2 =  (int) (location.getY() + RADIUS);
        
        loop_obj = new LoopbackObj( label, (int)location.getX(), (int)location.getY(), x1, y1,  x2,  y2);
        
        //loop_obj = new LoopbackObj();
        
    }
    
    public ArrayList<EdgeObj> incidentEdges() { return incidentEdges; }
    public void addIncidentEdge(EdgeObj e) { incidentEdges.add(e); }
    
    public String getLabel() { return label; }
    public void setLabel(String newLabel) { label = newLabel; }
        
    public String getExpression() { return expression; }
    public void setExpression(String val) { expression = val; }
    
    public Point2D getLocation() { return location; }
    public void setLocation(Point2D aPoint) { location = aPoint; }
    public void setLocation(double x, double y) { location = new Point2D.Double(x, y); }

    public boolean isSelected() { return selected; }
    public void setSelected(boolean state) { selected = state; }
    public void setUnSelected(boolean state) { selected = state; }
    
    public void setVisible_name(boolean val) { visible_name = val; }
    public boolean getVisible_name() { return  visible_name; }
    
    public void setVisible_expression(boolean val) { visible_expression = val; }
    public boolean getVisible_expression() { return  visible_expression; }
    
    
    public LoopbackObj getLoopBack()
    {
    	return loop_obj;
    }
    
    public void toggleSelected() { selected = !selected; }

    
    public void LoopToggleSelected() 
    { 
    	loopback_status = !loopback_status; 
   	}
   
    public void Set_loopback_status(boolean state)
    {
    	loopback_status = state;
    }

    public boolean Get_loopback_status()
    {
    	return loopback_status;
    }
    

    public void Set_reset_status(boolean state)
    {
    	reset_status = state;
    }

    public boolean Get_reset_status()
    {
    	return reset_status;
    }
    
    public LoopbackObj getloopback() 
    { 
    	return loop_obj; 
    }
    
    public void setLoop(LoopbackObj obj) 
    { 
    	loop_obj = obj;
   	}
    
/*
    public ArrayList<Node> neighbours() 
    {
        ArrayList<Node> result = new ArrayList<Node>();

        for (EdgeObj e: incidentEdges)
            result.add(e.otherEndFrom(this));

        return result;
    }
*/
    public String toString() 
    {
        return(label + "(" + location.getX() + "," + location.getY() + ")");
    }
    
    public void draw(Graphics g) 
    {

		int widthInPixels = 0;
		int heightInPixels = 0;
    	
    	if (selected)
            g.setColor(Color.RED);
    	else
            g.setColor(getStateColor());
    	               
        g.drawOval((int)location.getX() - RADIUS, (int)location.getY() - RADIUS, RADIUS*2, RADIUS*2);
        
        // reset sur le state
        if(	reset_status == true)
        {
        	  int rayon = RADIUS - 5;	
        	  g.drawOval((int)location.getX() - rayon, (int)location.getY() - rayon, rayon*2, rayon*2);
        }
        
        if(visible_expression == true)
        {
        	g.setColor(getTextColor());
        	Font myFont = new Font("Arial", 1, 14);
        	g.setFont(myFont);
        	Font currentFont = g.getFont();
    		FontMetrics fm = g.getFontMetrics( currentFont );
    		widthInPixels = fm.stringWidth(expression);
    		heightInPixels = fm.getHeight();
	 	    g.drawString(expression, (int)location.getX() - (widthInPixels /2), (int)location.getY() + (heightInPixels / 2) );
        }
        
        if(visible_name == true)
        { 	g.setColor(getTextColor());
        	Font myFont = new Font("Arial", 1, 14);
        	g.setFont(myFont);
        	g.drawString(label, (int)location.getX() + RADIUS, (int)location.getY() - RADIUS);
        }	
    }

    public void saveTo(PrintWriter aFile) 
    {
        aFile.println(label);
        aFile.println((int)location.getX());
        aFile.println((int)location.getY());
        aFile.println(selected);
        
        aFile.println(expression);
        aFile.println(visible_name);
        aFile.println(visible_expression);
        
        aFile.println(loopback_status);
        
		aFile.println((int) loop_obj.startPt.x );
		aFile.println((int) loop_obj.startPt.y );
		aFile.println((int) loop_obj.endPt.x );
		aFile.println((int) loop_obj.endPt.y );
			        	
		aFile.println((int) loop_obj.startCtrlPt.x );
		aFile.println((int) loop_obj.startCtrlPt.y );
		aFile.println((int) loop_obj.endCtrlPt.x );
		aFile.println((int) loop_obj.endCtrlPt.y );
		
		aFile.println((int) loop_obj.xTemp );
		aFile.println((int) loop_obj.yTemp );
		aFile.println((int) loop_obj.tempSI );
		aFile.println((int) loop_obj.tempEI );
		aFile.println((int) loop_obj.startStateIndex );
		aFile.println((int) loop_obj.endStateIndex );
		aFile.println((int) loop_obj.lengthS );
		aFile.println((int) loop_obj.lengthE );
		aFile.println(Double.toString(loop_obj.ctrlAngleS) ) ;
		aFile.println(Double.toString(loop_obj.ctrlAngleE) ) ;
        	
        aFile.println(reset_status);
        aFile.println( format_couleur( state_color ) );
        aFile.println( format_couleur( text_color ) );

    }
    
    public String format_couleur(Color c)
    {
    	  int r = c.getRed();
          int g = c.getGreen();
          int b = c.getBlue();
          String RGBColor = Integer.toString(r) + "-" +  Integer.toString(g) + "-" +  Integer.toString(b); 
    	  // chaine R-G-B
          return RGBColor;
    }
    
    public static Node loadFrom(BufferedReader aFile) throws IOException 
    {
        Node   aNode = new Node();
        
        String label = aFile.readLine();
        
        aNode.setLabel(label);
        aNode.loop_obj.setLabel(label);
        
        aNode.setLocation(Integer.parseInt(aFile.readLine()), Integer.parseInt(aFile.readLine()));
        aNode.setSelected(Boolean.valueOf(aFile.readLine()).booleanValue());
        
        
        aNode.setExpression(aFile.readLine());
        aNode.setVisible_name(Boolean.valueOf(aFile.readLine()).booleanValue());
        aNode.setVisible_expression(Boolean.valueOf(aFile.readLine()).booleanValue());
        
        
        aNode.Set_loopback_status(Boolean.valueOf(aFile.readLine()).booleanValue());
        
        aNode.loop_obj.setStartPt( Integer.parseInt(aFile.readLine()), Integer.parseInt(aFile.readLine()));
        aNode.loop_obj.setEndPt( Integer.parseInt(aFile.readLine()), Integer.parseInt(aFile.readLine()));
        aNode.loop_obj.setStartCtrlPt( Integer.parseInt(aFile.readLine()), Integer.parseInt(aFile.readLine()));
        aNode.loop_obj.setEndCtrlPt( Integer.parseInt(aFile.readLine()), Integer.parseInt(aFile.readLine()));
    
        
        aNode.loop_obj.xTemp = Integer.parseInt(aFile.readLine());
        aNode.loop_obj.yTemp = Integer.parseInt(aFile.readLine());
        
        aNode.loop_obj.tempSI = Integer.parseInt(aFile.readLine());
        aNode.loop_obj.tempEI = Integer.parseInt(aFile.readLine());

        aNode.loop_obj.startStateIndex = Integer.parseInt(aFile.readLine());
        aNode.loop_obj.endStateIndex = Integer.parseInt(aFile.readLine());

       
        
        aNode.loop_obj.lengthS = Integer.parseInt(aFile.readLine());
        aNode.loop_obj.lengthE = Integer.parseInt(aFile.readLine());
        
        aNode.loop_obj.ctrlAngleS = Double.parseDouble(aFile.readLine());
        aNode.loop_obj.ctrlAngleE = Double.parseDouble(aFile.readLine());
        
        aNode.loop_obj.x0 = (int) (aNode.getLocation().getX() - RADIUS);
        aNode.loop_obj.y0  = (int) (aNode.getLocation().getY() - RADIUS);
        aNode.loop_obj.x1  = (int) (aNode.getLocation().getX() + RADIUS);
        aNode.loop_obj.y1 =  (int) (aNode.getLocation().getY() + RADIUS);
        
      //  loop_obj = new LoopbackObj( aNode.getLabel() , (int) (aNode.getLocation().getX()), (int) (aNode.getLocation().getY()) , x1, y1,  x2,  y2);
        //loop_obj = new LoopbackObj( aNode.getLabel() , pt_setStartPt, pt_setEndPt, pt_setStartCtrlPt,  pt_setEndCtrlPt );
        
        aNode.loop_obj.chargement();
        
        aNode.Set_reset_status(Boolean.valueOf(aFile.readLine()).booleanValue());
        
        Color tmpcolor = null;
        String[] tokens = null;
        
        // pour la couleur du state
        tokens = aFile.readLine().split("-");
        tmpcolor =  new Color( Integer.parseInt(tokens[0]) , Integer.parseInt(tokens[1]), Integer.parseInt(tokens[2]));
        aNode.setStateColor(tmpcolor);
        
        // pour la couleur du texte
        tokens = aFile.readLine().split("-");
        tmpcolor =  new Color( Integer.parseInt(tokens[0]) , Integer.parseInt(tokens[1]), Integer.parseInt(tokens[2]));
        aNode.setTextColor(tmpcolor);
        
        return aNode;
    }

    /*
    private Color Color(double d, double d0, double d1) 
    {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }*/
    
    public void recalculation()
    {
    	loop_obj.recalculation();
    }
    
    public void setStateColor(Color c)
	{
		state_color = c;
	}
    
	public Color getStateColor()
	{
		return state_color;
	}
	
	public void setTextColor(Color c)
	{
		text_color = c;
	}
	    
	public Color getTextColor()
	{
		return text_color;
	}
		
}
