//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//*
//             LOW ENERGY MUON SPIN RELAXATION, ROTATION, RADIATION 
//
//  ID    : LEMuSRPgaMessenger.cc , v 1.1
//  AUTHOR: Taofiq PARAISO
//  DATE  : 2004-06-30 09:12
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
//
//  &           &&&&&&&&&&                            &&&&&&&         &&&&&&&&
//  &           &                                   &&      &&       &       &&
//  &           &                   &      &       &                &       &&
//  &           &&&&&&&            &      &         &&&&&&         &&&&&&&&  
//  &           &                 &      &&                &      &      &&
//  &           &                &&     &  &     &&      &&      &        &
//  &&&&&&&&&&  &&&&&&&&&&      &  &&&&&    &&    &&&&&&&       &        &&   
//                             &
//                            &
//                           &
//                         &  
//                          PRIMARY GENERATOR ACTION MEESENGER
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//


#include "LEMuSRPgaMessenger.hh"


#include "LEMuSRPrimaryGeneratorAction.hh"
#include "G4UIdirectory.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithADouble.hh"
#include "G4UIcmdWith3Vector.hh"
#include "G4UIcmdWith3VectorAndUnit.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4ios.hh"
#include "G4UnitsTable.hh"
#include "G4ParticleTable.hh"

/*!
 * The commands are instanciated and a new pointer is created for each of them.
 * A directory and name for the commands is also defined, as well as some guidance to the user about how to use the command.
 * Finally if possible some default values are defined.
*/
LEMuSRPgaMessenger::LEMuSRPgaMessenger(LEMuSRPrimaryGeneratorAction *thePGA)
:lemuPGA(thePGA)
{
  pgaDirectory = new G4UIdirectory("/lemuGun/");
  pgaDirectory->SetGuidance("LEMuSR particle shooting control commands.");

  // commands 

  posCmd = new G4UIcmdWith3Vector("/lemuGun/gunPosition",this);
  posCmd->SetGuidance("Set Gun Position >> IN CENTIMETERS.");
  posCmd->SetParameterName("X [cm]","Y [cm]","Z [cm]",true,true); 
  posCmd->SetDefaultValue(Hep3Vector(0., 0., -114));

  posCmd = new G4UIcmdWith3Vector("/lemuGun/MomentumDirection",this);
  posCmd->SetGuidance("Set momentum direction >> sum must equal one.");
  posCmd->SetParameterName("momX ","momY ","momZ ",true,true); 
  posCmd->SetDefaultValue(Hep3Vector(0., 0., 1.));


  scaCmd = new G4UIcmdWith3Vector("/lemuGun/scan/square",this);
  scaCmd->SetGuidance("Gun scan: xrange yrange nbins \n Shoot right number of particles to fill. \n xrange and yrange are divided in nbins.\n");
  scaCmd->SetParameterName("X range [cm]","Y range [cm]","Number of bins",true,true); 
  scaCmd->SetDefaultValue(Hep3Vector(2., 2., 400));

  scbCmd = new G4UIcmdWith3Vector("/lemuGun/scan/circular",this);
  scbCmd->SetGuidance("Gun scan: radius Rsteps ThetaSteps \n Shoot Rsteps*Thetasteps particles to fill.");
  scbCmd->SetParameterName("Radius [cm]","Number of step along radius","Number of steps along angle",true,true); 
  scbCmd->SetDefaultValue(Hep3Vector(1., 36 , 360 ));

  scgCmd = new G4UIcmdWith3Vector("/lemuGun/scan/gauss",this);
  scgCmd->SetGuidance("Gun gauss scan:.");
  scgCmd->SetParameterName("Radius [cm]","Number of step along radius","Number of steps along angle",true,true); 
  scgCmd->SetDefaultValue(Hep3Vector(1., 36 , 360 ));



  reset = new G4UIcmdWithoutParameter("/lemuGun/scan/reset",this);
  reset->SetGuidance("\n  Reset the counters for scanning");

  setEnergy = new G4UIcmdWithADouble("/lemuGun/energy/defined",this);
  setEnergy->SetGuidance("\n  Energy Value >> IN keV \n ");
  setEnergy->SetParameterName("Energy in [keV]",false);
  setEnergy->SetDefaultValue(20);
  setEnergy->AvailableForStates(G4State_PreInit,G4State_Idle); 

  setKEoffset = new G4UIcmdWithADouble("/lemuGun/energy/offset",this); // not implemented yet
  setKEoffset->SetGuidance("\n  KEoffset Value >> IN keV \n ");
  setKEoffset->SetParameterName("KEoffset in [keV]; default value 3.73",false);
  setKEoffset->SetDefaultValue(0);
  setKEoffset->AvailableForStates(G4State_PreInit,G4State_Idle); 



  setRndEnergy =  new G4UIcmdWithAString("/lemuGun/energy/random",this);
  setRndEnergy->SetGuidance("Gaussian energy distribution with default mean 20 kev and 0.5 kev deviation");
  setRndEnergy->SetParameterName("Random Energy: on/off",true);
  setRndEnergy->SetDefaultValue("on");


  setMuonium =  new G4UIcmdWithAString("/lemuGun/particle",this);
  setMuonium->SetGuidance("Particles to be shot");
  setMuonium->SetParameterName("Particle types: mu+/Mu or other.",true);
  setMuonium->SetDefaultValue("mu+");


  setEGauss = new G4UIcmdWith3Vector("/lemuGun/energy/gauss",this);
  setEGauss->SetGuidance("Gaussian energy distribution with specified mean and standard deviation\n ENTER VALUES >> IN keV ");
  setEGauss->SetParameterName("Mean Energy","Standard Deviation","",true,true); 
  setEGauss->SetDefaultValue(Hep3Vector(20., 0.5, 0.0));

}

