#include "error.hh"
#include "imagedatasource.hh"


using namespace Gecode;

ImageDataSource::ImageDataSource (Space& home, filewrapper& fw) : 
  DataSource (home),
  m_unavailable (),
  m_fw (fw)
{
  const uint64_t file_size  = fw.size ();

  if (file_size % BLOCK_SIZE != 0) {
    error ("Illegal image size: not a multiple of BLOCK_SIZE");
  }

  const uint64_t file_size_blocks  = file_size / BLOCK_SIZE;
  const uint64_t max_int = 1 << 31;
  if (file_size_blocks > max_int) {
    error ("Illegal image size: too large");
  }

  // Specify that m_unavailable is the complement of the region 0...(fw.size() - 1)
  Iter::Ranges::Singleton lower (Int::Limits::min, -1);
  Iter::Ranges::Singleton upper (file_size_blocks, Int::Limits::max);
  Iter::Ranges::Union<Iter::Ranges::Singleton, Iter::Ranges::Singleton> union_lower_upper (lower, upper);
  IntSet union_lower_upper_set (union_lower_upper);
    
  m_unavailable = IntVar (home, union_lower_upper_set);
  std::cout << "ImageDataSource.unavailable = " << m_unavailable << std::endl;
}


ImageDataSource::ImageDataSource (bool share, Space& home, ImageDataSource& ds) : 
  DataSource (share, home, ds),
  m_fw (ds.m_fw)
{
  m_unavailable.update (home, share, ds.m_unavailable);
}


IntVar& ImageDataSource::unavailable ()
{
  return m_unavailable;
}


unsigned char ImageDataSource::read (int64_t offset) const
{
  // int block = offset / BLOCK_SIZE;
  // assert (!m_unavailable.in (block));
  unsigned char result = m_fw.read (offset);
  // std::cout << "image read: " << offset << " = " << (unsigned int) result << std::endl;
  return result;
}


void ImageDataSource::read (int64_t block, unsigned char* buffer) const
{
  m_fw.read (block, buffer);
}


void ImageDataSource::print (std::ostream& os) const 
{
  os << "ImageDataSource (" << m_unavailable << ")";
}


