#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <cassert>

#include "FitBeam.h"
#include "FitConf.h"

#include "Rtypes.h"

//using namespace std;

FitConf* FitConf::instance = 0;

FitConf* FitConf::GetInstance()
{
  if (instance == 0) instance = new FitConf;
  return instance;
}

FitConf::FitConf()
{
  std::cout<<"FitConf constructed"<<std::endl;
  ResetVectors();
}
FitConf::~FitConf()
{
}
void FitConf::ResetVectors()
{
  // default config (pidcut not really used since my pans are filtered):
  neugen=false; neugen_conf_name=""; neugen_conf_no=0; pidcut=0.2; cutlowy=false; doinuke=false;
  xsecrw=false; maqe=1.0; mares=1.0; kno=1.0; smooth_width=0.0;
  nFix=0;
  nuemrccfile="";
  nuemrcchist="";
  beamType.clear();
  mcPOT.clear();
  dataPOT.clear();
  dataPATH.clear();
  dataNAME.clear();
  mcPATH.clear();
  mcNAME.clear();
  zflPar.clear();
  zflMin.clear();
  zflMax.clear();
  zflFix.clear();
  zbmFix.clear();
  detFix.clear();
  zbmPar.clear(); 
  zbmMin.clear();
  zbmMax.clear();
  zbmPen.clear();
  detPar.clear();
  detMin.clear();
  detMax.clear();
  detPen.clear();
}
void FitConf::ReadInput(const char* inputFile)
{
  std::string inp_file=inputFile;
  std::ifstream stream;
  stream.open(inp_file.c_str());
  assert(stream.is_open() && "Can't open input file"); 
  std::cout <<"Reading beam data from "<<inp_file<<std::endl;  
  std::string sline;
  char cline[200];

  ResetVectors();
 
  while (stream.getline(cline,200))
    {
      sline=cline;
      if (sline.find("*",0)==0||sline.size()==0) continue;  //lines that start with * are ignored
	  unsigned int i;
	  i=sline.find("NPAR");
	  if (i!=std::string::npos)
	    {
	      int NPAR;
	      NPAR=atoi((sline.substr(4,sline.size()-4)).c_str());
	    }
	  if (sline.find("NEUGEN")!=std::string::npos)
	    {
	      neugen=true;
	      if (sline.find("false")!=std::string::npos) neugen=false;
 	      while (sline.find(" ",0)<sline.size()) sline.replace(sline.find(" ",0),1,"");
	      neugen_conf_name=sline.substr(sline.find("{")+1,sline.find(",")-sline.find("{")-1);
	      neugen_conf_no=atoi(sline.substr(sline.find(",")+1,sline.find("}")-sline.find(",")+1).c_str());
	      continue;
	    }
	  if (sline.find("PIDCUT")!=std::string::npos)
	    {
	      sline=sline.substr(6,sline.size()-6);
	      while (sline.find(" ",0)<sline.size()) sline.replace(sline.find(" ",0),1,"");
	      pidcut=atof(sline.c_str());
	      continue;
	    }
	  if (sline.find("SMOOTH")!=std::string::npos)
	    {
	      sline=sline.substr(6,sline.size()-6);
	      while (sline.find(" ",0)<sline.size()) sline.replace(sline.find(" ",0),1,"");
	      smooth_width=atof(sline.c_str());
	      
	      continue;
	    }
	  if (sline.find("CUTLOWY")!=std::string::npos)
	    {
	      if (sline.find("true")!=std::string::npos) cutlowy=true;
	      continue;
	    }
	  if (sline.find("DOINUKE")!=std::string::npos)
	    {
	      if (sline.find("true")!=std::string::npos) doinuke=true;
	      continue;
	    }
	  if (sline.find("XSECRW")!=std::string::npos)
	    {
	      sline=sline.substr(6,sline.size()-6);
	      while (sline.find(" ",0)<sline.size()) sline.replace(sline.find(" ",0),1,"");
	      if (sline.find("true")!=std::string::npos)
		{
		  xsecrw=true;
		  maqe=atof(sline.substr(sline.find("{")+1,
					 sline.find_first_of(",")-sline.find("{")-1).c_str());
		  mares=atof(sline.substr(sline.find_first_of(",")+1,
					  sline.find_last_of(",")-sline.find_first_of(",")-1).c_str());
		  kno=atof(sline.substr(sline.find_last_of(",")+1,
					sline.find("}")-sline.find_last_of(",")-1).c_str());
		}
	      continue;
	    }
    	  if (sline.find("MINUIT")!=std::string::npos)
	    {
	      if (sline.find("SIMPLEX")!=std::string::npos) minCom.push_back("SIMPLEX");
	      if (sline.find("MIGRAD")!=std::string::npos) minCom.push_back("MIGRAD");
	      if (sline.find("IMPROVE")!=std::string::npos) minCom.push_back("IMPROVE");
	      if (sline.find("MINOS")!=std::string::npos) minCom.push_back("MINOS");
	      if (sline.find("HESSE")!=std::string::npos) minCom.push_back("HES");
	      continue;
	    }
	  if (sline.find("NUEMRCC")!=std::string::npos)
	    {
	      while (sline.find(" ",0)<sline.size()) sline.replace(sline.find(" ",0),1,"");
	      nuemrccfile=sline.substr(sline.find("{")+1,
				       sline.find(",")-sline.find("{")-1);
	      nuemrcchist=sline.substr(sline.find(",")+1,
                                       sline.find("}")-sline.find(",")-1);
	    }
	  i=sline.find("FITBEAMS");
	  if (i!=std::string::npos)
	    {
	      while (sline.substr(0,8)!="ENDBEAMS")
		{
		  stream.getline(cline,200);
		  sline=cline;
		  int j;
		  while (sline.find(" ",0)<sline.size())
		    {
		      j=sline.find(" ",0);
		      sline.replace(j,1,"");
		    }
		  if (sline.find("*",0)==0||sline.size()==0) continue;
		  if (sline.find("MCPAN")!=std::string::npos)
		    {
		      mcPATH.push_back(sline.substr(sline.find("{")+1,
						    sline.find_first_of(",")-sline.find("{")-1));
		      mcNAME.push_back(sline.substr(sline.find_last_of(",")+1,
						    sline.find("}")-sline.find_last_of(",")-1));
		    }
		  else if (sline.find("DATAHIST")!=std::string::npos)
		    {
		      dataPATH.push_back(sline.substr(sline.find("{")+1,
						      sline.find_first_of(",")-sline.find("{")-1));
		      dataNAME.push_back(sline.substr(sline.find_last_of(",")+1,
						      sline.find("}")-sline.find_last_of(",")-1));
		    }
		  else if (sline.find("ENDBEAMS")==std::string::npos)
		    {
		          
		      beamType.push_back(FitBeam::AsInt(FitBeam::StringToEnum(
							sline.substr(0,sline.find("{")))));
		      dataPOT.push_back(atof((sline.substr(
					     sline.find("{")+1,
					     sline.find(",")-sline.find("{")-1)).c_str()));
		      mcPOT.push_back(atof((sline.substr(
		        		   sline.find(",")+1,
					   sline.find("}")-sline.find(",")-1)).c_str()));
										  
		    }
		}
	    }
	  i=sline.find("ZFLUK");
	  if (i!=std::string::npos)
	    {
	      while (sline.substr(0,8)!="ENDZFLUK")
		{
		  stream.getline(cline,100);
		  sline=cline;
		  int j;
		  while (sline.find(" ",0)<sline.size())
		    {
		      j=sline.find(" ",0);
		      sline.replace(j,1,"");
		    }
		  if (sline.find("*",0)==0||sline.size()==0) continue;
		  if (sline.find("PTPENALTY",0)!=0&&sline.find("END")!=0){
		    zflPar.push_back(atof(sline.substr(sline.find("{")+1,sline.find_first_of(",")-sline.find("{")-1).c_str()));
		    zflMin.push_back(atof(sline.substr(sline.find_first_of(",")+1,sline.find_last_of(",")-sline.find_first_of(",")-1).c_str()));
		    zflMax.push_back(atof(sline.substr(sline.find_last_of(",")+1,sline.find("}")-sline.find_last_of(",")-1).c_str()));
		    if (sline.find("fix")!=std::string::npos) {zflFix.push_back(1); nFix++;}
		    else zflFix.push_back(0);
		  }
		  else if (sline.find("PTPENALTY",0)==0)
		    {
		      piPlusPTpenalty=atof(sline.substr(sline.find("{")+1,sline.find(",")-sline.find("{")-1).c_str());
		      piMinusPTpenalty=atof(sline.substr(sline.find_first_of(",")+1,sline.find("}")-sline.find_last_of(",")-1).c_str());
		    }
		}
	    }
	  i=sline.find("ZBEAM");
	  if (i!=std::string::npos)
	    {
	      while (sline.substr(0,8)!="ENDZBEAM")
		{
		  stream.getline(cline,100);
		  sline=cline;
		  int j;
		  while (sline.find(" ",0)<sline.size())
		    {
		      j=sline.find(" ",0);
		      sline.replace(j,1,"");
		    }
		  if (sline.find("*",0)==0||sline.size()==0) continue;
		  if (sline.find("END")!=0) {
		  int fcm=sline.find_first_of(",");
		  zbmPar.push_back(atof(sline.substr(sline.find("{")+1,fcm-sline.find("{")-1).c_str()));
		  zbmMin.push_back(atof(sline.substr(sline.find_first_of(",")+1,sline.find_first_of(",",fcm+1)-sline.find_first_of(",")-1).c_str()));
		  zbmMax.push_back(atof(sline.substr(sline.find_first_of(",",fcm+1)+1,sline.find_last_of(",")-sline.find_first_of(",",fcm+1)-1).c_str()));
		  zbmPen.push_back(atof(sline.substr(sline.find_last_of(",")+1,sline.find("}")-sline.find_last_of(",")-1).c_str()));
		  if (sline.find("fix")!=std::string::npos) {zbmFix.push_back(1); nFix++;}
		  else zbmFix.push_back(0);
		  }
		}
	    }
	  
	  i=sline.find("DET");
	  if (i!=std::string::npos)
	    {
	      while (sline.substr(0,8)!="ENDDET")
		{
		  stream.getline(cline,100);
		  sline=cline;
		  int j;
		  while (sline.find(" ",0)<sline.size())
		    {
		      j=sline.find(" ",0);
		      sline.replace(j,1,"");
		    }
		  if (sline.find("*",0)==0||sline.size()==0) continue;
		  int fcm=sline.find_first_of(",");
		  if (sline.find("END")!=0) {
		  detPar.push_back(atof(sline.substr(sline.find("{")+1,fcm-sline.find("{")-1).c_str()));
		  detMin.push_back(atof(sline.substr(sline.find_first_of(",")+1,sline.find_first_of(",",fcm+1)-sline.find_first_of(",")-1).c_str()));
		  detMax.push_back(atof(sline.substr(sline.find_first_of(",",fcm+1)+1,sline.find_last_of(",")-sline.find_first_of(",",fcm+1)-1).c_str()));
		  detPen.push_back(atof(sline.substr(sline.find_last_of(",")+1,sline.find("}")-sline.find_last_of(",")-1).c_str()));
		  if (sline.find("fix")!=std::string::npos) {detFix.push_back(1); nFix++;}
		  else detFix.push_back(0); 
		  }
		}
	    }
    }
  if ((dataPOT.size()!=mcPOT.size())||
      (dataPOT.size()!=beamType.size())||
      (dataPOT.size()!=dataPATH.size())||
      (dataPOT.size()!=dataNAME.size())||
      (dataPOT.size()!=mcPATH.size())||
      (dataPOT.size()!=mcNAME.size()))
    std::cerr<< "Input file doesn't have all the necessary data for MC pans and data histograms!!"<<std::endl;


  stream.close();
  /*
  for (unsigned int n=0;n<beamType.size();n++)
    {
      cout <<mcPATH[n]<<" "<<dataPOT[n]<<" "<<mcPOT[n]<<endl; 
    }
 for (unsigned int n=0;n<zflPar.size()-1;n++)
    {
      cout <<zflPar[n]<<" "<<zflMin[n]<<" "<<zflMax[n]<<endl; 
    }
 for (unsigned int n=0;n<zbmPar.size()-1;n++)
    {
      cout <<zbmPar[n]<<" "<<zbmMin[n]<<" "<<zbmMax[n]<<" "<<zbmPen[n]<<endl; 
    }
 for (unsigned int n=0;n<detPar.size()-1;n++)
    {
      cout <<detPar[n]<<" "<<detMin[n]<<" "<<detMax[n]<<" "<<detPen[n]<<endl; 
    }

  */
}
