/*************************************************************************
 *    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 "CellTypePlugin.h"
// #include <CompuCell3D/Automaton/CellType.h>
// using namespace CompuCell3D;
// 
// #include <CompuCell3D/Simulator.h>
// #include <CompuCell3D/Potts3D/Potts3D.h>
// 
// #include <XMLCereal/XMLPullParser.h>
// #include <XMLCereal/XMLSerializer.h>
// 
// #include <BasicUtils/BasicString.h>
// #include <BasicUtils/BasicException.h>
// 
// #include <iostream>
// using namespace std;
// 
// CellTypePlugin::CellTypePlugin() {classType = new CellType(classNode);}
// 
// CellTypePlugin::~CellTypePlugin() {}
// 
// void CellTypePlugin::init(Simulator *simulator) {
// 
//            potts = simulator->getPotts();
// 
//            cellAccessorPtr=potts->getCellAccessorPtr();
// 
//             //potts->getCellFactoryGroupPtr()->registerClass(&cellTypeGAccessor);
//             //cellTypeGAccessorPtr=&cellTypeGAccessor;
// 
//             potts->registerCellDynamicClassNode(&classNode);
//             potts->registerBCGChangeWatcher(this);
//             potts->registerAutomaton(this);
//             classType = new CellType(classNode);
// /*
//            potts = simulator->getPotts();
//       cellAccessorPtr=potts->getCellAccessorPtr();
//            potts->registerCellDynamicClassNode(&classNode);
//            potts->registerBCGChangeWatcher(this);
//            potts->registerAutomaton(this);
//            classType = new CellType(classNode);*/
// }
// 
// unsigned char CellTypePlugin::getCellType(const Cell *cell) const {
//   if (!cell) return 0;
//   else if (classNode.get(cell)->type == 0)
//   {
//       if (drand48() < .5)
//           classNode.get(cell)->type = 1;
//       else
//           classNode.get(cell)->type = 2;
//   }
//   return classNode.get(cell)->type;
// }
// 
// string CellTypePlugin::getTypeName(const char type) const {
//   switch (type) {
//   case 0: return "Medium";
//   case 1: return "NonCondensing";
//   case 2: return "Condensing";
//   default: THROW(string("Unknown cell type ") + BasicString(type) + "!");
//   }
// }
// 
// unsigned char CellTypePlugin::getTypeId(const string typeName) const {
//   if (typeName == "Medium") return 0;
//   else if (typeName == "NonCondensing") return 1;
//   else if (typeName == "Condensing") return 2;
//   else THROW(string("Unknown cell type ") + typeName + "!");
// }
// 
// void CellTypePlugin::readXML(XMLPullParser &in) {
// }
// 
// void CellTypePlugin::writeXML(XMLSerializer &out) {
// }


 
#include "CellTypePlugin.h"
#include <map>
#include <vector>
#include <CompuCell3D/Automaton/CellType.h>
using namespace CompuCell3D;

#include <CompuCell3D/Simulator.h>
#include <CompuCell3D/Potts3D/Potts3D.h>

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

#include <BasicUtils/BasicString.h>
#include <BasicUtils/BasicException.h>

#include <iostream>
using namespace std;

CellTypePlugin::CellTypePlugin() {classType = new CellType();}

CellTypePlugin::~CellTypePlugin() {}

void CellTypePlugin::init(Simulator *simulator) {
           potts = simulator->getPotts();

            potts->registerCellGChangeWatcher(this);
            potts->registerAutomaton(this);
            classType = new CellType();


}

unsigned char CellTypePlugin::getCellType(const CellG *cell) const {

   //cerr<<"getCellType: classNode.get(cell)->type="<<(int)classNode.get(cell)->type<<endl;
   if(!cell) return 0;

   return cell->type;

}


string CellTypePlugin::getTypeName(const char type) const {


  std::map<unsigned char,std::string>::const_iterator typeNameMapItr=typeNameMap.find((const unsigned char)type);

  
  if(typeNameMapItr!=typeNameMap.end()){
      return typeNameMapItr->second;
  }else{
      THROW(string("getTypeName: Unknown cell type  ") + BasicString(type) + "!");
  }


}

unsigned char CellTypePlugin::getTypeId(const string typeName) const {


  std::map<std::string,unsigned char>::const_iterator nameTypeMapItr=nameTypeMap.find(typeName);
  
  
  if(nameTypeMapItr!=nameTypeMap.end()){
      return nameTypeMapItr->second;
  }else{
      THROW(string("getTypeName: Unknown cell type  ") + typeName + "!");
  }

}


// string CellTypePlugin::getTypeName(const char type) const {
//   
//   
//   switch (type) {
//   case 0: return "Medium";
//   case 1: return "NonCondensing";
//   case 2: return "Condensing";
//   case 3: return "Extra";
//   default: THROW(string("getTypeName: Unknown cell type  ") + BasicString(type) + "!");
//   }
// }
// 
// 
// unsigned char CellTypePlugin::getTypeId(const string typeName) const {
//    
//   if (typeName == "Medium") return 0;
//   else if (typeName == "NonCondensing") return 1;
//   else if (typeName == "Condensing") return 2;
//   else if (typeName == "Extra") return 3;
//   else THROW(string("getTypeId: Unknown cell type ") + typeName + "!");
// }

void CellTypePlugin::readXML(XMLPullParser &in) {
  in.skip(TEXT);

   vector<unsigned char> frozenTypeVec;
   
  while (in.check(START_ELEMENT)) {
    if (in.getName() == "CellType") {
      string typeName = in.getAttribute("TypeName").value;
      unsigned char typeId = BasicString::parseUByte(in.getAttribute("TypeId").value);
      cerr<<"typeName="<<typeName<<endl;
      cerr<<"typeId="<<(short)typeId<<endl;
  
      typeNameMap[typeId]=typeName;
      nameTypeMap[typeName]=typeId;

      ///deciding whether to freeze or not
      int attrNum=in.findAttribute("Freeze");
      if(attrNum != -1){
         in.getAttribute("Freeze").value;
         frozenTypeVec.push_back(typeId);
      }
            
      
      in.matchSimple();
    }
    else {
      throw BasicException(string("Unexpected element '") + in.getName() +
                           "'!", in.getLocation());
    }

    in.skip(TEXT);
  }

  potts->setFrozenTypeVector(frozenTypeVec);
  
}

void CellTypePlugin::writeXML(XMLSerializer &out) {
}
