/*test*/
import java.io.*;
import java.net.*;
import java.util.*;
import taskspaces.system.*;
import taskspaces.rna.*;

/**
 * This class will search for Ile and HH structures
 * in generated sequences.
 * @version     1.00 13 January 2003
 * @author      Robert Markel
 */
public class Ilehh extends Task implements Runnable 
{
   /** Compostion array. */
   float[] composition;

   /** Number of sequences to generate at each point in composition space and sequence length. */
   int sequences;

   /** Sequence lengths for generated sequences. */
   int[] lengths;

   /** Folding program. */
   String program;

   /** URL address of XML file containing specifications for lab-isolated motifs. */
   String xmlFile;

   /** File for output data. */
   String outputFile;

   /** File for status data. */
   String statusFile;

   /** ID number for this task. */
   //int id=0;

   /** Partitioner for tasks. */
   Partition parts;

   /** Percentage of steps through the composition space. */
   float percentSteps;

   /** Writer for output. */
   PrintWriter pw;
    //PrintWriter debug;

   /** Space address to send results. */
   String resultSpace;

   /** Indicates if running in a shared filesystem environment. */
   String useReceiver;

   /** Indicates if binary is present locally. */
   String download; 

   /** For timing. */
   long time;

   /** For restart. */
   int[] taskList;
    
   /** For logging */
   String user;
   static String app = "ilehh";
    //PrintWriter logWrite;

   /** 
    * Default constructor for initialization. 
    */
   public Ilehh() {}

   /** 
    * Constructor for tasks. 
    */
   public Ilehh(int id,long tasks,int sequences,String xmlFile,String program,String outputFile,
                Partition parts,float percentSteps,int[] lengths,String resultSpace,String useReceiver,
                String download,String user)
   {
      this.id=id;
      this.tasks=tasks;
      this.sequences=sequences;
      this.xmlFile=xmlFile;
      this.program=program;
      this.outputFile=outputFile;
      this.parts=parts;
      this.percentSteps=percentSteps;
      this.lengths=lengths;
      this.resultSpace=resultSpace;
      this.useReceiver=useReceiver;
      this.download=download;
      //System.out.println(user);
      this.user=user;
   }


   /**
    * Called by TaskAgent to advance data when creating new Tasks
    * while resident in a Space.
    * @return void
    */
   public void nextData()
   {
      try
      { 
         id++;
         if(id>1)  
         {  
            parts.next(); 
         }
      } catch(Exception e) {e.printStackTrace();}
   }

