import java.io.*;
import java.util.StringTokenizer;

public class GraphMain
{
   static BufferedReader console = new BufferedReader
                                  (new InputStreamReader(System.in));

/**
 * Return one line from System.in
 */
   static String readLine()
   {  String rtn = "";

      try
      {  rtn = console.readLine();  }
      catch (Exception e)
      {  System.out.println(e);  System.exit(-1);  }
      return rtn;
   }

   public static void main ( String[] args )
   {
      String   lineIn = "";
      GraphClose  map = new GraphClose();
      PrintWriter logFile = null;
      BufferedReader inp = null;

      try
      {  File f  = new File("GraphLogFile.txt");
         logFile = new PrintWriter(new FileWriter(f));
      }
      catch (IOException e)
      {  System.err.println ("Log file open failed: " + e);
         System.exit(-1);
      }

   // Debug option:  program supports command-line argument of file name
      if (args.length > 0)
      {
         lineIn = args[0];
         System.out.println ("Reading data from file " + lineIn);
      }

      inp = openInput (lineIn);
      logFile.println ("Data read from " + lineIn);

      map.fillGraph(inp);

      System.out.println ("\nThe data file has " + map.nCities() + " towns, and "
           + map.nRoads()  + " roads connecting them.");

      if (args.length > 1)
      {
         lineIn = args[1];
         System.out.println ("Starting from " + lineIn);
      }

      logFile.println ( "\nThe data file has " + map.nCities()
          + " towns, and " + map.nRoads()  + " roads connecting them.");
      map.dump(logFile);
      System.out.println ( "\nThe data file has " + map.nCities()
          + " towns, and " + map.nRoads()  + " roads connecting them.");
      map.dump(System.out);

      System.out.println();

      map.transitiveClosure();
      System.out.println ("\nTransitive closure result:");
      map.report(System.out);
      logFile.println ("\nTransitive closure result:");
      map.report(logFile);

      map.reflexiveTransitiveClosure();
      System.out.println ("\nReflexive transitive closure result:");
      map.report(System.out);
      logFile.println ("\nReflexive transitive closure result:");
      map.report(logFile);

      map.allShortestPaths();

      logFile.println ("\nAll shortest paths matrix");
      map.pathReport(logFile);
      System.out.println ("\nAll shortest paths matrix");
      map.pathReport(System.out);

      System.out.println ("\nEnter \"EXIT\" as starting node to exit.\n");
      while (true)  // break on "EXIT" as start
      {
         String start, finish, result;

         System.out.print("Starting node: ");
         start = readLine();
         if ( start.equals("EXIT") )
            break;
         System.out.print("Ending node: ");
         finish = readLine();
         result = map.pathQuery(start, finish);
         System.out.println ( "Path:  " + result);
         logFile.println ( "Path:  " + result);
      }
      logFile.close();
   }

   static BufferedReader openInput ( String lineIn )
   {
      BufferedReader inp = null;

      if ( lineIn == null || lineIn.length() == 0 )
      {
         System.out.print ("input file:  ");
         lineIn = readLine();
      }

      while ( inp == null )
      {
         try
         {
            File f = new File (lineIn);
            FileReader  fis = new FileReader(f);
            inp = new BufferedReader (fis);
         }
         catch (IOException e)
         {  System.out.println ("Exception: " + e);  }
         finally
         {  if (inp == null)
            {
               System.out.print ("Yo! Open failed for " + lineIn
                    + "\nPlease enter a valid file name:  ");
               System.out.flush();
               lineIn = readLine();
               if ( lineIn.length() == 0 )
               {  System.out.println ("NULL name; aborting!");
                  System.exit(0);
               }
            }
         }

      }

      return inp;
   }

}
