#include "Syslog.h"

#include "DeviceClassifier.hh"

/*
 * class DeviceClassifier
 */

SingletonUse<Random> DeviceClassifier::s_rand_gen;

// structors :

DeviceClassifier::DeviceClassifier(ArgList const &args)
  :AbstractClassifier(args) {
  Argument const &descr = args.get("descr");
  size_t i, endi = descr.length();

  for( i=0; i<endi; i+=2 ) {
    Symbol name = descr[i], attr = descr[i+1];
    
    AbstractDevice *dev = m_devices->useDevice(name, args);
    if( NULL==dev )
      throw ParseError(name+" is an unknown device");
    else if( !dev->hasAttribute(attr) )
      throw ParseError(name+" does not have attribute "+attr);
    m_fields.push_back(std::make_pair(dev, dev->get(attr)));
  }
  // Setting the dimension of the vector :
  m_current.setDimension(m_fields.size());
}

// Manipulators

bool DeviceClassifier::classify(DeviceClassifier::cluster_type &winner,
				DeviceClassifier::dist_type &distance) {
  size_t idx = 0;
  std::vector< std::pair<AbstractDevice *, dbEntry *> >::const_iterator i = m_fields.begin();
  std::vector< std::pair<AbstractDevice *, dbEntry *> >::const_iterator const endi = m_fields.end();
  std::vector<cluster_type> winners;
  
  for( ; endi!=i; ++idx, ++i) {
    if( !i->first->ready() )
      return false;
    m_current[idx] = i->second->getValue();
  }
#ifdef DEBUG
  {
    Symbol tmp = m_current.toString();
    Syslog::write("Cluster : classify %s", tmp.c_str());
  }
#endif // DEBUG
  classify(m_current, winners, distance);
  if( winners.size()>0 )
    winner = winners[s_rand_gen->roll(winners.size())];
  else 
    winner = 0;
  
  return true;
}

// Observers

size_t DeviceClassifier::dimension() const {
  return m_fields.size();
}

