/***************************************************************************
 *   Copyright (C) 2004 by Raphael Langerhorst                             *
 *   raphael-langerhorst@gmx.at                                            *
 *                                                                         *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the       *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to    *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:                                             *
 *                                                                         *
 *   The above copyright notice and this permission notice shall be        *
 *   included in all copies or substantial portions of the Software.       *
 *                                                                         *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
 ***************************************************************************/
 
#ifndef GBEGDYNAMICGENERATORCATEGORYH
#define GBEGDYNAMICGENERATORCATEGORYH

#include "PseudoRNG.h"

#include <GElement.h>
#include <GEnergy.h>
#include <GVector3.h>
#include <GForm.h>
#include <GAgent.h>
#include <GObject.h>

#include <qptrlist.h>

namespace GBE
{

/**
  \class GDynamicGeneratorCategory GDynamicGeneratorCategory.h
  \brief Handles child element creation for an element category.
  @author Raphael Langerhorst
  
  A specialised class needs to be defined for every kind of
  child element that can be created.
  
  The element itself is not created in the category class but in
  the GDynamicGeneratorAgent class. Vital parts are provided by
  the category: the form and agents. The energy is provided by
  the parent element.
  
  @note If the created child element should again provide the same
  kind of content or child element creation then a
  GDynamicGeneratorAgent with a fitting category list
  must be added to the created child.
  @see GDynamicGeneratorAgent
*/
class GDynamicGeneratorCategory
{
  protected:
  
    /**
     * When the correct category is chosen for element creation,
     * this range attribute is used to determine the correct category.
     * Range must be between 0 and 1, all Ranges of used categories
     * summed up should result in a number less than 1 because all
     * categories above 1 will never be chosen (as the generated
     * random number is always between 0 and 1).
     * @see GDynamicGeneratorAgent::recursiveGeneration()
     */
    double Range;
    
    /**
     * Holds the minimum radius an element of this category will occupy.
     */
    double RadiusMin;
    
    /**
     * Holds the maximum radius an element of this category can occupy.
     */
    double RadiusMax;
    
    /**
     * Determines, whether the element form may overlap with other
     * elements.
     * If forms may overlap, the generator agent will create such
     * an element although it will overlap with another element.
     */
    bool FormOverlapAllowed;
    
  public:
  
    /**
      * Constructor. Sets values for this element category.
      */
    GDynamicGeneratorCategory(double range,
                              double radius_min, double radius_max,
                              bool form_overlapping_allowed);
                              
    /**
      * Virtual destructor.
      */
    virtual ~GDynamicGeneratorCategory();
  
    /**
      * @return the range for choosing the correct category.
      */
    double getRange() const;
    
    /**
      * @return the maximum size of a generated element.
      */
    double getRadiusMax() const;
    
    /**
      * @return the minimum size of a generated element.
      */
    double getRadiusMin() const;
    
    /**
      * @return true when elements of this category may overlap.
      */
    bool formOverlapAllowed() const;
    
    /**
      * This actually creates a form attribute
      * for a new element of this category.
      */
    virtual GCS::GForm* createForm(const GCS::GEnergy& energy, const GCS::GVector3& position, Util::PseudoRNG& rng) const = 0;
    
    /**
     * Here the element can be posprocessed.
     * This is especially important for creating agents
     * and adding them to the element.
     * @note DO NOT execute the agents.
     *       Elements are generally executed and parked by the GWE.
     */
    virtual void postProcess(GCS::GElement* element, Util::PseudoRNG& rng) const = 0;
    
};

}

#endif
