//
// 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 "BitSetFactsContainer.h"

using namespace planning;

BitSetFactsContainer::BitSetFactsContainer(IntegerInterval interval)
  : m_facts(interval.getLength()), m_offset(interval.getStart()), m_hashCode(0)
{
}

BitSetFactsContainer::BitSetFactsContainer(const BitSetFactsContainer &other)
  : m_facts(other.m_facts), m_offset(other.m_offset), m_hashCode(other.m_hashCode)
{
}

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

bool BitSetFactsContainer::isSet(FormulaId id) const
{
  const int bit = id - m_offset;
  assert(bit >= 0 && (size_t)bit < m_facts.size());

  return m_facts[bit];
}

void BitSetFactsContainer::set(FormulaId id)
{
  const int bit = id - m_offset;
  assert(bit >= 0 && (size_t)bit < m_facts.size());

  if (!m_facts.test(bit))
  {
    m_facts.set(bit);
    m_hashCode += m_uintHasher(id);
  }
}

void BitSetFactsContainer::unset(FormulaId id)
{
  const int bit = id - m_offset;
  assert(bit >= 0 && (size_t)bit < m_facts.size());

  if (m_facts.test(bit))
  {
    m_facts.reset(bit);
    m_hashCode -= m_uintHasher(id);
  }
}

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

int BitSetFactsContainer::compareTo(const FactsContainer& other) const
{
  BitSetFactsContainer& container = (BitSetFactsContainer&) other;
  assert(m_facts.size() == container.m_facts.size());

  COMPARE(m_hashCode, container.m_hashCode);

  boost::dynamic_bitset<> diff(m_facts ^ container.m_facts);
  size_t first_diff = diff.find_first();
  if (first_diff == boost::dynamic_bitset<>::npos)
    return 0;
  else
    return m_facts.test(first_diff) ? 1 : -1;

  //for (size_t i = 0; i < m_facts.size(); ++i)
  //{
  //  bool b1 = m_facts[i];
  //  bool b2 = container.m_facts[i];
  //  COMPARE(b1, b2);
  //}
}