
 
#include "PlayerSettingsPlugin.h"
using namespace CompuCell3D;

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

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

#include <BasicUtils/BasicString.h>
#include <BasicUtils/BasicException.h>
#include <PublicUtilities/StringUtils.h>
#include <iostream>
#include <algorithm>

using namespace std;

PlayerSettingsPlugin::PlayerSettingsPlugin() {}

PlayerSettingsPlugin::~PlayerSettingsPlugin() {}

void PlayerSettingsPlugin::extraInit(Simulator *simulator) {
   Potts3D *potts=simulator->getPotts();
   Dim3D fieldDim = potts->getCellFieldG()->getDim();

/*     cerr<<"\n\n\\t\t\tPlayer Settings \n\n";
      cerr<<"playerSettings.xyProjFlag="<<playerSettings.xyProjFlag<<endl;
      cerr<<"playerSettings.xyProj="<<playerSettings.xyProj<<endl;*/
   ///Making sure that player settings are reasonable
   if(playerSettings.xyProjFlag){
//       cerr<<"playerSettings.xyProjFlag="<<playerSettings.xyProjFlag<<endl;
      ASSERT_OR_THROW("Value of XYProj has to be within limits for z dimension of the field",
         playerSettings.xyProj>0 && playerSettings.xyProj<fieldDim.z
      );
//       cerr<<"playerSettings.xyProj="<<playerSettings.xyProj<<endl;
   }

   if(playerSettings.xzProjFlag){
      ASSERT_OR_THROW("Value of XZProj has to be within limits for y dimension of the field",
         playerSettings.xzProj>0 && playerSettings.xyProj<fieldDim.y
      );
   }

   if(playerSettings.yzProjFlag){
      ASSERT_OR_THROW("Value of YZProj has to be within limits for x dimension of the field",
         playerSettings.yzProj>0 && playerSettings.yzProj<fieldDim.x
      );
   }

   if(playerSettings.rotationXFlag){
      ASSERT_OR_THROW("Value of XRot must be between -180 and 180",
         playerSettings.rotationX>=-180 && playerSettings.rotationX<=180
      );
   }

   if(playerSettings.rotationYFlag){
      ASSERT_OR_THROW("Value of YRot must be between -180 and 180",
         playerSettings.rotationY>=-180 && playerSettings.rotationY<=180
      );
   }

      if(playerSettings.rotationZFlag){
      ASSERT_OR_THROW("Value of ZRot must be between -180 and 180",
         playerSettings.rotationZ>=-180 && playerSettings.rotationZ<=180
      );
   }

//    cerr<<"\n\n\\t\t\tPlayer Settings \n\n"; 
   
      
}

// PlayerSettings PlayerSettingsPlugin::getPlayerSettings()  {
//    return playerSettings;
// 
// }



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

  int attrNum;
  
  while (in.check(START_ELEMENT)) {
    if (in.getName() == "Project2D") {
    
//       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;

      ///reading 2D settings - projections
      attrNum=in.findAttribute("XYProj");
      if(attrNum != -1){
         playerSettings.xyProj=BasicString::parseUInteger(in.getAttribute("XYProj").value);
         playerSettings.xyProjFlag=true;
      }

      attrNum=in.findAttribute("XZProj");
      if(attrNum != -1){
         playerSettings.xzProj=BasicString::parseUInteger(in.getAttribute("XZProj").value);
         playerSettings.xzProjFlag=true;
      }
      
      attrNum=in.findAttribute("YZProj");
      if(attrNum != -1){
         playerSettings.yzProj=BasicString::parseUInteger(in.getAttribute("YZProj").value);
         playerSettings.yzProjFlag=true;
      }
            
      
      in.matchSimple();
    }
    else if (in.getName() == "Rotate3D"){
      ///reading  3D rotations parameters - used by player
      attrNum=in.findAttribute("XRot");
      if(attrNum != -1){
         playerSettings.rotationX=BasicString::parseUInteger(in.getAttribute("XRot").value);
         playerSettings.rotationXFlag=true;
      }

      attrNum=in.findAttribute("YRot");
      if(attrNum != -1){
         playerSettings.rotationY=BasicString::parseUInteger(in.getAttribute("YRot").value);
         playerSettings.rotationYFlag=true;
      }

      attrNum=in.findAttribute("ZRot");
      if(attrNum != -1){
         playerSettings.rotationZ=BasicString::parseUInteger(in.getAttribute("ZRot").value);
         playerSettings.rotationZFlag=true;
      }
      in.matchSimple();
                  
    }
    else if(in.getName() == "Resize3D"){
      ///reading  3D widget size parameters used by player - the bigger the smaller object will be
      attrNum=in.findAttribute("X");
      if(attrNum != -1){
         playerSettings.sizeX3D=BasicString::parseUInteger(in.getAttribute("X").value);
         playerSettings.sizeX3DFlag=true;
      }

      attrNum=in.findAttribute("Y");
      if(attrNum != -1){
         playerSettings.sizeY3D=BasicString::parseUInteger(in.getAttribute("Y").value);
         playerSettings.sizeY3DFlag=true;
      }

      attrNum=in.findAttribute("Z");
      if(attrNum != -1){
         playerSettings.sizeZ3D=BasicString::parseUInteger(in.getAttribute("Z").value);
         playerSettings.sizeY3DFlag=true;
      }
      
      in.matchSimple();
    }
    else if(in.getName() == "InitialProjection"){
      attrNum=in.findAttribute("Projection");
      if(attrNum != -1){
         playerSettings.initialProjection=in.getAttribute("Projection").value;
         //changing to lowercase 
         changeToLower(playerSettings.initialProjection);
         ASSERT_OR_THROW("InitialProjection has have a value of xy or xz or yz",
         playerSettings.initialProjection=="xy" || playerSettings.initialProjection=="xz" || playerSettings.initialProjection=="yz"
         );
      }
      in.matchSimple();
    }

    
    else {
      throw BasicException(string("Unexpected element '") + in.getName() +
                           "'!", in.getLocation());
    }

    in.skip(TEXT);
  }

  
  
}

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