/*******************************************************************************
 * GenRGenS v.1.0, Generation of Random Genomic Sequences                      *
 * Copyright (C) 2001  Alain Denise/Yann Ponty                                 *
 *                                                                             *
 * This program is free software; you can redistribute it and/or               *
 * modify it under the terms of the GNU General Public License                 *
 * as published by the Free Software Foundation; either version 2              *
 * of the License, or (at your option) any later version.                      *
 *                                                                             *
 * This program is distributed in the hope that it will be useful,             *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of              *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
 * GNU General Public License for more details.                                *
 *                                                                             *
 * You should have received a copy of the GNU General Public License           *
 * along with this program; if not, write to the Free Software                 *
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. *
 *******************************************************************************/

package GenRGenS;

import java.io.*;
import java.lang.reflect.*;
import GenRGenS.utility.*;
import GenRGenS.utility.callbacks.*;

/*****************************************************************************
*              classe GenRGenS
*                  Programme principal
*
******************************************************************************/

/**
 * La classe <code>GenRGenS</code> a un double rôle <P>
 *            <DD><DD><DT>1) Elle contient la configuration du logiciel
 *            <DD><DD><DT>Le nombre de séquences ?générer
 *            <DD><DD><DT>La taille des séquences.
 *            <DD><DD><DT>La politique ?adopter face ?la présence d'"impasses" dans la génération markovienne.
 *            <DD><DD><DT>Le type de données utilisées pour le dénombrement des grammaires.
 *            <DD><DD><DT>Le nom du fichier principal ?analyser.<P>
 *            <DD><DD><DT>2) Elle est la classe principale du soft dans sa version "console"
 *            <DD><DD><DT>En cela, elle a principalement un rôle coordinateur.<P>
 *
 * @author  Frédéric Sarron
 * @author  Yann Ponty
 * @version 2.1
 */


public class GenRGenS
{
		/**
		 * Le numéro de la version de GenRGenS
		 */
		public static final String version = "2.1";





		/**
		 * Variable contenant la taille souhaitée pour les séquences générées
		 * Par défaut, la taille est égale ?-1 et provoque une erreur au moment de la génération car il apparait
		 * stupide de ne pas la définir, on pourra alors tester l'égalit?de cette variable ?-1
		 * pour forcer l'utilisateur ?la définir.
		 */
		public static int size = -1;


		/**
		 * Variable contenant le nombre souhait?de séquences ?générer.
		 * Valeur par défaut : 1.
		 */
	  public static int howMany = 1;


		/**
		 * Variable contenant le nom du fichier de description ?traiter afin de générer un générateur
		 * Par défaut, le nom du fichier est égal ?"" afin de forcer l'utilsateur ?le définir.
		 */
	  public static String nomFichier = "";


		/**
		 * Variable exprimant la nécessit?d'un commentaire sur les actions en cours.
		 * Valeur par défaut : Faux.
		 */
	  public static boolean verbose = false;


    /**
     *  Les Sorties standard et d'erreur utilis?es par le logiciel
     */
    public static PrintStream out = System.out;
    public static PrintStream err = System.err;




		/**
		 * Définit la taille souhaitée pour les séquences générées
		 * Par défaut, la taille est égale ?-1 et provoque une erreur car il apparait
		 * stupide de ne pas la définir.
		 * @param nsize La nouvelle valeur pour la taille des séquences ?générer.
		 */
    public static void setSize(int nsize)
    {
      size = nsize;
    }


		/**
		 * Définit le nombre souhait?de séquences ?générer.
		 * @param nb Le nouveau nombre de séquences ?générer.
		 */
    public static void setHowMany(int nb)
    {
      howMany = nb;
    }

		/**
		 * Définit le fichier ?traiter.
		 * @param s Le nouveau fichier ?traiter.
		 */
    public static void setFileName(String s)
    {
      nomFichier = s;
    }

		/**
		 * Renvoie la taille souhaitée pour les séquences générées
		 * @return La valeur pour la taille des séquences ?générer.
		 */
    public static int getSize()
    {
      return size;
    }

		/**
		 * Renvoie le nombre souhait?de séquences ?générer.
		 * @return Le nombre de séquences ?générer.
		 */
    public static int getHowMany()
    {
      return howMany;
    }

		/**
		 * Renvoie le nom fichier ?traiter.
		 * @return Le fichier ?traiter.
		 */
    public static String getFileName()
    {
      return nomFichier;
    }


