//
// 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
//

#include "stdafx.h"
#include "AtomicFormulaApplication.h"
#include "AtomicFormula.h"
#include "../../../World/IDurativeClosedWorld.h"

#include <assert.h>

using namespace planning;

AtomicFormulaApplication::AtomicFormulaApplication(const AtomicFormula* atomicFormula, const ITerm** arguments)
  : DescribedFormulaApplication(atomicFormula, arguments)
{
  INITIALIZE_HASH_CODE();
}

const AtomicFormulaApplication* AtomicFormulaApplication::apply(const Bindings* bindings) const
{
  return static_cast<const AtomicFormulaApplication*>(FormulaApplication::apply(bindings));
}

const AtomicFormulaApplication* AtomicFormulaApplication::evaluateArguments(const IClosedWorld* world, 
                                                                            const Bindings* bindings) const
{
  return static_cast<const AtomicFormulaApplication*>(FormulaApplication::evaluateArguments(world, bindings));
}

const AtomicFormula* AtomicFormulaApplication::getAtomicFormula() const
{
  return static_cast<const AtomicFormula*>(m_rootFormula);
}

bool AtomicFormulaApplication::evaluate(const IClosedWorld* world, const Bindings* bindings) const
{
  const AtomicFormulaApplication* groundFormula = evaluateArguments(world, bindings);
  return world->isSet(groundFormula);
}

void AtomicFormulaApplication::update(const IClosedWorld* evaluationWorld, 
                                      IDurativeClosedWorld* updateWorld, 
                                      const Bindings* bindings, 
                                      const ActionContext* actionContext) const
{
  const AtomicFormulaApplication* groundFormula = evaluateArguments(evaluationWorld, bindings);
  updateWorld->set(groundFormula);
}

/// <summary>
/// Enumerates all the worlds within which this logical expression evaluates to true.
/// This method is used to support the goal modality expressions.
/// </summary>
/// <returns>All the worlds satisfying this logical expression.</returns>
void AtomicFormulaApplication::enumerateSatisfyingWorlds(PartialWorldSet& worlds) const
{
  //  HashSet<PartialWorld> list = new HashSet<PartialWorld>();
  //  PartialWorld world = new PartialWorld();
  //  world.Set(this);
  //  list.Add(world);
  //  return list;

  assert(worlds.size() == 0);

  PartialWorld* world = new PartialWorld();
  world->set(this);

  worlds.insert(world);
}