/*!
* Kills the implemented pointers.
*/
LEMuSRPgaMessenger::~LEMuSRPgaMessenger()
{
  delete posCmd;
  delete momCmd;
  delete scaCmd;
  delete scgCmd;
  delete scbCmd;
  delete reset;
  delete setEnergy;
  delete setRndEnergy;
  delete setMuonium;
  delete setKEoffset;
  delete setEGauss;
  delete pgaDirectory;
}


/*!
 * This method registers all the operation to take when a command is 
 * entered in the terminal. Typically, the command is read and according to its name, is identified to a command defined in the constructor.
 * Then the user value is read by the GetNewValue type methods. It can be a string, a double, a vector etc.
 *
 * What to do with this new value(s) is then implemented.
*/
void LEMuSRPgaMessenger::SetNewValue(G4UIcommand * command,G4String newValues)
{
  
  if( command==posCmd )
    {
      lemuPGA->scan=0;
      lemuPGA->X=posCmd->GetNew3VectorValue(newValues).x();
      lemuPGA->Y=posCmd->GetNew3VectorValue(newValues).y();
      lemuPGA->Z=posCmd->GetNew3VectorValue(newValues).z();
     }
  else if( command==momCmd )
    {
      //      lemuPGA->scan=0;
      lemuPGA->momX=momCmd->GetNew3VectorValue(newValues).x();
      lemuPGA->momY=momCmd->GetNew3VectorValue(newValues).y();
      lemuPGA->momZ=momCmd->GetNew3VectorValue(newValues).z();
     }
  else if( command==scaCmd)
    {
      lemuPGA->scan=1;
      G4int xb, yb;
      lemuPGA->m_xrange=scaCmd->GetNew3VectorValue(newValues).x();
      lemuPGA->m_yrange=scaCmd->GetNew3VectorValue(newValues).y();

            xb=(G4int)(scaCmd->GetNew3VectorValue(newValues).z()/(2*scaCmd->GetNew3VectorValue(newValues).x())); 
            yb=(G4int)(scaCmd->GetNew3VectorValue(newValues).z()/(2*scaCmd->GetNew3VectorValue(newValues).y()));

      //    xb=(G4int)(scaCmd->GetNew3VectorValue(newValues).z()); 
      //    yb=(G4int)(scaCmd->GetNew3VectorValue(newValues).z());
      lemuPGA->m_nbxsteps=xb;
      lemuPGA->m_nbysteps=yb;

      
      lemuPGA->m_counterx = 0;
      lemuPGA->m_countery = 0;
 
      G4cout<<"Scan will make " << lemuPGA->m_nbxsteps << " steps along x and " <<lemuPGA->m_nbysteps <<" steps along y.\n sHooT :: " << xb*yb <<" particles to fill.\n ";
      
    }
  
  else if( command==scbCmd) 
    {
      lemuPGA->scan=2;
      lemuPGA->m_xrange=scbCmd->GetNew3VectorValue(newValues).x();
      lemuPGA->m_nbxsteps=(G4int)scbCmd->GetNew3VectorValue(newValues).y();
      lemuPGA->m_nbysteps=(G4int)scbCmd->GetNew3VectorValue(newValues).z();
      
      lemuPGA->m_counterx = 0;
      lemuPGA->m_countery = 0;
      
    }
  
  else if( command==scgCmd) 
    {
      lemuPGA->scan=3;
      lemuPGA->m_xrange=scgCmd->GetNew3VectorValue(newValues).x();
      lemuPGA->sc_mean =scgCmd->GetNew3VectorValue(newValues).y();
      lemuPGA->sc_stddev=scgCmd->GetNew3VectorValue(newValues).z();
      
      lemuPGA->m_counterx = 0;
      lemuPGA->m_countery = 0;
       G4cout<<"Scan will make 40 steps along radius and 180 steps along angle.\n sHooT :: 3600  particles to fill.\n "; 
    }
  else if( command==reset) 
    {
      lemuPGA->m_counterx = 0;
      lemuPGA->m_countery = 0;    
    }

  
  else if( command==setMuonium) 
    {
      G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
      
      if(particleTable->FindParticle(newValues))
	{
	  lemuPGA->pname=newValues;
	}
      else
	{
	  lemuPGA->pname="mu+";
	  G4cout<<"Particle " << newValues<<" not found ==>> will shoot mu+. "<<G4endl;
	};
      
    }
  else if( command==setKEoffset)
    {
      lemuPGA->ke_offset=setKEoffset->GetNewDoubleValue(newValues)*keV;
    }
  
  else if(command == setEnergy)
    {
      lemuPGA->rnd=false;
      G4double k=setEnergy->GetNewDoubleValue(newValues);
      lemuPGA->energy=k*keV;
    }
  else if(command == setRndEnergy)
    {
      lemuPGA->rnd=true;
    }
  else  if( command==setEGauss )
    {
      lemuPGA->gauss=1;
      lemuPGA->mean  = setEGauss->GetNew3VectorValue(newValues).x();
      lemuPGA->stddev= setEGauss->GetNew3VectorValue(newValues).y();
     }
      


}

