//
// 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 and it 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.
//
// Implementation: Simon Chamberland
// Project Manager: Froduald Kabanza
//

#ifndef _FLUENTS_CONTAINER_H
#define _FLUENTS_CONTAINER_H

#include "../../IClosedWorld.h"
#include "../../../Exp/Formula/Described/NumericFluentApplication.h"
#include "../../../Exp/Formula/Described/ObjectFluentApplication.h"
#include "../../../Exp/Term/Object.h"
#include "../../../Exception/UndefinedFluentException.h"
#include "../../../Exception/NumericException.h"
#include "../../../Utils/Utils.h"

namespace planning
{
  /// <summary>
  /// A fluents container is responsible for holding and updating both numeric
  /// and object fluents.
  /// </summary>
  class FluentsContainer
  {
  public:

    virtual FluentsContainer* copy() const = 0;

    virtual double getNumericFluent(FormulaId id) const = 0;

    virtual const planning::Object* getObjectFluent(FormulaId id) const = 0;

    virtual void setNumericFluent(FormulaId id, double value) = 0;
    
    virtual void setNumericFluent(FormulaId id, 
                          const planning::ArithmeticFunction& function, 
                          double argument) = 0;

    virtual void setObjectFluent(FormulaId id, const planning::Object* value) = 0;

    virtual void undefineObjectFluent(FormulaId id) = 0;

    virtual size_t getHashCode() const = 0;

    virtual int compareTo(const FluentsContainer& other) const = 0;

  protected:
    boost::hash<double> m_doubleHasher;
    //boost::hash<size_t> m_uintHasher;
    CustomHash<size_t> m_uintHasher;


    //#region Public Methods

    ///// <summary>
    ///// Copies this facts container.
    ///// </summary>
    ///// <returns>A copy of this facts container.</returns>
    //public abstract FactsContainer Copy();

    //#endregion

    //#region IConstantWorld Interface

    ///// <summary>
    ///// Checks whether the specified described atomic formula holds in this world.
    ///// </summary>
    ///// <param name="formulaID">A formula ID.</param>
    ///// <returns>True, false, or unknown.</returns>
    //public abstract FuzzyBool IsSet(int formulaID);

    //#endregion

    //#region IWorld Interface

    ///// <summary>
    ///// Sets the specified atomic formula to true.
    ///// </summary>
    ///// <param name="formulaID">A formula ID.</param>
    //public abstract void Set(int formulaID);

    ///// <summary>
    ///// Sets the specified atomic formula to false.
    ///// </summary>
    ///// <param name="formulaID">A formula ID.</param>
    //public abstract void Unset(int formulaID);

    //#endregion

    //#region Object Interface Overrides

    ///// <summary>
    ///// Returns whether this facts container is equal to another object.
    ///// </summary>
    ///// <param name="obj">The other object to test for equality.</param>
    ///// <returns>Whether this facts container is equal to the other object.</returns>
    //public override abstract bool Equals(object obj);
    //
    ///// <summary>
    ///// Returns the hash code of this facts container.
    ///// </summary>
    ///// <returns>The hash code of this facts container.</returns>
    //public override abstract int GetHashCode();

    //#endregion

    //#region IComparable<OpenWorld> interface

    ///// <summary>
    ///// Compares this facts container with another facts container.
    ///// </summary>
    ///// <param name="other">The other facts container to compare this facts container to.</param>
    ///// <returns>An integer representing the total order relation between the two facts containers.
    ///// </returns>
    //public abstract int CompareTo(FactsContainer other);

    //#endregion
  };
}

#endif