/**
	* Graph Class describe graph with Vertices Class and Edges Class
	* this class perform open list algorithm to Graph to find min color
	**/
	
// this Class is a memeber of GCRawData package
package GCRawData;

import java.util.*;
import java.awt.*;

public class Graph 
{
		private Vertices Ver = null;
		private Edges Ed = null;
		private Vertices VerColor = null;
    private ColorTable Ct= null;
		private Stack st = null;
		private Stack st_history = null;
     
		// constructor make Vertices and Edges
		public Graph( Vector argVer, Vector argFrom, Vector argTo ) throws GraphException {
			Ver = new Vertices();
			Ed = new Edges();
      Ct = new ColorTable(argVer.size());
			System.out.println("[Debug] ColorTable size: "+Ct.size());
                        
			for ( int i = 0; i<argVer.size(); i++ )
				Ver.add( (String)argVer.elementAt(i) );
			
			// when two Vectors which describe each vertex of edges have different size
			// throw exception ~
			if ( argFrom.size() != argTo.size() ) throw new GraphException("[Error]not allowed another size of Edge parameter");
			for ( int i = 0; i<argFrom.size(); i++) {
				if ( Ver.containsVer((String)argFrom.elementAt(i)) && Ver.containsVer((String)argTo.elementAt(i)) )
					Ed.add( (String)argFrom.elementAt(i), (String)argTo.elementAt(i) );
				else throw new GraphException("[Error]false edges");
			}
		}
		
		// get minimun color size
		public int getMinColor() throws GraphException {
    	Vertices vt = new Vertices();
      st = new Stack();
      st_history = new Stack();
                        
      // init
      Ct.setStart();
      vt.setColor( vt.add(Ver.getStartVertex()), Ct.getNextColor() );
      st.push( vt );
      st_history.push( vt );
      // perform open list algorith to call openList function
      if ( Ver.size() != 1 && !openList(st) ) throw new GraphException("[Error]have an unexpected problem in Graph.getMinColor()");
      VerColor = (Vertices)st.pop();
                        
			return VerColor.getColorSize();
		}
		
		// get vertices with thier colors
		public Vertices getColorVertices() {
			return new Vertices(VerColor);
		}
		
		// perform open-list algorith to graph
		private boolean openList(Stack st) {
       // init
       Color tmp_color = null;
       System.out.println("[Debug] Graph.getMinColor(): func openList() start");
       String tmp_st = null;
       tmp_st = Ver.getNextVertex();
       int vminSize = 0;
                        
       // select color for each vertex
       do {
       	// init for next vertex
       	// pop 
        Vertices tmp_ver = (Vertices)st.pop();
        Vertices tmp_new_ver = new Vertices( tmp_ver );
        // set ColorTable pointer to First
        Ct.setStart();
        tmp_color  = Ct.getNextColor();
        System.out.println("[Debug] Graph.getMinColor().openList(): Vertex \""+tmp_st+"\" turn");
        //select one color for new vertex
        do {
        	// find first color for vertex
          if ( tmp_new_ver.getVertexFromColor( tmp_color ) == "GC_NULL" ) {
          	tmp_new_ver.add(tmp_st);
            tmp_new_ver.setColor( tmp_st, tmp_color );
          } else {
            String tmp_st2 = tmp_ver.getVertexFromColor( tmp_color );
            
            // find connection between vertex to exist in stack and vertex to insert stack
            while ( !tmp_st2.equals("GC_NULL") ) {                       
            	if ( !Ed.find( tmp_st2, tmp_st ) ) tmp_st2 = tmp_ver.getVertexFromColorNext( tmp_color );
              else {
              	System.out.println("[Debug] Graph.getMinColor().openList(): Vertex "+tmp_st2+" connected to");
                // select other color
                tmp_color = Ct.getNextColor();
                tmp_st2 = tmp_ver.getVertexFromColor( tmp_color );
              }
              System.out.println("[Debug] Graph.getMinColor().openList().tmp_color: "+tmp_color);
              System.out.println("[Debug] Graph.getMinColor().openList().tmp_color2: "+tmp_st2);
            }
            
            //complete new vertices;
            tmp_new_ver.add(tmp_st);
            tmp_new_ver.setColor( tmp_st, tmp_color );
                        
          }
          //push new vertices to the stack
          if ( vminSize == 0 || tmp_new_ver.size() <= vminSize ) {
          	System.out.println("[Debug] Graph.getMinColor().openList()added to Stack");
          	st.push( new Vertices(tmp_new_ver) );
          	st_history.push( new Vertices(tmp_new_ver) );
          	vminSize = tmp_new_ver.size();
          }
          tmp_color = Ct.getNextColor();
        } while ( !tmp_st.equals( tmp_new_ver.getEndVertex() ) && tmp_color != null );
        //end of one vertex
        vminSize = 0;
        tmp_new_ver = new Vertices(tmp_ver);
        tmp_st = Ver.getNextVertex();
      } while ( tmp_st !=  "GC_NULL" );     
                        
      return true;
		}
		
		// return history stack
		public Stack getStack() {
			System.out.println( "[Debug] Graph.getStack stack size: "+st.size() );
			return (Stack)st_history.clone();
		}
		
}