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

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

#include "Sprinkle.hxx"

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

CODE_MODULE_DECLARATION( Sprinkle, Sprinkle );

using namespace std;

void Sprinkle::oracle() { signpost dprdebug_block_signpost(__FILE__,__LINE__,__FUNCTION__); 
  catomID startID=0;
  catomID endID=20000; //0xffffffff;
  double Z = 10;
  double Xstart = 0, Xend = 10, Ystart = 0, Yend = 10;
  double Rate = 1.0;
  long n = 0;

  // running with simulationStart()

  // get options from experiment file
  string tmp;
  tmp = worldPtr->search_key_value_list( "Sprinkle_startID" );
  if (tmp!="") startID = strtoul( tmp.c_str(), 0, 0 );
  tmp = worldPtr->search_key_value_list( "Sprinkle_endID" );
  if (tmp!="") endID = strtoul( tmp.c_str(), 0, 0 );
  tmp = worldPtr->search_key_value_list( "Sprinkle_Xstart" );
  if (tmp!="") Xstart = strtod( tmp.c_str(), 0 );
  tmp = worldPtr->search_key_value_list( "Sprinkle_Ystart" );
  if (tmp!="") Ystart = strtod( tmp.c_str(), 0 );
  tmp = worldPtr->search_key_value_list( "Sprinkle_Xend" );
  if (tmp!="") Xend = strtod( tmp.c_str(), 0 );
  tmp = worldPtr->search_key_value_list( "Sprinkle_Yend" );
  if (tmp!="") Yend = strtod( tmp.c_str(), 0 );
  tmp = worldPtr->search_key_value_list( "Sprinkle_Z" );
  if (tmp!="") Z = strtod( tmp.c_str(), 0 );
  tmp = worldPtr->search_key_value_list( "Sprinkle_Rate" );
  if (tmp!="") Rate = strtod( tmp.c_str(), 0 );
  tmp = worldPtr->search_key_value_list( "Sprinkle_n" );
  if (tmp!="") n = strtoul( tmp.c_str(), 0, 0 );

  double t = 0.0;
  catomID cID = endID;
  CatomSim *c;

  oracleYield();

  do {
    // running with oracles only
    while ( t < 1.0 ) {

      // get next catom in range
      bool already_wrapped = false;
      while (1) {
        if (cID==endID) {
          if (already_wrapped) {
            cerr << "Sprinkle: ERROR - no catoms in ID range\n";
            oracleExit();
          }
          cID = startID;
          already_wrapped = true;
        } else cID++;
        if ( worldPtr->catomHash.find(cID) != worldPtr->catomHash.end() ) break;
      }
      cerr << "Sprinkle: using cID " << cID <<"\n";
      c = worldPtr->catomHash[cID];

      // move it to (random x, random y, Z)
      double x = Xstart + (Xend-Xstart)*(((double)rand())/RAND_MAX);
      double y = Ystart + (Yend-Ystart)*(((double)rand())/RAND_MAX);
      c->C.moveTo( x, y, Z );

      // next one should arrive based on exponential interarrival times
      t += - log( ((double)rand())/RAND_MAX )/Rate;
    }
    t -= 1.0;
    n --;
    oracleYield();
    // running with newTick(), endTick(), other oracles
    oracleYield();
  } while ( n != 0 );

  // done
}

