//
// Copyright (c) 2009 Froduald Kabanza and the Université de Sherbrooke.
// Use of this software is permitted for non-commercial research purposes, and
// it may be copied or applied only for that use. All copies must include this
// copyright message.
// 
// This is a research prototype that has not gone through intensive tests and
// is delivered as is. It may still contain bugs. Froduald Kabanza and the
// Université de Sherbrooke disclaim any responsibility for damage that may be
// caused by using it.
//
// Please note that some files were inspired in part by the PDDL4J library:
// http://www.math-info.univ-paris5.fr/~pellier/software/software.php 
//
// Implementation: Simon Chamberland
// Project Manager: Froduald Kabanza
//

#ifndef _DESCRIBED_FORMULA_H
#define _DESCRIBED_FORMULA_H

#include "../RootFormula.h"

namespace planning
{
  /// <summary>
  /// A described formula is a formula whose value is described directly in the world.
  /// Thus a world holds values corresponding to described formulas only.
  /// </summary>
  class DescribedFormula : public RootFormula
  {
  public:
    /// <summary>
    /// This structures holds all possible described formulas' attributes.
    /// These attributes are not present in the PDDL grammar; they were rather added
    /// for TLPlan.
    /// </summary>
    struct Attributes
    {
      /// <summary>
      /// Initialize the set of attributes with the specified values.
      /// </summary>
      /// <param name="detectCycles">Whether to check for cycles.</param>
      Attributes(bool detectCycles)
      {
        DetectCycles = detectCycles;
      }

      /// <summary>
      /// Whether the cycles detection mechanism should use this formula.
      /// </summary>
      bool DetectCycles;
    };

    /// <summary>
    /// Creates a new described formula with a specified name, arguments, and set of attributes.
    /// </summary>
    /// <param name="name">The name of the new described formula.</param>
    /// <param name="arguments">The arguments (variables) of the new described formula.</param>
    /// <param name="attributes">The new described formula's attributes.</param>
    template <class Iterator>
    DescribedFormula(const std::string& name, Iterator argumentsBegin, Iterator argumentsEnd, 
                     Attributes attributes)
      : RootFormula(name, argumentsBegin, argumentsEnd), m_isInvariant(false), m_attributes(attributes)
    {
    }

    /// <summary>
    /// The default attributes.
    /// </summary>
    static const Attributes DefaultAttributes;

  private:

    /// <summary>
    /// Whether this formula is invariant (a formula is invariant if its value is never
    /// modified by actions).
    /// This value is set in the preprocessing phase.
    /// </summary>
    bool m_isInvariant;
    /// <summary>
    /// Whether the cycles detection mechanism should use this formula.
    /// </summary>
    Attributes m_attributes;
  };
}

#endif