   /**
    * Called by Nodes to execute application. 
    * @return void
    */
   public void run()
   {
      try
      {

		//java.util.Random myRand = new java.util.Random(1);
		java.util.Random myRand = new java.util.Random(id*10000);
		System.out.println("Ilehh: putting seed "+String.valueOf(id*10000));

         if(id==0)
         {
            // Get input. 
            BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
            print("Ilehh: This is the Ile/HH Task.\nEnter the input file URL:");
            String inputURL=reader.readLine();
			//print("Please enter your username.");
			user="user";
            reader.close();
            Properties p=load(inputURL); 
            useReceiver=p.getProperty("use_receiver");
            download=p.getProperty("download");
            sequences=Integer.parseInt(p.getProperty("number_of_sequences"));
            xmlFile=p.getProperty("xml_file");
            program=p.getProperty("program");
            int percent=Integer.parseInt(p.getProperty("step_percentage"));
            outputFile=p.getProperty("output_file");
            statusFile=p.getProperty("status_file");
            String allLengths=p.getProperty("sequence_lengths");
            StringTokenizer tokenizer=new StringTokenizer(allLengths,",");
            int size=Integer.parseInt(tokenizer.nextToken());
            lengths=new int[size];
            int i=0;
            while(tokenizer.hasMoreTokens())
            {
               lengths[i]=Integer.parseInt(tokenizer.nextToken());
               i++;
            } 

            // Set parameters. 
            int obs=0;
            if(percent==2) obs=50;
            if(percent==5) obs=20;
            if(percent==10) obs=10;
            if(percent==20) obs=5;
            if(percent==25) obs=1;
            int tasks=0;
            if(obs==50) tasks=18424; 
            if(obs==20) tasks=969; 
            if(obs==10) tasks=84; 
            if(obs==5) tasks=4; 
            if(obs==1) tasks=1; 

            // Get space addresses.
            String[] spaces=getSpaces();
            String taskSpace=spaces[0];
            String resultSpace=spaces[1];
            //System.out.println("Result space: "+resultSpace);

            // Handle partitioning.
            parts=new Partition();
            parts.setObjectNumber(obs);
            parts.setModuleNumber(4);
            parts.reset();
            float percentage=0;
            if(obs==100) percentSteps=.01f;
            if(obs==50) percentSteps=.02f;
            if(obs==20) percentSteps=.05f;
            if(obs==10) percentSteps=.10f;
            if(obs==5) percentSteps=.20f;

	    // Create the Output
	    (new File("./logs/")).mkdir();
	    //logWriteName = "./logs" + user + "." + app;
	    //logWrite = new PrintWriter(new FileWriter(logWriteName, true));
	    
            // Send task. 
			(new File("./results/")).mkdir();
            String statusPath = statusFile.replace('/',File.separatorChar);
            PrintWriter statusWriter = new PrintWriter(new FileWriter(statusPath,true));
            BufferedReader br = new BufferedReader(new FileReader(statusPath));
            String str;
            taskList = new int[tasks+1];
            while((str = br.readLine()) != null)
            {
               int idInFile = Integer.parseInt(str);
               taskList[idInFile] = 1;
            }
            Ilehh task=new Ilehh((id++),tasks,sequences,xmlFile,program,outputFile,parts,percentSteps,
                                 lengths,resultSpace,useReceiver,download,user);
            print("Ilehh: Sending task.");
			String webserver = getCodeServer();
			String sysPath = "testArea/taskspacesFE/uploads";
			sendURL(taskSpace, new URL("http://"+webserver+"/"+sysPath+"/"+user+"/"+app+"/"));
            sendAgent(taskSpace,new TaskAgent(task,taskList, user, "ilehh"));  
            print("Ilehh: Task sent to Space!");

			//logWrite.println("Task sent to Space!");
            if(useReceiver.equals("yes"))
            {
               print("Ilehh: Starting result Receiver.");
               new Thread((new Receiver(resultSpace,tasks,outputFile,statusFile,user,app,true))).start();
            }
            return; 
         }
	 
	 
	 //debug=new PrintWriter(new FileWriter("debug"+String.valueOf(id),false));
	 (new File("./logs/")).mkdir();
	 logWriteName = "./logs" + user + "." + app;
	 PrintWriter logWrite = new PrintWriter(new FileWriter(logWriteName, true));

         program=program.replace('/',File.separatorChar);
         outputFile=outputFile.replace('/',File.separatorChar);
         int matches=0;
         ProcessManager pm=new ProcessManager();
         if(download.equals("yes"))
         {
            print("Ilehh: Checking binary. Will download if not present.");
            String programName=program.substring(program.lastIndexOf('/')+1,program.length());
            pm.getResource(program,programName,true,true);
         }
         composition=parts.getPercentages(percentSteps);
         print("Ilehh: Task "+String.valueOf(id));
        // uncomment the following for single equal composition runs
         // composition[0]=(float)0.25;
         // composition[1]=(float)0.25;
         // composition[2]=(float)0.25;
         // composition[3]=(float)0.25;
         String comp=composition[0]+",";
         for(int i=1; i<composition.length-1; i++) comp+=composition[i]+","; 
         comp+=String.valueOf(composition[composition.length-1]);
         //System.out.println(xmlFile);
         MotifsParser parser=new MotifsParser(xmlFile);
         ArrayList entries=parser.getEntries();
         if(useReceiver.equals("no"))
         {
            pw=new PrintWriter(new FileWriter(outputFile,false));
         }
         time=System.currentTimeMillis();

         // gu=0: no GU
         // gu=1: GU
         // gumax = 1 for no GU runs, gumax = 2 for GU
         // gustart = 0 for no GU, gustart = 1 for GU
         int gumax = 2;
         int gustart = 1;

         String[] results = new String[lengths.length*(gumax-gustart)*entries.size()];

         int resultIndex = 0;
         for(int i=0; i<entries.size(); i++)
         { 
            DatabaseEntry entry=(DatabaseEntry)entries.get(i);
            String type=entry.getName();
	    //System.out.println(type);
            for(int gu=gustart; gu<gumax; gu++)
            {
               if(gu==0) entry.setComposition(composition,false);
               if(gu==1) entry.setComposition(composition,true);
               for(int j=0; j<lengths.length; j++)
               { 
                  for(int k=0; k<sequences; k++)
                  { 
                     String[] modules=entry.generateModules(myRand);
                     List list=SequenceGenerator.embedModules(modules,lengths[j],composition,myRand);
                     if(list!=null)
                     {
                        String sequence=(String)list.get(0);
                        int[] points=(int[])list.get(1);
                        String structure=pm.execute(program+" n "+sequence);
			//System.out.println("Sequence: "+sequence);
                        //System.out.println("Structure: "+structure);
                        //System.out.println("Match: "+Matcher.match(entry.getStructures(),structure,points,entry.getConstraints()));
                        //debug.println("Sequence:  "+sequence);
                        //debug.println("Structure: "+structure);
                        //debug.println("Match: "+Matcher.match(entry.getStructures(),structure,points,entry.getConstraints()));
                        if(Matcher.match(entry.getStructures(),structure,points,entry.getConstraints())) matches++;
                     }
                  }
                  String result=(type+"\t"+comp+"\t"+gu+"\t"+lengths[j]+"\t"+matches+"/"+sequences);
                  results[resultIndex]=result;
                  resultIndex++;
                  if(useReceiver.equals("no"))
                  {
                     pw.println(result);
                     pw.flush();
                  }
                  /*
                  else
                  {
                     send(resultSpace,result); 
                     results[i]=result;
                  } 
                  */
                  matches=0;
               } 
            }          
         }
         //debug.flush();
         parser.reset();
         parser=null;
         if(useReceiver.equals("no"))
         { 
            pw.println(((System.currentTimeMillis()-time)/1000/60)+" minutes"); 
            pw.close();
         }
         else
         {
            Result result = new Result(id,results);
            send(resultSpace,result);
         }
      } catch(Exception e) {e.printStackTrace(); System.out.println("lawl"); }
      return;
   } 
}
