/************************************************************************
 * AhcConfigReader.hh                                                   *
 *                                                                      *
 * class to load HAB settings from a config file                        *
 *                                                                      *
 * Author:  Benjamin Lutz                                               *
 * Version: 1.4                                                         * 
 * date:    12.07.05                                                    *
 *                                                                      *           
 * 06.04.05  added support for different DAC values for each channel    *
 * 12.04.05  added LED_Sel to switch between VCalib destination         *
 * 26.04.05  added getHoldStart() function                              *
 * ??.07.05  added insert function for new data structure (Paul)        *
 * 24.08.05  added readin of STAGE position file                        *
 * 26.01.06  adapting ConfigReader for ahcExpert run of new DAQ         *
 *           (delete all DAQ related part)                              *
 *           and add a selectable trigger type                          *
 *                                                                      *
 * to-do: predifined modes are not supportet until now                  *
 *                                                                      *
 ************************************************************************/

#ifndef AhcConfigReader_h
#define AhcConfigReader_h

#include <iostream>
#include <cstdio>
#include <vector>
#include "AhcVfeConfigurationData.hh"
#include "CrcFeConfigurationData.hh"

using namespace std;

class AhcConfigReader
{

public: 
  AhcConfigReader(char* filename, unsigned printlevel);         // constructor needs name of config file and printlevel
  ~AhcConfigReader();

  void insertSettings(AhcVfeConfigurationData* AHCVfe); // these routines copies the values of the config file into 
  void insertSettings(CrcFeConfigurationData* CRCFe);                // the given data types

  unsigned getHoldStart();
  unsigned getTrigger();
  unsigned getAnalogOutChan();
  unsigned getLEDSel();
  unsigned getHoldEnable();
  unsigned getTcalib();
  unsigned getCalibWidth();
  unsigned getVcalib();
  void setHoldStart(unsigned changehold);
  unsigned getHoldWidth();
  bool getSTAGEenable();
  bool getSTAGEmodemulti();
  int getSTAGExArray(int i);
  int getSTAGEyArray(int i);
  unsigned getSTAGEArraySize();
  unsigned getROchip(int i);
  unsigned getROchan(int i);
  
  
 
private:

  ifstream _configFile;
  ifstream _stageFile;
  string _strBuffer;
  char _charBuffer[128];
  bool _readUser;
  bool _injectionResistor;
  bool _gainCap[4];
  bool _shapingCap[4];
  bool _STAGEenable;
  bool _STAGEuseFile;
  int _STAGExposition;
  int _STAGEyposition;
  char _STAGEfile[128];
  unsigned _rochip;
  unsigned _rochan;
  bool _Tcalib;
  unsigned _Vcalib;
  unsigned _calibWidth;
  bool _LEDSel;
  bool _holdEnable;
  unsigned _holdStart;
  unsigned _holdWidth;
  unsigned _printlevel;
  unsigned _trigger;
  unsigned _analogOutChan;
 
  vector<int> _STAGEchipArray;
  vector<int> _STAGEchanArray;
  vector<int> _STAGExArray;
  vector<int> _STAGEyArray;

  char _fileName[128];

};
 

