import uk.ac.bbk.dcs.automed.qproc.QueryProcessor;
import uk.ac.bbk.dcs.automed.qproc.QueryProcessorConfiguration;
import uk.ac.bbk.dcs.automed.qproc.iql.ASG;
import uk.ac.ic.doc.automed.STR;
import uk.ac.ic.doc.automed.reps.Schema;
import uk.ac.ic.doc.automed.wrappers.AutoMedWrapper;

/*
 * An application to query the integrated University database example.
 */
public class UniversityDatabaseQuerying {
  static void printHelp() {
    System.out.println("Usage: UniversityDatabaseQuerying [ options ]\n"+
      "  -debug <0-10>         set debug level\n");
  }

  public static void readArgs(String[] args) {
    int i=0;

    try {
      while (i<args.length) {     	
	if (args[i].charAt(0)!='-') {
	  System.out.println("Error at "+args[i]+"\n");
	  printHelp();
	  System.exit(10);
	} 
	else if (args[i].startsWith("-debug")) 
	  STR.setDebugLevel(Integer.parseInt(args[++i]));
	else if (args[i].startsWith("-help")) 
	  printHelp();
	
	++i;
      }

      if (STR.atDebugLevel(5))
	System.out.println("Finished reading arguments, "+
			   "about to read database");

    }
    catch (ArrayIndexOutOfBoundsException e) {
      System.out.println("You didn't supply an argument to the "
			 +args[i-1]+" option!");
      printHelp();
      System.exit(10);
    }
  }
//Lucas 19/06/06
//  QueryReformulator qr;
//  QueryAnnotator qa;
//  LogicalOptimiser lo;
//  PhysicalOptimiser po;
//  FunctionTable ft;
//  Evaluator e;
  QueryProcessor gqp;
  QueryProcessorConfiguration qpc;
  static Schema sg;
  Schema[] extSchemas;

  public UniversityDatabaseQuerying() throws Exception  {
    qpc = new QueryProcessorConfiguration();
    qpc.setRangeSemantics(QueryProcessorConfiguration.RANGE_LOWER);
    qpc.setReformulationSemantics(QueryProcessorConfiguration.REFORMULATION_GAV);
    gqp = new QueryProcessor();
    extSchemas = sg.getAttachedSchemas(Schema.DATA_SOURCE_TYPE);
//    qr=new QueryReformulator(sg,extSchemas);
//    qa=new QueryAnnotator(extSchemas);
//    lo=new LogicalOptimiser();
//    po=new PhysicalOptimiser();
//    ft=new StandardFunctionTable();
//    e=new Evaluator(ft);

    if (extSchemas.length==0) {
      System.out.println("No attached data sources");
      System.exit(0);
    }

    System.out.println("Will run query over sources:");
    for (int i=0;i<extSchemas.length;i++)
      System.out.println(extSchemas[i].toString());
  }

  public void runQuery(String q) throws Exception {
    long t=System.currentTimeMillis();
    System.out.println("Processing query:"+q);
    ASG g=new ASG(q);
//    System.out.println("Original graph:"+g);
//    qr.reformulate(g);
//    System.out.println("After reformulator:"+g);
//    lo.optimise(g);
//    System.out.println("After logical optimiser:"+g);
//    qa.process(g);
//    System.out.println("After fragment processing:"+g);
//    po.optimise(g);
//    System.out.println("After physical optimiser:"+g);
//    e.evaluate(g);
//    System.out.println("After evaluator:"+g);
//    gqp.setLogicalOptimisation(false);
    gqp.process(g, sg,extSchemas,null,qpc);
    System.out.println("Result:"+g);
    System.out.println("Total execution time:"+
		       (System.currentTimeMillis()-t)/1000.0);
  }

  public static void main(String[] args) {
    readArgs(args);

    try {
      System.out.println("AutoMed Repository: "+
			 "Querying of University Databases");

      AutoMedWrapper.setDebugLevel(0);

      sg = Schema.getSchema("uni_ze");
      UniversityDatabaseQuerying qe=
	new UniversityDatabaseQuerying();

      qe.runQuery("<<female>> ++ <<male>>");

      qe.runQuery("[{x} | {x}<-<<female>>; x>'2'] ++ "+
		  "[{x} | {x}<-<<male>>; x<'5']");
      
      //if (1==1) return;
      qe.runQuery("<<person,name>>");

      qe.runQuery("distinct [{i,iname,y} | {i,iname} <- <<person,id>> ; "+
      	  "{i,y} <- <<person,dname>>]"); 

      qe.runQuery("distinct [{iname,jname,y} | {i,iname} <- <<person,id>> ; "+//
      	  "{i,y} <- <<person,dname>>; {j,jname} <- <<person,id>> ; "+
      	  "{j,y} <- <<person,dname>>; "+
      	  "{i} <- <<male>>; {j} <- <<female>>]");
    }	   
    catch (Throwable t) {
      System.err.println(t.toString());
      t.printStackTrace();
    }
  }
}
