import java.awt.Graphics2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

public class GraphObj 
{
		private String    			        label;
	 	
		private static ArrayList<ChartObj> list_chartObj = new ArrayList<ChartObj>();

	    
	    // Stroke oldStroke = g2.getStroke();
	    //g2.setStroke(lineStyle.getStroke());

		
	    public GraphObj() 
	    {
	    	this.label = "plouf";
	    	//new ArrayList<ChartObj>();
	    }
	    
	    public GraphObj(String label) 
	    {
	    	this.label = label;
	    }
	    
	/*    
	    public Graph_Node() 
	    {
	    	this("", new ArrayList<Node_Rectangular>()); 	
	    
	    	//new ArrayList<Node_Rectangular>();
	    }
	    

	    public Graph_Node(String name, ArrayList<Node_Rectangular> initialNodes) 
	    {
	        name_state = name;
	        node_rectangles = initialNodes;
	    }
	*/  
	    
	/*    
	    public void addEdge(ChartObj start_obj, ChartObj end_obj) 
	    {
	    	TransitionObj anEdge = new TransitionObj(start_obj, end_obj);
	        start_obj.addIncidentEdge(anEdge);
	        end_obj.addIncidentEdge(anEdge);
	    }
	 */
	    
	    public void addChartObj(ChartObj obj) 
	    {
	    	list_chartObj.add(obj);
	    }
	    
	    public ArrayList<ChartObj> getChartObj() 
	    { 
	    	return list_chartObj; 
	   	}
	    
	    public void draw(Graphics2D g2)
	    {
	    	for (ChartObj obj : list_chartObj)
	        {	   
	    		obj.draw(g2); 
	        }   
	       
  	 ArrayList<TransitionObj> transitions = getTransitions();
	       
	       	for (TransitionObj obj: transitions)  
	       	{
	    	   obj.draw_transition(g2);
	        }

	    }
	    
	    
	    public ChartObj insideObj(int x, int y) 
	    {
	   	
	        for (int i = 0;  i< list_chartObj.size() ; i++)
	        {
	        	ChartObj obj = list_chartObj.get(i); 
	        	
	        	if( obj.getObjType().equals("ACTIVITY_OBJ") )
	        	{
		            int xmin = obj.getX1() ;
		   		 	int ymin = obj.getY1() ;
		   		 	int xmax = xmin + obj.getWidth_Activity(); 
		   		 	int ymax = ymin + obj.getHeight_Activity();
		   		 
		   		 	if(x >= xmin && x <= xmax && y >= ymin && y <= ymax  )
		   		 	{
		   		 		System.out.println("Activity detected.. "); 
		   		 		return obj;
		   		 	}
	        	}	
	        	else
	        	{
	        		  int x1 = obj.getP1().x;
	                  int y1 = obj.getP1().y;
	                  int x2 = obj.getP2().x;
	                  int y2 = obj.getP2().y;
	                  int x3 = obj.getP3().x;
	                  int y3 = obj.getP3().y;
	                  int x4 = obj.getP4().x;
	                  int y4 = obj.getP4().y;
	                  
	                  // triangle 1 : P1 P2 P3
	                  boolean is_inside_triangle1 = isInside(x1 , y1, x2 , y2 , x3 , y3 , x,  y); 
	                  // triangle 1 : P1 P4 P3
	            	  boolean is_inside_triangle2 = isInside(x1 , y1, x4 , y4 , x3 , y3 , x,  y); 
	            	
	            	  if( is_inside_triangle1  == true || is_inside_triangle2 == true )
	            	  {
			   		 		System.out.println("Decision detected.. "); 
			   		 		return obj;
	            	  }
	        	}
	        }
	        
	        return null;
	    }
	    
