
#include <CompuCell3D/DiffSecrData.h>
#include <XMLCereal/XMLPullParser.h>
#include <XMLCereal/XMLSerializer.h>
#include <BasicUtils/BasicString.h>
#include <BasicUtils/BasicException.h>
#include <PublicUtilities/StringUtils.h>
#include <CompuCell3D/Automaton/Automaton.h>

using namespace CompuCell3D;
using namespace std;

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


   while(in.check(START_ELEMENT)) {
   
      if (in.getName() == "DiffusionConstant") {
         cerr<<"Got Diffusion constant tag"<<endl;
         diffConst = BasicString::parseDouble(in.matchSimple());
      }
      else if (in.getName() == "DecayConstant") {
         cerr<<"Got decay constant tag"<<endl;
         decayConst = BasicString::parseDouble(in.matchSimple());
      }
      else if (in.getName() == "DeltaX") {
         deltaX = BasicString::parseDouble(in.matchSimple());
      }
      else if (in.getName() == "DeltaT") {
         deltaT = BasicString::parseDouble(in.matchSimple());
      }
      else if (in.getName() == "DoNotDiffuseTo") {
         string avoidType;
         avoidType= in.matchSimple();
         avoidTypeIdSet.insert(automaton->getTypeId(avoidType));
         //avoidTypeVec.push_back(avoidType);
      }
      else if (in.getName() == "ConcentrationFileName"){
         concentrationFileName=in.matchSimple();
      }
      
         
/*      else if (in.getName() == "Secretion") {
         string secreteType;
         float secrConst;
         unsigned char typeId;
         secreteType = in.getAttribute("Type").value;
         typeId=automaton->getTypeId(secreteType);
         secrConst = BasicString::parseDouble(in.matchSimple());
         
         typeIdSecrConstMap.insert(make_pair(typeId,secrConst));  
      }*/
         
      else if (in.getName() == "FieldName") {
         fieldName = in.matchSimple();
      }else{
         throw BasicException(string("Unexpected element '") + in.getName() +
                           "'!", in.getLocation());
      }
   
      //writing diffusion description
      in.skip(TEXT);
   }
   cout<<*this<<endl;
   
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void SecretionData::readXML(XMLPullParser &in){

   in.skip(TEXT);

   
   while(in.check(START_ELEMENT)) {
   
      if (in.getName() == "SecretionOnContact") {
         string secreteType;
         float secrConst;
         unsigned char typeId;
         unsigned char contactTypeId;
         vector<string> contactTypeNamesVec;
         string contactTypeName;
         std::map<unsigned char,SecretionOnContactData>::iterator mitr;
         
         secreteType = in.getAttribute("Type").value;
         typeId=automaton->getTypeId(secreteType);

         if(in.findAttribute("SecreteOnContactWith")>=0){
            contactTypeName=in.getAttribute("SecreteOnContactWith").value;
            //parseStringIntoList(contactTypeNames,contactTypeNamesVec,",");
            
         }
         
         contactTypeId=automaton->getTypeId(contactTypeName);
         
/*         ASSERT_OR_THROW(
            "There has to be at least one entry in the ContactTypes",
            contactTypeNamesVec.size()>0
         );*/
         
         secrConst = BasicString::parseDouble(in.matchSimple());

         //SecretionOnContactData secrOnContactData;
         //secrOnContactData.secrConst=secrConst;
         
         

         mitr=typeIdSecrOnContactDataMap.find(typeId);
         
         if(mitr != typeIdSecrOnContactDataMap.end() ){
            mitr->second.contactCellMap.insert(make_pair(contactTypeId,secrConst));
         }else{
            SecretionOnContactData secrOnContactData;
            secrOnContactData.contactCellMap.insert(make_pair(contactTypeId,secrConst));
            typeIdSecrOnContactDataMap.insert(make_pair(typeId,secrOnContactData));   
         }

         //init set of contactTypeId's
/*         std::set<unsigned char> contactCellSet;
         for(unsigned int i = 0 ; i < contactTypeNamesVec.size() ; ++ i){
            secrOnContactData.contactCellSet.insert(automaton->getTypeId(contactTypeNamesVec[i]) );
         }*/
         

                  
         //secretionFcnPtrVec.push_back(&FlexibleDiffusionSolverFE::)
         //secretionName="SecretionOnContact";
         secrTypesNameSet.insert("SecretionOnContact");
         
         in.skip(TEXT);
         //break; //only one secretion Data allowed
      }
      else if (in.getName() == "Secretion") {
         string secreteType;
         float secrConst;
         unsigned char typeId;
         secreteType = in.getAttribute("Type").value;
         typeId=automaton->getTypeId(secreteType);
         secrConst = BasicString::parseDouble(in.matchSimple());
         
         typeIdSecrConstMap.insert(make_pair(typeId,secrConst));
         
         //secretionName="Secretion";
         secrTypesNameSet.insert("Secretion");
         in.skip(TEXT);
         //break; //only one secretion Data allowed
      }

      
      else{
         throw BasicException(string("Unexpected element '") + in.getName() +
                           "'!", in.getLocation());
      }
   
      //writing diffusion description
      in.skip(TEXT);
   }
   //activate secretion function
   active=true;
}