  /**
   * Démarre la génération ?proprement parler, se basant sur les paramètres
   * de configurations.
   */
  public static void startGeneration()
  {
		Generator gen=null;
		if (GenRGenS.nomFichier.equals(""))
		{
		  GenRGenS.err.println("Filename needed !");
		}
    else
    {
      if (GenRGenS.size == -1)
			{
			  GenRGenS.err.println("Size for the generated sequence is needed !");
			}
      else
      {
        try
				{
					FileReader fr = new FileReader(GenRGenS.nomFichier);
					String type = Linker.getDescriptionFileHeader(fr);
          File f = new File(GenRGenS.nomFichier);
					Class GeneratorClass = Linker.getGeneratorClassFromType(type);
		      if (GenRGenS.verbose)
      		{
		        GenRGenS.err.println("Searching a generator for this file's type (\""+type+"\") ...");
		      }
					try
					{
    				  Object[] args = new Object[1];
  			  	  Constructor[] tab = GeneratorClass.getConstructors() ;
  			  	  boolean found = false;
  			  	  for (int i = 0; (i<tab.length)/*&&(!found)*/;i++)
  			  	  {
  			  	    Constructor c = tab[i];
  			  	    Class[] argsTypes = c.getParameterTypes();
  			  	    
  			  	    if (argsTypes.length == 1)
  			  	    {
  			  	      Class param = argsTypes[0];
  			  	      if (param.isAssignableFrom(f.getClass()))
  			  	      {
  			  	        found = true;
  			  	        args[0] = f;
  			  	        gen = (Generator) c.newInstance(args);
  			  	      }
  			  	    }
  			  	  }
				      if (!found)
				      {
				        GenRGenS.err.println("No constructor matching File in the main class of package \""+type+"\".");
				      }
			  	}
  	  		catch(InvocationTargetException in)
  	  		{
  	  		  GenRGenS.err.println(in.getTargetException());
  	  		}
					if (gen != null)
					{

  	        if (GenRGenS.verbose)
       	  	{
	            GenRGenS.err.println("Starting sequence generation ...");
	          }
            for (int i=0; i<GenRGenS.howMany; i++)
			      {
						  GenRGenS.out.println(gen.generateRandomWord(GenRGenS.size));
				    };
  	        if (GenRGenS.verbose)
       	  	{
	            GenRGenS.err.println("Generation complete!");
	          }
          }
        }
		    catch (FileNotFoundException e)
		    {
		      GenRGenS.err.println("File not found :  \""+GenRGenS.nomFichier+"\"");
		    }
        catch (GenerationException e)
        {
          GenRGenS.err.println(e.toString());
          //System.exit(2);
        }
			  catch	(Exception e)
			  {
				  GenRGenS.err.println (e.toString());
				  e.printStackTrace(GenRGenS.err);
				  //System.exit(2);
			  };
      }
    }
  }

		/**
		 * Code executable de l'application GenRGenS "console".
		 */
		public static void main(String[] argument)
		{
       
        GenRGenS.err.println(
          "GenRGenS v."+GenRGenS.version+", Copyright (C) 2001 Alain Denise/Yann Ponty\n"+
          "GenRGenS comes with ABSOLUTELY NO WARRANTY; Details found in LICENCE.\n"+
          "This is free software, and you are welcome to redistribute it \n"+
          "under certain conditions; Details found in LICENCE.\n"

        );
        // Initialisation du Linker, chargement des packages, etc ...
        Linker.configureParser();
        Packages.installCommonPackages();

        // Analyse de la ligne de commande
        Linker.getCommandLineParser().parse(argument);
		    if (GenRGenS.nomFichier.equals(""))
		    {
		      GenRGenS.err.println("Filename needed !");
 		      Linker.getCommandLineParser().printHelp();
 		      System.exit(1);
		    }
        else
        {
          if (GenRGenS.size == -1)
			    {
			      GenRGenS.err.println("Size for the generated sequence is needed !");
   		      Linker.getCommandLineParser().printHelp();
 		        System.exit(1);
			    }
		    }
        GenRGenS.startGeneration();
        System.exit(0);
    }

  public static WorkProgress progress = new WorkProgress()
  {
    private long _amount=1;
    private long _progress=0;
    private int CHARS_PER_LINE = 75;
      private int _numChars = 0;
    
    public void setWorkName(String name)
    {
      GenRGenS.err.println("");
      GenRGenS.err.println(name+" :");
    }
    public void setAmount(long amount)
    {
      _progress = 0;
      _numChars= 0;
      _amount = amount;
    }
    public void setProgress(long value)
    {
        int count = (int)((((value)*CHARS_PER_LINE)/_amount));
      if(count>_numChars)
      {
        for(int i=_numChars;i<count;i++)
        {
          GenRGenS.err.print(".");
        }
        _numChars = count;
      }
      if(value==_amount)
          {GenRGenS.err.print("\n");}
    }
  };

}
