///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright (C) 2006 by Intel Coproration and Carnegie Mellon University    //
// Contacts: casey.j.helfrich @ intel.com                                    //
//           bdr @ cs.cmu.edu                                                //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

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

#include "XYMelt.hxx"
#include "CatomSim.hxx"

CODE_MODULE_DECLARATION( XYMelt, XYMelt );

#include "CatomWorld.hxx"

using namespace std;


StateFile::Module* XYMelt::StateFileConstructor() {

  myModule_ = StateFile::Module::getInstance( name_ );

  // NOTE: Set Skip to true if you are not currently using save/load
  myModule_->setSkip( true );
  
  // Check to see if this module has already been setup
  if (myModule_->getVersion())
    return myModule_;

  // If not, set up this module for the first time
  myModule_->setVersion( 1 );
  myModule_->setVersionRange( 1 );
  myModule_->setContentProfile( "c" );
  myModule_->setContentNames( "isMoving" );

  return myModule_;
}

void XYMelt::newTick() {
  
  Catom * hostCatom2 = &(worldPtr->catomHash[hostCatom]->C);

  // If I'm powered off, I can't do anything
  if(!(hostCatom2->amPowered())) {
    return;
  }

  // If I'm on the floor I'm done, power down.
  if(hostCatom2->amOnFloor()) {
    hostCatom2->setBatteryLife(0);
    hostCatom2->setColor(0,0,255,0);
    return;
  }
  
  // Check downward (if no one is there, move there)
  if(hostCatom2->getNeighbor(6) == 0) {
    Point3D newLoc = (hostCatom2->getLocation()).plus(Point3D(0,0,-2));

/*    catomSim->location = newLoc;
    
    double newHigh[3] = {newLoc.getX() + 1, 
			 newLoc.getY() + 1, 
			 newLoc.getZ() + 1}; 
    double newLow[3] = {newLoc.getX() - 1, 
			newLoc.getY() - 1, 
			newLoc.getZ() - 1}; 
    worldPtr->updateCatomTreeRegion(worldPtr->catomHash[hostCatom],
				    newLow, 
				    newHigh); 
*/
   hostCatom2->moveTo( newLoc );
    
    return;    
  }

  // If I made it this far, there are some potential moves to check for

  // If someone is on top of me and is not part of the model,
  // I don't move for now
  unsigned int temp = hostCatom2->getNeighbor(1);
  if(temp != 0) {
    if(worldPtr->catomHash[temp]->green != 0.5)
      return;
  }
    
  // Choose +x or +y movement
  unsigned int right = rand() % 2;
  
  if(right) {
    // Check to the +x (if no one is there, move there)
    if(hostCatom2->getNeighbor(2) == 0) {
      Point3D newLoc = (hostCatom2->getLocation()).plus(Point3D(2,0,0));

/*      catomSim->location = newLoc;
      
      // update rTree
      double newHigh[3] = {newLoc.getX() + 1, 
			   newLoc.getY() + 1, 
			   newLoc.getZ() + 1}; 
      double newLow[3] = {newLoc.getX() - 1, 
			  newLoc.getY() - 1, 
			  newLoc.getZ() - 1}; 
      worldPtr->updateCatomTreeRegion(worldPtr->catomHash[hostCatom],
				      newLow, 
				      newHigh); 
*/
      hostCatom2->moveTo( newLoc );
            
      // Imediately check downward
      if(hostCatom2->getNeighbor(6) == 0) {
	Point3D newLoc = (hostCatom2->getLocation()).plus(Point3D(0,0,-2));
	
/*	// update rTree
	double newHigh[3] = {newLoc.getX() + 1, 
			     newLoc.getY() + 1, 
			     newLoc.getZ() + 1}; 
	double newLow[3] = {newLoc.getX() - 1, 
			    newLoc.getY() - 1, 
			    newLoc.getZ() - 1}; 
	worldPtr->updateCatomTreeRegion(worldPtr->catomHash[hostCatom],
					newLow, 
					newHigh); 
	catomSim->location = newLoc;    
*/
	hostCatom2->moveTo( newLoc );
      }  
    }    
    return;
  } else {
    // Check to the +y (if no one is there, move there)
    if(hostCatom2->getNeighbor(3) == 0) {
      Point3D newLoc = (hostCatom2->getLocation()).plus(Point3D(0,2,0));

/*      catomSim->location = newLoc;
      
      // update rTree
      double newHigh[3] = {newLoc.getX() + 1, 
			   newLoc.getY() + 1, 
			   newLoc.getZ() + 1}; 
      double newLow[3] = {newLoc.getX() - 1, 
			  newLoc.getY() - 1, 
			  newLoc.getZ() - 1}; 
      worldPtr->updateCatomTreeRegion(worldPtr->catomHash[hostCatom],
				      newLow, 
				      newHigh); 
*/
      hostCatom2->moveTo( newLoc );
      
      
      // Imediately check downward
      if(hostCatom2->getNeighbor(6) == 0) {
	Point3D newLoc = (hostCatom2->getLocation()).plus(Point3D(0,0,-2));
	
/*	// update rTree
	double newHigh[3] = {newLoc.getX() + 1, 
			     newLoc.getY() + 1, 
			     newLoc.getZ() + 1}; 
	double newLow[3] = {newLoc.getX() - 1, 
			    newLoc.getY() - 1, 
			    newLoc.getZ() - 1}; 
	worldPtr->updateCatomTreeRegion(worldPtr->catomHash[hostCatom],
					newLow, 
					newHigh); 
	catomSim->location = newLoc;    
*/
	hostCatom2->moveTo( newLoc );
      }  
    }    
    return;
  }
}
