package rabbit;
import cern.jet.random.Uniform;
import cern.jet.random.Empirical;
import cern.jet.random.engine.MersenneTwister;


/*----------------------------------------------------------------------*
* Rabbit : Represent a single rabbit                                    *
*----------------------------------------------------------------------*/
public class Rabbit
{
   private int  age;
   private int  timeSinceFertilization;
   private char sexe;

   //Constants
   final static int ADULT = 5;
   final static int LIFETIME = 108;
   private final static double[] LITTER = new double[]{0.152068063,0.209424084,0.235602094,0.157068063,0.104712042,0.02617801,0.013089005,0.013089005,0.005235602,0.005};

   //Random generator
   private static Uniform rand = new Uniform(0,1,5489);
   private static Empirical gen = new Empirical(LITTER,Empirical.LINEAR_INTERPOLATION, new MersenneTwister());

	/*----------------------------------------------------------------------*
	* Constructor                                                           *
	*                                                                       *
	* Input :                                                               *
	*      - _age : an unsigned int value representing the age in month of  *
	*      the Rabbit                                                       *
	*      - _time : an unsigned int value representing the time since the  *
	*      Fertilization in case of female Rabbit                             *
	*      - _sexe : a char value representing the sexe of a Rabbit         *
	*----------------------------------------------------------------------*/
   public Rabbit(int _age, char _sexe, int _timeSinceFertilization)
   {
     this.age = _age;
     this.timeSinceFertilization = _timeSinceFertilization;
     this.sexe = _sexe;
   }

   /*----------------------------------------------------------------------*
   * Getter sexe                                                           *
   *                                                                       *
   * Output :                                                              *
   *      - a char representing the sexe of the rabbit                     *
   *----------------------------------------------------------------------*/
   public char sexe()
   {
      return this.sexe;
   }

   /*----------------------------------------------------------------------*
   * Getter age                                                            *
   *                                                                       *
   * Output :                                                              *
   *      - a int representing the age of the rabbit                       *
   *----------------------------------------------------------------------*/
   public int age()
   {
      return this.age;
   }

   /*----------------------------------------------------------------------*
   * toString : return a String representing the rabbit                    *
   *                                                                       *
   * Output :                                                              *
   *      - a String representing the actual rabbit                        *
   *----------------------------------------------------------------------*/
   public String toString()
   {
      //If female rabbit
      if(this.sexe == 'f')
      {
         //If adult
         if(this.age > this.ADULT)
         {
            return "Adult Female";
         }
         //If young
         else
         {
            return "Young Female";
         }
      }
      //If male rabbit
      else 
      {    		
         //If adult
         if(this.age > this.ADULT)
         {
            return "Adult Male";
         }
         //If young
         else
         {
            return "Young Male";
         }
      }
   }

   /*----------------------------------------------------------------------*
   * aging : Age a rabbit by one year                                      *
   *----------------------------------------------------------------------*/
   public void aging()
   {
      this.age++;

      //If female rabbit
      if(this.sexe == 'f')
      {
         this.timeSinceFertilization++;
      }
   }

   /*----------------------------------------------------------------------*
   * reproduce : if the rabbit is a female and there is male, it lays      *
   *                                                                       *
   * Input :                                                               *
   *      - a Population representing the actual population                *
   *----------------------------------------------------------------------*/
   public int reproduce(Population _pop)
   {
      //If there is male
      if(_pop.adultMales() > 0)
      {
         //If female and not pregnant or in rest time
         if(this.sexe == 'f' && this.timeSinceFertilization > 2)
         {
            //Reset value
            this.timeSinceFertilization = 0;

            //Determine size of lay i [3,12] following the LITTER empirical law
            int size =  3 + (int) Math.round(gen.nextDouble());

            //Create new rabbits
            for(int i = 0 ; i < size ; i++)
            {
               _pop.add(new Rabbit(0,this.rand.nextInt() == 1 ? 'f' : 'm',3));
            }
            return size;
         }
      }
      return 0;
   }
}