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

#include "stdafx.h"
#include "HashSetFactsContainer.h"
#include "../../../Utils/Utils.h"

#include <algorithm>

using namespace planning;

HashSetFactsContainer::HashSetFactsContainer(IntegerInterval)
  : m_hashCode(0), m_dirty(false)
{
}

HashSetFactsContainer::HashSetFactsContainer(const HashSetFactsContainer &other)
  : m_facts(other.m_facts), m_hashCode(0), m_dirty(true)
{
}

HashSetFactsContainer* HashSetFactsContainer::copy() const
{
  return new HashSetFactsContainer(*this);
}

bool HashSetFactsContainer::isSet(FormulaId id) const
{
  return m_facts.find(id) != m_facts.end();
}

void HashSetFactsContainer::set(FormulaId id)
{
  std::pair<stdext::hash_set<FormulaId>::iterator, bool> p = m_facts.insert(id);
  if (p.second)
  {
    m_hashCode += m_uintHasher(id);
    m_dirty = true;
  }
}

void HashSetFactsContainer::unset(FormulaId id)
{
  if (m_facts.erase(id))
  {
    m_hashCode -= m_uintHasher(id);
    m_dirty = true;
  }
}

size_t HashSetFactsContainer::getHashCode() const
{
  return m_hashCode;
}

const std::vector<FormulaId>& HashSetFactsContainer::getSortedFacts() const
{
  if (m_dirty)
  {
    m_dirty = false;
    m_sortedFacts.assign(m_facts.begin(), m_facts.end());
    std::sort(m_sortedFacts.begin(), m_sortedFacts.end());
  }
  return m_sortedFacts;
}

int HashSetFactsContainer::compareTo(const FactsContainer& other) const
{
  HashSetFactsContainer& container = (HashSetFactsContainer&) other;

  COMPARE(m_hashCode, container.m_hashCode);

  COMPARE(m_facts.size(), container.m_facts.size());

  const std::vector<FormulaId>& sortedFacts1 = getSortedFacts();
  const std::vector<FormulaId>& sortedFacts2 = container.getSortedFacts();

  for (std::vector<FormulaId>::const_iterator it1 = sortedFacts1.begin(), it2 = sortedFacts2.begin();
       it1 != sortedFacts1.end();
       ++it1, ++it2)
  {
    COMPARE(*it1, *it2);
  }
  return 0;
}