public class Face
{
    //A face contains a list of vertices
    public List faceVertices;
    public Vertex middlePoint=null;
    public double sumOfAngles;
    
    public Face(List vertices, double sum, Vertex mid)
    {
        faceVertices = vertices;
        sumOfAngles = sum;
        middlePoint = mid;
    }

    //this function checks to see if the given vertex is in the list of vertices of the face
    //public boolean isVertexInList(Vertex v)
    public int isVertexInList(Vertex v)
    {
        Vertex thisVertex;
        for (int i = 0; i < faceVertices.length; i++)
        {
            thisVertex = (Vertex)(faceVertices.elements[i]);
            //vertex is found
            if (thisVertex.Compare(v))
                return i;
        }
        //no vertex is found
        return -1;
    }
    
    //compare if two faces are identical, return true if yes or false if not    
    public boolean Compare(Face f)
    {
        Vertex checkVertex;
        int vertCheck = -2;
        
        //if the total number of points of the given face is not equal to the 
        //number of points of this object, the two faces are not identical
        if (f.faceVertices.length != faceVertices.length)
            return false;
        
        //for every points from the given face, check to see if it exists in this object
        for (int i = 0; i < f.faceVertices.length; i++)
        {
            checkVertex = (Vertex)(f.faceVertices.elements[i]);
            //if there is at least one vertex of the given face is not in the list of 
            //this face, the two faces are not identical
            //NOTE: there shouldn't be any two points of a same face has the same 
            //      x and y coordinates
            vertCheck = isVertexInList(checkVertex);
            if (vertCheck < 0)
                return false;
        }
        return true;
    }

    //Given an edge, check to see if the face is adjacent to the edge
    public boolean isEdgeAdjacentToFace(Edge e)
    {
        Vertex startPt, endPt;
        int sCheck = -2, eCheck = -2;
 
        //get the two points of the given edge
        startPt = e.start;
        endPt = e.end;
        sCheck = isVertexInList(startPt);
        eCheck = isVertexInList(endPt);
        
        //check to see if the points are in the list of vertices of this face
        if ((sCheck > 0) && (eCheck > 0))
            return true;
        else
            return false;
    }
    
    public double longestDistance()  
    {
        double dist = 0;
        double distLong = 0;
        Vertex vertexA, vertexB;

        for (int i=0; i<faceVertices.length; i++)
        {
            vertexA = (Vertex)(faceVertices.elements[i]);
            for (int j=0; j<faceVertices.length; j++)
            {
                vertexB = (Vertex)(faceVertices.elements[j]);
                dist = vertexA.distance(vertexB);
                if (distLong < dist)
                    distLong = dist;
            }
        }
        return distLong;
    }        

    //This function compare the two faces to see which face has the longest distance
    //between vertices of the face:
    //  If greater return 1
    //  If equal return 0
    //  If less than return -1
    public int longestDistThan (Face f)
    {
        if (longestDistance() > f.longestDistance())
            return 1;
        else if (longestDistance() == f.longestDistance())
            return 0;
        else
            return -1;
    }

  /***********************************************************/
  /* smallestCoordinate:                                     */       
  /*        Find the smallest coordinate (X or Y) for a      */       
  /*        given face                                       */       
  /***********************************************************/
  private double smallestCoordinate(int direction)
  {
        //if direction = 1 then find the x coordinate
        //if direction = 2 then find the y coordinate
        Vertex v;
        double x = 0, y = 0;
        
        for (int i=0; i < faceVertices.length; i++)
        {
            v = (Vertex)(faceVertices.elements[i]);
            if (i == 0)
            {
                x = v.position.x;
                y = v.position.y;
            }
            else
            {
                if (direction == 1) 
                    if (v.position.x < x)
                        x = v.position.x;                    
                else
                    if (v.position.y < y)
                        y = v.position.y;                
            }
        }
        if (direction == 1)
            return x;
        else 
            return y;
  }

  /***********************************************************/
  /* greatestCoordinate:                                     */       
  /*        Find the greatest coordinate (X or Y) for a      */       
  /*        given face                                       */       
  /***********************************************************/
  private double greatestCoordinate(int direction)
  {
        //if direction = 1 then find the x coordinate
        //if direction = 2 then find the y coordinate
        Vertex v;
        double x = 10, y = 10;
        
        for (int i=0; i < faceVertices.length; i++)
        {
            v = (Vertex)(faceVertices.elements[i]);            
            if (direction == 1) 
                if (v.position.x > x)
                    x = v.position.x;                    
            else
                if (v.position.y > y)
                    y = v.position.y;                
        }
        if (direction == 1)
            return x;
        else 
            return y;
  }

  public void findExtPoints()
  {
        Vertex v;
        //we will be placed a point on the top of the graph
        double x1 = smallestCoordinate (1),         //smallest x
               x2 = greatestCoordinate (1),         //greatest x    
               y1 = smallestCoordinate (2),         //smallest y
               y2 = greatestCoordinate (2);         //greatest y (not used)
        double x,y;
        x = (x1 + x2) / 3;      //1/3
        y = y1 - 20;            //above graph
        v = new Vertex (0,0);
        v.position.x = x;
        v.position.y = y;
        middlePoint = v;    //middle point for external face
  }
  
  public void displayFaceVertices (int faceNumber)
  {      
      Vertex v;
      
      System.out.println  ("****** Vertices for face #" + faceNumber + " ******");
      for (int i = 0; i < faceVertices.length; i++)
      {
          v = (Vertex)(faceVertices.elements[i]);
          System.out.println("... vertex #" + i + " = (" + v.position.x + "," + v.position.y + ")");          
      }
  }  
}