AhcConfigReader::AhcConfigReader(char* filename, unsigned printlevel)
{
  sprintf(_fileName,"%s",filename);


  _readUser=false;
  _injectionResistor=true;
  _gainCap[0]=true;
  _gainCap[1]=true;
  _gainCap[2]=true;
  _gainCap[3]=true;
  _shapingCap[0]=true;
  _shapingCap[1]=true;
  _shapingCap[2]=true;
  _shapingCap[3]=true;
  _STAGEenable=false;
  _STAGEuseFile=false;
  _STAGExposition=0;
  _STAGEyposition=0;
  _STAGEfile[0]=0;
  _rochip=0;
  _rochan=0;
  _Tcalib=true;
  _Vcalib=0;
  _calibWidth=128;
  _LEDSel=false;
  _holdEnable=true;
  _holdStart=55;
  _holdWidth=64000;
  _printlevel=printlevel;
  _trigger=24;
  _analogOutChan=0;

  cout << "**************************************" << endl << "loading settings from " << filename  << endl << endl;
   
  _configFile.open(filename);

  while (_configFile.good())
    {

      _configFile >> _strBuffer;
      
      if (_strBuffer=="#")
	{
	  _configFile.getline(_charBuffer,sizeof(_charBuffer));
	  if (printlevel >2) cout << "comment: "<< _charBuffer  << endl;
	}

      if (_strBuffer=="mode")
	{
	  _configFile >> _strBuffer;
	  if (_strBuffer=="physics") {}                //notimplemented yet
	  if (_strBuffer=="calibration") {}            //notimplemented yet
	    if (_strBuffer=="user") _readUser = true;
	  if (printlevel >4)	    cout << "found mode setting: "<< _strBuffer  << endl;
	}
      
      if (_readUser && _strBuffer=="injectionResistor")
	{
	  if (printlevel >4)	  cout << "injection resistor setting found" <<endl;
	  _configFile >> _strBuffer;
	  if (_strBuffer == "used")  
	    {
	      cout << "set injection resistor to 10kOhm" << endl;         
	      _injectionResistor = true;
	    }
	  else if (_strBuffer == "unused") 
	    {
		cout << "set injection resistor to shorted" << endl;         
	      _injectionResistor = false;
	    }
	  else 
	    {
	      cout << "syntax error: injectionResistor value must be used or unused only" << endl;
	      exit(1);
	    }
	  
	}
      if (_readUser && _strBuffer=="gainCapacitor0.1pF")
	{
	  if (printlevel >4)	  cout << "gain capacitor 0.1pF setting found" <<endl;
	  _configFile >> _strBuffer;
	  if (_strBuffer == "used")  
	    {
	      cout << "set gain capacitor 0.1pF on" << endl;         
	      _gainCap[3] = true;
	    }
	  else if (_strBuffer == "unused") 
	    {
	      cout << "set gain capacitor 0.1pF off" << endl;         
	      _gainCap[3] = false;
	    }
	  else 
	    {
	      cout << "syntax error: gainCapacitor0.1pF value must be used or unused only" << endl;
	      exit(1);
	    }
	}
      
 	if (_readUser && _strBuffer=="gainCapacitor0.2pF")
	  {
	  if (printlevel >4)	    cout << "gain capacitor 0.2pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set gain capacitor 0.2pF on" << endl;         
		_gainCap[2]=true; 
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set gain capacitor 0.2pF off" << endl;         
		_gainCap[2]=false;
	      }
	    else 
	      {
		cout << "syntax error: gainCapacitor0.2pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }
	
	if (_readUser && _strBuffer=="gainCapacitor0.4pF")
	  {
	  if (printlevel >4)	    cout << "gain capacitor 0.4pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set gain capacitor 0.4pF on" << endl;         
		_gainCap[1]=true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set gain capacitor 0.4pF off" << endl;         
		_gainCap[1]=false;	
	      }
	    else 
	      {
		cout << "syntax error: gainCapacitor0.4pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }
	
 	if (_readUser && _strBuffer=="gainCapacitor0.8pF")
	  {
	  if (printlevel >4)	    cout << "gain capacitor 0.8pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set gain capacitor 0.8pF on" << endl;         
		_gainCap[0]=true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set gain capacitor 0.8pF off" << endl;         
		_gainCap[0]=false;
	      }
	    else 
	      {
		cout << "syntax error: gainCapacitor0.8pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }

 	if (_readUser && _strBuffer=="shapingCapacitor0.3pF")
	  {
	  if (printlevel >4)	    cout << "shaping capacitor 0.3pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set shaping capacitor 0.3pF on" << endl;         
		_shapingCap[3] = true;
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set shaping capacitor 0.3pF off" << endl;         
		_shapingCap[3] = false; 
	      }
	    else 
	      {
		cout << "syntax error: shapingCapacitor0.3pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }
 	if (_readUser && _strBuffer=="shapingCapacitor0.6pF")
	  {
	  if (printlevel >4)	    cout << "shaping capacitor 0.6pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set shaping capacitor 0.6pF on" << endl;         
		_shapingCap[2] = true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set shaping capacitor 0.6pF off" << endl;         
		_shapingCap[2] = false;	
	      }
	    else 
	      {
		cout << "syntax error: shapingCapacitor0.6pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }

 	if (_readUser && _strBuffer=="shapingCapacitor1.2pF")
	  {
	  if (printlevel >4)	    cout << "shaping capacitor 1.2pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set shaping capacitor 1.2pF on" << endl;         
		_shapingCap[1] = true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set shaping capacitor 1.2pF off" << endl;         
		_shapingCap[1] = false;	
	      }
	    else 
	      {
		cout << "syntax error: shapingCapacitor1.2pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }

  	if (_readUser && _strBuffer=="shapingCapacitor2.4pF")
	  {
	  if (printlevel >4)	    cout << "shaping capacitor 2.4pF setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "used")  
	      {
 		cout << "set shaping capacitor 2.4pF on" << endl;         
		_shapingCap[0] = true;	
	      }
	    else if (_strBuffer == "unused") 
	      {
		cout << "set shaping capacitor 2.4pF off" << endl;         
		_shapingCap[0] = false;	
	      }
	    else 
	      {
		cout << "syntax error: shapingCapacitor2.4pF value must be used or unused only" << endl;
		exit(1);
	      }
	  }
	
	// add movable stage steeting
    

	if (_readUser && _strBuffer=="STAGEenable")
	  {
	  if (printlevel >4)	    cout << "STAGE enable setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "on")  
	      {
 		cout << "set STAGE control on" << endl;         
		_STAGEenable = true;
	      }
	    else if (_strBuffer == "off") 
	      {
		cout << "set STAGE off" << endl;         
		_STAGEenable = false;
	      }
	    else 
	      {
		cout << "syntax error: STAGE enable value must be on or off only" << endl;
		exit(1);
	      }
	  }


	if (_readUser && _strBuffer=="STAGEmode")
	  {
	  if (printlevel >4)	    cout << "STAGE mode setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "single")  
	      {
 		cout << "one single STAGE position will be used" << endl;         
		_STAGEuseFile = false;
	      }
	    else if (_strBuffer == "multi") 
	      {
		cout << "STAGE positions will be read from file" << endl;         
		_STAGEuseFile = true;
	      }
	    else 
	      {
		cout << "syntax error: STAGE mode value must be single or multi only" << endl;
		exit(1);
	      }
	  }

	if (_readUser && _strBuffer=="STAGExposition")
	  {
	  if (printlevel >4)	    cout << "STAGE x-position setting found" <<endl;
	    _configFile >> _STAGExposition;
	    cout << "set STAGE x-position to " << _STAGExposition << endl;         
	  }

	if (_readUser && _strBuffer=="STAGEyposition")
	  {
	  if (printlevel >4)	    cout << "STAGE y-position setting found" <<endl;
	    _configFile >> _STAGEyposition;
	    cout << "set STAGE y-position to " << _STAGEyposition << endl;         
	  }

  	if (_readUser && _strBuffer=="STAGEfile")
	  {
	    if (printlevel >4)	    cout << "STAGE file name found" <<endl;
	    _configFile >> _STAGEfile;
	    if (_STAGEuseFile)  cout << "found file "<< _STAGEfile << " with STAGE positions" << endl;         
	    else   cout << "found file "<< _STAGEfile << " with STAGE positions, but will not be used because STAGE-mode is single" << endl; 
	  }

  	if (_readUser && _strBuffer=="Trigger")
	  {
	    if (printlevel >4)	    cout << "Trigger setting found" <<endl;
	    _configFile >> _trigger;
	    cout << "set Trigger to"<< _trigger << endl;         
	  }
	else 
	  {
	    cout << "Trigger set to default value : 24" << endl;
	  }


  	if (_readUser && _strBuffer=="TCalib")
	  {
	  if (printlevel >4)	    cout << "TCalib enable setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "on")  
	      {
 		cout << "set TCalib on" << endl;         
		_Tcalib = true;
	      }
	    else if (_strBuffer == "off") 
	      {
		cout << "set TCalib off" << endl;         
		_Tcalib = false;
	      }
	    else 
	      {
		cout << "syntax error: TCalib value must be on or off only" << endl;
		exit(1);
	      }
	  }

  	if (_readUser && _strBuffer=="VCalib")
	  {
	    if (printlevel >4)	    cout << "Vcalib value setting found" <<endl;
	    _configFile >> _Vcalib;
	    cout << "set Vcalib to " << _Vcalib<< endl;         
	  }

  	if (_readUser && _strBuffer=="calibWidth")
	  {
	  if (printlevel >4)	    cout << "calibWidth value setting found" <<endl;
	    _configFile >> _calibWidth;
	    cout << "set calib width to " << _calibWidth << endl;         
	  }

	
	if (_readUser && _strBuffer=="LEDSel")
	  {
	  if (printlevel >4)	    cout << "LEDSel enable setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "on")  
	      {
 		cout << "set LEDSel on" << endl;         
		_LEDSel = true;
	      }
	    else if (_strBuffer == "off") 
	      {
		cout << "set LEDSel off" << endl;         
		_LEDSel = false;
	      }
	    else 
	      {
		cout << "syntax error: LEDSel value must be on or off only" << endl;
		exit(1);
	      }
	  }



  	if (_readUser && _strBuffer=="holdEnable")
	  {
	  if (printlevel >4)	    cout << "hold enable setting found" <<endl;
	    _configFile >> _strBuffer;
	    if (_strBuffer == "on")  
	      {
 		cout << "set hold on" << endl;         
		_holdEnable = true;
	      }
	    else if (_strBuffer == "off") 
	      {
		cout << "set hold off" << endl;         
		_holdEnable = false;
	      }
	    else 
	      {
		cout << "syntax error: holdEnable value must be on or off only" << endl;
		exit(1);
	      }
	  }

  	if (_readUser && _strBuffer=="holdStart")
	  {

	  if (printlevel >4)	    cout << "holdStart value setting found" <<endl;
	    _configFile >> _holdStart;
	    cout << "set hold start to " << _holdStart << endl;         
	  }



  	if (_readUser && _strBuffer=="holdWidth")
	  {
	  if (printlevel >4)	    cout << "holdWidth value setting found" <<endl;
	    _configFile >> _holdWidth;
	    cout << "set hold width to " << _holdWidth << endl;         
	  }


	if (_readUser && _strBuffer=="analogOutChan")
	  {
	  if (printlevel >4)	    cout << "Analog Out channel choise value setting found" <<endl;
	    _configFile >> _analogOutChan;
	    cout << "set analog out channel to " << _analogOutChan << endl;         
	  }


	_strBuffer  = "";
    }

  _configFile.close();

  
  // reading of STAGEposition file 

  /*
  if (!_STAGEuseFile) 
    {
      if ( (_STAGExposition > 0) && (_STAGExposition < 800) && (_STAGEyposition > 0) && (_STAGEyposition < 800) )  
	{
	  _STAGExArray.push_back(_STAGExposition);
	  _STAGEyArray.push_back(_STAGEyposition);
	}
	  else 
		{
		  cout << "-- range error -- STAGE x-position: "<< _STAGExposition << "  STAGE y-position: "<< _STAGEyposition   <<endl;
		}
    }
  
  
  if (_STAGEuseFile) 
    {
      if (printlevel >4)  cout << "trying to load STAGE positions from " << _STAGEfile <<endl;
      if (_STAGEfile == "") 
	{ 
	  cout << "syntax error: emtpy STAGE file string. In STAGE mode multi you must supply a valid STAGEfile value" << endl;
	  exit(1);
	}

      _stageFile.open(_STAGEfile);

      if (!_stageFile.good() || !_stageFile.is_open()) 
      	{
	  cout << "file error: error while opening "<< _STAGEfile << " please check if file exist and is readable" << endl;	  
	  exit(1);
	}

      unsigned STAGEentries(0);
      unsigned connector;
      int xmovement, ymovement;
      bool dataStart(false);
      while (_stageFile.good())
	{
	  if (!dataStart)
	    {
	      _stageFile >> _strBuffer;
	      
	      if (_strBuffer=="#")
		{
		  _stageFile.getline(_charBuffer,sizeof(_charBuffer));
		  if (printlevel >2) cout << "comment: "<< _charBuffer  << endl;
		}
	      if (_strBuffer=="--data--") dataStart = true;
	      
	    }
	  else
	    {
	      _stageFile >> _rochip >> _rochan >> connector >> _STAGExposition >> _STAGEyposition >> xmovement >> ymovement;
	      if ( (_STAGExposition > 0) && (_STAGExposition < 800) && (_STAGEyposition > 0) && (_STAGEyposition < 800) )  
		{
		  _STAGEchipArray.push_back(_rochip);
		  _STAGEchanArray.push_back(_rochan);
		  _STAGExArray.push_back(xmovement);
		  _STAGEyArray.push_back(ymovement);
		}
	      else 
		{
		  cout << "-- range error -- chip: " << _rochip << "  channel: " << _rochan << "  STAGE x-position: "<< _STAGExposition << "  STAGE y-position: "<< _STAGEyposition   <<endl;
		  exit(1);
		}
	      STAGEentries++;
	      if (printlevel > 4) cout << "  chip: " << _rochip << "  channel: " << _rochan << "  STAGE x-position: "<< _STAGExposition << "  STAGE y-position: "<< _STAGEyposition   <<endl;
	    }
	}
      _stageFile.close();
      cout << "found " << STAGEentries << " STAGE setting entries in file" << endl;
      if (_STAGExArray.size() != _STAGEyArray.size()) 
	{
	  cout << " different number of x and y positions check position file  " << endl;
	  exit(1);
	}
      
    }
  */


  cout << endl << "finished loading settings" << endl <<"**************************************" << endl << endl ;

}

AhcConfigReader::~AhcConfigReader() 
{
}

void AhcConfigReader::insertSettings(AhcVfeConfigurationData* AHCVfe)
{
  AhcVfeShiftRegister sr;
  sr.injectionResistor(_injectionResistor);

  for (int i(0);i<4;i++)
    {
      sr.gainCapacitor(i,_gainCap[i]);
      sr.shapingCapacitor(i,_shapingCap[i]);
    }

  for (int i(0);i<12;i++)
    {
      AHCVfe->shiftRegister(i,sr);
    }

  //  if (_printlevel > 0) 
  cout << "loaded settings from "<< _fileName << " to AhcVfeConfigurationData structure" << endl;
  //AHCVfe->print(cout);
}

void AhcConfigReader::insertSettings(CrcFeConfigurationData* CRCFe)
  //not used in AhcConfiguration.hh due to problems
{
  //CRCFe->calibEnable(_Tcalib);
  //CRCFe->calibWidth(_calibWidth);

  //  CRCFe->dacData(CrcFeConfigurationData::top,_Vcalib);
  // CRCFe->dacData(CrcFeConfigurationData::bot,_Vcalib);
  //CRCFe->dacData(CrcFeConfigurationData::boardB,_Vcalib);

  //CRCFe->holdStart(_holdStart);
  //CRCFe->holdWidth(_holdWidth);

    
  AhcVfeControl c(0);
  c.ledSel(_LEDSel);
  c.swHoldIn(!_holdEnable);
  
  //c.ledSel(CrcFeConfigurationData::top,_LEDSel);
  //c.ledSel(CrcFeConfigurationData::bot,_LEDSel);
  //c.swHoldIn(CrcFeConfigurationData::top,!_holdEnable);
  //c.swHoldIn(CrcFeConfigurationData::bot,!_holdEnable);

  if(!_holdEnable) CRCFe->vfeMplexClockPulses(_analogOutChan);

  CRCFe->vfeControl(c.data());
  
  //  if (_printlevel > 0) 
  cout << "loaded settings from "<< _fileName << " to CrcFeConfigurationData structure" << endl;
  //CRCFe->print(cout);
}

unsigned AhcConfigReader::getHoldStart()
{
  return _holdStart;
}

unsigned AhcConfigReader::getTrigger()
{
  return _trigger;
}

unsigned AhcConfigReader::getAnalogOutChan()
{
  return _analogOutChan;
}

unsigned AhcConfigReader::getLEDSel()
{
  return _LEDSel;
}


unsigned AhcConfigReader::getHoldEnable()
{
  return _holdEnable;
}

void AhcConfigReader::setHoldStart(unsigned changehold)
{
  _holdStart = changehold;
}

unsigned AhcConfigReader::getHoldWidth()
{
  return _holdWidth;
}

unsigned AhcConfigReader::getTcalib()
{
  return _Tcalib;
}

unsigned AhcConfigReader::getCalibWidth()
{
  return _calibWidth;
}

unsigned AhcConfigReader::getVcalib()
{
  return _Vcalib;
}


bool AhcConfigReader::getSTAGEenable()
{
  return _STAGEenable;
}

bool AhcConfigReader::getSTAGEmodemulti()
{
  return _STAGEuseFile;
}

int AhcConfigReader::getSTAGExArray(int i)
{
  return _STAGExArray[i];
}

int AhcConfigReader::getSTAGEyArray(int i)
{
  return _STAGEyArray[i];
}

unsigned AhcConfigReader::getSTAGEArraySize()
{
  return _STAGExArray.size();
}

unsigned AhcConfigReader::getROchip(int i)
{
  return _STAGEchipArray[i];
}

unsigned AhcConfigReader::getROchan(int i)
{
  return _STAGEchanArray[i];
}





#endif
