//
// 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 "Object.h"
#include "Type/PrimitiveType.h"

using namespace planning;

/// <summary>
/// Creates a new constant with the specified name and typeset.
/// </summary>
/// <param name="name">The name of the new constant.</param>
/// <param name="typeSet">The typeset of the new constant.</param>
Object::Object(const std::string& name, PrimitiveType* type)
: m_name(name), m_type(type)
{
  assert(m_type != NULL);
  _setHashCode(_calculateHashCode());
}

/// <summary>
/// Evaluates this term in the specified closed world.
/// The bindings should not be modified by this call.
/// </summary>
/// <param name="world">The evaluation world.</param>
/// <param name="bindings">A set of variable bindings.</param>
/// <returns>Undefined, or the constant resulting from the evaluation.</returns>
/// <exception cref="PDDLParser.Exception.BindingException">A BindingException is thrown if an attempt
/// is made to evaluate an unbound variable.</exception>
const Object* Object::evaluate(const IClosedWorld* world, const Bindings* bindings) const
{
  return this;
}

const PrimitiveType* Object::getType() const
{
  return m_type;
}

  /// <summary>
/// Returns the typeset of this term.
/// </summary>
/// <returns>This term's typeset.</returns>
PrimitiveType* Object::getType()
{
  return m_type;
}

void Object::_output(std::ostream& out) const
{
  out << m_name;
}

ObjectId Object::getObjectId(const Type* type) const
{
  boost::unordered_map<const Type*, ObjectId>::const_iterator it = m_objectIDs.find(type);
  if (it == m_objectIDs.end())
    throw std::domain_error("Object::getObjectId(): Object \"" + toString(this) + "\" is not associated with type \""
                          + toString(type) + "\".");
  return it->second;
}

void Object::setObjectId(const Type* type, ObjectId id) const
{
  m_objectIDs[type] = id;
}

const IExp* Object::_internalApply(const Bindings* bindings) const
{
  return this;
}

int Object::_internalCompareTo(const IExp& other) const
{
  COMPARE_PTR(this, &other);

  return 0;
}

