/// <summary>
        /// Tries to finds all possible mating partners in all available animals.
        /// When a male and female is matched, they are removed from the collections of available animals.
        /// </summary>
        /// <param name="availableMales">Collection which keeps available males</param>
        /// <param name="availableFemales">Collection which keeps available females</param>
        /// <returns>Returns Task object which represents an asynchronous operation</returns>
        public async Task HandleAvailableAnimals(ConcurrentBag <IMale> availableMales, ConcurrentBag <IFemale> availableFemales)
        {
            var tasks  = new List <Task>();
            var tuples = new List <Tuple <IFemale, IMale> >();

            IFemale female = null;
            IMale   male   = null;

            while (availableFemales.TryTake(out female))
            {
                if (!female.IsAlive) // check for alive females, dead animals will be removed from simulation collections.
                {
                    continue;
                }

                male = null;
                while (availableMales.TryTake(out male))
                {
                    if (!male.IsAlive) // check for alive males, dead animals will be removed from simulation collections.
                    {
                        continue;
                    }

                    tuples.Add(new Tuple <IFemale, IMale>(female, male));
                    break;
                }

                if (male == null)
                {
                    // add female back to available females
                    availableFemales.Add(female);
                    break;
                }
            }

            // handles the list of "male and female couples to mate" by grouping
            // predefined number of the couples together and routing them to be handled by a new asynchronous Task
            for (int i = 0; i < tuples.Count; i += App.SimulationConfig.OperationCountPerTask)
            {
                tasks.Add(simulationEventHandler.OnMatingPartnersFound(tuples.GetRange(i, Math.Min(App.SimulationConfig.OperationCountPerTask, tuples.Count - i))));
            }

            // Waits for all the asynchronous tasks to be completed in order to proceed.
            // This is important for the simulation execution in order not to bypass any operation which may cause wrong simulation results.
            await Task.WhenAll(tasks.ToArray());
        }
 /// <summary>
 /// Determines if the mating will succeed with result of female pregnancy.
 /// Current implementation provides 50% pregnancy chance.
 /// </summary>
 /// <param name="female">female to mate</param>
 /// <param name="male">male to mate</param>
 /// <returns>Returns true if female gets pregnant otherwise returns false</returns>
 public bool Mate(IFemale female, IMale male)
 {
     // Future Scope:
     //      Fertality rates can be added to male and female through configuration for pregnancy probability.
     return(random.Value.Next(0, 2) == 0);
 }