	    public boolean isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y) 
	    {    
	    	/* Calculate area of triangle ABC */
	    	double A = triangle_area (x1, y1, x2, y2, x3, y3); 
	   
	    	/* Calculate area of triangle PBC */  
	    	double A1 = triangle_area (x, y, x2, y2, x3, y3); 
	   
	    	/* Calculate area of triangle PAC */  
	    	double A2 = triangle_area (x1, y1, x, y, x3, y3); 
	   
	    	/* Calculate area of triangle PAB */   
	    	double A3 = triangle_area (x1, y1, x2, y2, x, y); 
	     
	    	/* Check if sum of A1, A2 and A3 is same as A */
	    	return (A == A1 + A2 + A3); 
	    } 
	   
	    
	    public double triangle_area(int x1, int y1, int x2, int y2,  int x3, int y3) 
	    { 
	    	return Math.abs((x1*(y2-y3) + x2*(y3-y1)+ x3*(y1-y2))/2.0); 
	    } 
    
	    public ArrayList<ChartObj> selectedChartObj() 
	    {
	        ArrayList<ChartObj>   selected = new ArrayList<ChartObj>();
	        for (ChartObj obj:  list_chartObj)
	        {	
	           if (obj.isSelected()) 
	            {
	            	selected.add(obj);
	            }
	       }  
	       return selected;
	    }
	    
	    public String getSelected()
	    {
	        int position = 0;
	        
	        for (ChartObj obj:  list_chartObj)
	        {    
	            if (obj.isSelected())
	            {     
	                  String id = obj.getID();
	                  return(id);  
	            } 
	            position = position + 1;
	        }          
	        
	        return(null);
	    }
	   
	    public ChartObj ChartObjNamed(String id) 
	    {
	        for (ChartObj obj:  list_chartObj)
	        {	
	            if (obj.getID().equals(id))  
	            	return obj;
	        }
	            
	        return null; 
	    }
	    
	    public ArrayList<TransitionObj> getTransitions() 
	    {
	        ArrayList<TransitionObj>  transitions = new ArrayList<TransitionObj>();

	        for (ChartObj obj: list_chartObj) 
	        {
	            for (TransitionObj element: obj.incidentEdges()) 
	            {
	                if (!transitions.contains(element)) 
	                	transitions.add(element);
	            }
	        }
	        return transitions;
	    }
	    
	    public boolean GetTransitionExists(ChartObj start, ChartObj end) 
	    {

	    	String new_start = start.getID();
	    	String new_end = end.getID();
	    	
	    	ArrayList<TransitionObj>  edges = getTransitions();
	    	
	    	if(edges.size() != 0)
	    	{
		    	for (TransitionObj element:  edges) 
		    	{
		    		String exists_start  = element.getStartObj().getID();
		    		String exists_end  = element.getEndObj().getID();
		        	
		    		if( new_start.equals(exists_start)  && new_end.equals(exists_end) )        	
		    		{
		    			return true;
		    		}
		        
		    	}
	    	}	
	    	
	        return false;
	    }
	    
	    public void addTransition(ChartObj start_obj, ChartObj end_obj) 
	    {
	    	String type_transition = "";
	    	
	    	String un = start_obj.getObjType();
	    	String deux = end_obj.getObjType();
	    	
	    	if(start_obj.getObjType().equals("ACTIVITY_OBJ")  && end_obj.getObjType().equals("ACTIVITY_OBJ") )
	    	{
	    		type_transition = "ONLY_ACTIVITY_OBJ";
	    	}
	    	
	    	if(start_obj.getObjType().equals("ACTIVITY_OBJ") && end_obj.getObjType().equals("DECISION_OBJ") )
	    	{
	    		type_transition = "ACTIVITY_DECISION_OBJ";
	    	}
	    	
	    	if(start_obj.getObjType().equals("DECISION_OBJ")  && end_obj.getObjType().equals("ACTIVITY_OBJ") )
	    	{
	    		type_transition = "DECISION_ACTIVITY_OBJ";
	    	}
	    	
	    	if(start_obj.getObjType().equals("DECISION_OBJ")  && end_obj.getObjType().equals("DECISION_OBJ") )
	    	{
	    		type_transition = "ONLY_DECISION_OBJ";
	    	}
	    	
	        TransitionObj obj = new TransitionObj(start_obj, end_obj, type_transition);
	        start_obj.addIncidentEdge(obj);
	        end_obj.addIncidentEdge(obj);
	    }
	    
	    
	    public void deleteChartObj(ChartObj obj) 
	    {
	        for (TransitionObj element:   obj.incidentEdges())
	        	element.otherEndFrom(obj).incidentEdges().remove(element);

	        list_chartObj.remove(obj);  // Remove the node now
	    }
	
	    public TransitionObj insideTransition(int x, int y) 
	    {
	    	for (TransitionObj obj:  getTransitions() )
			{
	    		if( obj.detection_transistion( x, y) == true )
			    {
			    	System.out.println("Transition selected");
	        		return obj;
	        	}
	        }

	    	return null;
	    }

	    
	    public ArrayList<TransitionObj> selectedTransistion() 
	    {
	        ArrayList<TransitionObj>   selected = new ArrayList<TransitionObj>();
	        for (TransitionObj obj:  getTransitions())
	            if (obj.isSelected()) 
	            	selected.add(obj);
	        return selected;
	    }
	    
	    public void deleteTransition(TransitionObj trans) 
	    {
	        trans.getStartObj().incidentEdges().remove(trans);
	        trans.getEndObj().incidentEdges().remove(trans);
	    }
	    
	    public void effacer_tout() 
	    {
	    	 ArrayList<TransitionObj>    trans = getTransitions();
	    	 list_chartObj.clear();
	         trans.clear();
	    }
	    
	    
	    public void saveTo(PrintWriter aFile) 
	    {
	        aFile.println(label);
	       
	        aFile.println(list_chartObj.size());
	        for (ChartObj n:  list_chartObj)
	            n.saveTo(aFile);

	        ArrayList<TransitionObj>    trans = getTransitions();
	       
	        aFile.println(trans.size());
	        for (TransitionObj obj:  trans)
	            obj.saveTo(aFile);
	        
	    }
	    
	    public static GraphObj loadFrom(BufferedReader aFile) throws IOException 
	    {
  	    	GraphObj    aGraph = new GraphObj( aFile.readLine() ); //aFile.readLine());

	        int numObj = Integer.parseInt(aFile.readLine());
	        for (int i=0; i<numObj; i++) 
	        {
	        	ChartObj temp = ChartObj.loadFrom(aFile);
	            aGraph.addChartObj(temp); 
	            
	            //addChartObj(ChartObj obj) 
	            
	        }
	        
	        
	        int numTrans = Integer.parseInt(aFile.readLine());
	        for (int i=0; i<numTrans; i++) 
	        {
	        	TransitionObj temp = TransitionObj.loadFrom(aFile);
	        	String IDStartName = temp.getIDStartObj();
	        	String IDEndName = temp.getIDEndObj();
	        	
	        	ChartObj obj1 = findObjNamed(IDStartName);
	        	ChartObj obj2 = findObjNamed(IDEndName);
	        	
	        	aGraph.addTransition( findObjNamed(IDStartName) , findObjNamed(IDEndName) ); 
	        }
/*	 
	        int numEdges = Integer.parseInt(aFile.readLine());
	        for (int i=0; i<numEdges; i++) 
	        {
	            EdgeObj tempEdge = EdgeObj.loadFrom(aFile);
	            Node start = aGraph.nodeAt(tempEdge.getStartNode().getLocation().getX(),  tempEdge.getStartNode().getLocation().getY());
	            Node end = aGraph.nodeAt(tempEdge.getEndNode().getLocation().getX(),  tempEdge.getEndNode().getLocation().getY());
	            aGraph.addEdge(start, end);
	        }
*/        
	        return aGraph;
	    }
	   
	 /*   
	    public static GraphObj loadFrom(BufferedReader aFile) throws IOException 
	    {
  	    	GraphObj    aGraph = new GraphObj( aFile.readLine() ); //aFile.readLine());

	        int numObj = Integer.parseInt(aFile.readLine());
	        for (int i=0; i<numObj; i++) 
	        {
	        	ChartObj temp = ChartObj.loadFrom(aFile);
	            aGraph.addChartObj(temp); 
	            
	            //addChartObj(ChartObj obj) 
	            
	        }
	        
	        return aGraph;
	    	
	    }
	   */
	    
	    public static ChartObj findObjNamed(String objID) 
	    {
	        for (ChartObj obj:  list_chartObj)
	            if (obj.getID().equals(objID))  return obj;

	        return null;  
	    }
	    
}
