/*************************************************************************
 *    CompuCell - A software framework for multimodel simulations of     *
 * biocomplexity problems Copyright (C) 2003 University of Notre Dame,   *
 *                             Indiana                                   *
 *                                                                       *
 * This program is free software; IF YOU AGREE TO CITE USE OF CompuCell  *
 *  IN ALL RELATED RESEARCH PUBLICATIONS according to the terms of the   *
 *  CompuCell GNU General Public License RIDER you can redistribute it   *
 * and/or modify it under the terms of the GNU General Public License as *
 *  published by the Free Software Foundation; either version 2 of the   *
 *         License, or (at your option) any later version.               *
 *                                                                       *
 * This program is distributed in the hope that it will be useful, but   *
 *      WITHOUT ANY WARRANTY; without even the implied warranty of       *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    *
 *             General Public License for more details.                  *
 *                                                                       *
 *  You should have received a copy of the GNU General Public License    *
 *     along with this program; if not, write to the Free Software       *
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.        *
 *************************************************************************/

#include "SurfaceFlexPlugin.h"
#include "SurfaceFlexEnergy.h"

#include <CompuCell3D/Simulator.h>
#include <CompuCell3D/Potts3D/Potts3D.h>
using namespace CompuCell3D;

#include <XMLCereal/XMLPullParser.h>
#include <XMLCereal/XMLSerializer.h>


#include <iostream>
using namespace std;

SurfaceFlexPlugin::SurfaceFlexPlugin() : potts(0) {}

SurfaceFlexPlugin::~SurfaceFlexPlugin() {
  if (surfaceEnergy) delete surfaceEnergy;
}


void SurfaceFlexPlugin::init(Simulator *simulator) {

  potts = simulator->getPotts();
  cellFieldG = potts->getCellFieldG();
  
  surfaceEnergy = new SurfaceFlexEnergy(cellFieldG);
  potts->registerEnergyFunction(surfaceEnergy);

  potts->registerCellGChangeWatcher(this);


}

void SurfaceFlexPlugin::extraInit(Simulator *simulator){
   cerr<<"potts addr="<<potts<<endl;
   surfaceEnergy->initTypeId(potts);
}




void SurfaceFlexPlugin::field3DChange(const Point3D &pt, CellG *newCell,
				 CellG *oldCell) {

  unsigned int token = 0;
  double distance;
  int oldDiff = 0;
  int newDiff = 0;
  Point3D n;
  CellG *nCell=0;
  
   
  // Count surface difference
  while (true) {
    n = cellFieldG->getNeighbor(pt, token, distance, false);
    if (distance > 1) break;
     nCell = cellFieldG->get(n); //pulls out cell from a field
         
    if (newCell == nCell) newDiff--;
    else newDiff++;

    if (oldCell == nCell) oldDiff++;
    else oldDiff--;
  }
    //newCell is aggregate of objects ; classNode stores offset(in the cell aggregate) to surfaceNode ;   

  if (newCell) newCell->surface += newDiff;
  if (oldCell) oldCell->surface += oldDiff;
     

}



void SurfaceFlexPlugin::readXML(XMLPullParser &in) {
  surfaceEnergy->readXML(in);
}

void SurfaceFlexPlugin::writeXML(XMLSerializer &out) {
  surfaceEnergy->writeXML(out);
}
