///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright (C) 2006 by Intel Corporation and Carnegie Mellon University    //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <errno.h>
#include <string.h>

#include "CatomStick.hxx"
#include "CatomWorld.hxx"
#include "CatomSim.hxx"

// comment out to avoid updating magnets when not moving
#define no_optimization 1

CODE_MODULE_DECLARATION( CatomStick, CatomStick, 1 );

using namespace std;

void CatomStick::newTick() { signpost dprdebug_block_signpost(__FILE__,__LINE__,__FUNCTION__); 
#ifdef no_optimization
  need_update=true;
#else
  CatomSim *c = worldPtr->catomHash[hostCatom];
  Point3D tmppos = c->C.getLocation();
  if ((tmppos-lastpos).norm()>0.1) {
    need_update=true;
    set<CatomSim*>::iterator it;
    for ( it=c->nearCatoms.begin(); it!=c->nearCatoms.end(); it++ ) {
      REMOTE_CODE_MODULE((*it)->C.getID(), CatomStick )->need_update = true;
    }
  }
  lastpos = tmppos;
#endif
}

void CatomStick::endTick() { signpost dprdebug_block_signpost(__FILE__,__LINE__,__FUNCTION__); 
  unsigned int i;
  CatomSim *c = worldPtr->catomHash[hostCatom];
  double dist[NUM_FEATURES+1];
  if (need_update) need_update=false;
  else return;
  for (i=1; i<=NUM_FEATURES; i++) {
    c->magnet_state[i] = 0;
    dist[i] = 1000;
  }
  set<CatomSim*>::iterator it;
  for ( it=c->nearCatoms.begin(); it!=c->nearCatoms.end(); it++ ) {
    catomID rid = (*it)->C.getID();
    int rmode = REMOTE_CODE_MODULE( rid, CatomStick )->mode;
    Point3D rcenter = (*it)->C.getLocation();
    double rdist = (c->C.getLocation()-rcenter).norm();
    featureID dir = c->C.getNearestFeature( rcenter );
    if ( rdist < dist[dir] && rdist < 2.2*CatomSim::catom_radius) {
      dist[dir] = rdist;
      if ( mode==-1 || rmode==-1 ) {  // repel
        c->magnet_state[dir] = ((rid+hostCatom)&0x01)?1:-1;
      } else if ( mode==1 && rmode==1 ) {  // attract  -- do we want && or || here?
        c->magnet_state[dir] = (rid < hostCatom)?1:-1;
      } else {  // neither
        c->magnet_state[dir]=0;
      }
    }
  }
}

