#ifndef DetectorConstruction_H
#define DetectorConstruction_H 1

class G4LogicalVolume;
class G4VPhysicalVolume;
class G4Material;
class SensitiveDetector;
class G4VPVParameterisation;

#include "G4VUserDetectorConstruction.hh"

// Mandatory user class that defines the detector used in the
// simulation, its geometry and its materials.
// Derived from the G4VUserDetectorConstruction initialisation 
// abstract base class.

class DetectorConstruction : public G4VUserDetectorConstruction
{
	public:
		DetectorConstruction();		// Constructor
		~DetectorConstruction();	// Destructor

	private:
        // Method to construct the detector
        G4VPhysicalVolume* Construct();
        // Method to construct the sensitive detector
        void ConstructSDandField();
        // Method to define the materials
        void DefineMaterials();
        // Method to read the values of parameters from file
        void DefineParameters();

	public:
		// Get methods
		// Method to get the world physical volume
        const G4VPhysicalVolume* GetWorld()     {return experimentalHall_phys;};

	    // Method to get the world dimensions
		G4double GetWorldSide()               	{return worldSide;};

		// Method to get the Scint physical volume
	    const G4VPhysicalVolume* GetScint()  	{return scint_phys;};

	    // Methods to get the scintillator bar dimensions
		G4double GetScintX()          		    {return scint_x;};
		G4double GetScintY()          		    {return scint_y;};
		G4double GetScintZ()          		    {return scint_z;};
    
        G4double GetScintGap()                  {return scint_gap;};

		// Methods to get the geometrical parameters
		G4int GetNumberOfBars()		            {return n_side;};
		G4int GetNumberOfSlicesPerBar()		    {return NbOfSlicesPerBar;};
        G4int GetNumberOfMaskElementsPerSide()  {return n_mask_elem_side;};

        // Methods to get the side collimator dimensions
        G4double GetCollSideThick()          	{return coll_side_thick;};
        G4double GetCollSideHeight()          	{return coll_side_height;};
    
        // Methods to get the SDD dimensions
        G4double GetSDDThick()          		{return sdd_thick;};

        // Methods to get the bus dimensions
        G4double GetBusThick()                  {return bus_thick;};
        G4double GetBusHeight()                 {return bus_height;};
        G4double GetBusSide()                   {return bus_side;};

        // Methods to get the optical coupler dimensions
        G4double GetOptCouplerThick()           {return optCoupler_thick;};

        // Methods to get the mask dimensions
        G4double GetMaskSideX()                 {return mask_side_x;};
        G4double GetMaskSideY()                 {return mask_side_y;};
        G4double GetMaskThick()                 {return mask_thick;};
        G4double GetMaskFocalDistance()         {return mask_focalDistance;};

        // Methods to get the upper collimator dimensions
        G4double GetCollUpper1Thick()           {return coll_upper1_thick;};
        G4double GetCollUpper2Thick()           {return coll_upper2_thick;};
        G4double GetCollUpper2Height()          {return coll_upper2_height;};

        // Methods to get the polypropylene dimensions
        G4double GetPolypropThick()           {return poly_thick;};

        // Methods to get the MLI dimensions
        G4double GetKapThick()              {return kap_thick;};
        G4double GetAlumThick()             {return al_thick;};

        // Methods to get the materials
        G4Material* GetScintMaterial()        	{return scintMaterial;};
        G4Material* GetCollSideMaterial()       {return collSideMaterial;};
        G4Material* GetSDDMaterial()        	{return sddMaterial;};
        G4Material* GetBusMaterial()        	{return busMaterial;};
        G4Material* GetMaskMaterial()        	{return maskMaterial;};
        G4Material* GetOptCouplerMaterial()     {return optCouplerMaterial;};
        G4Material* GetPolyMaterial()           {return polypropMaterial;};
        G4Material* GetKapMaterial()            {return kapMaterial;};
        G4Material* GetAlumMaterial()           {return alumMaterial;};
        
		// Set methods
		// Method to set the world dimensions
		void SetWorldSide(G4double wside)		    {worldSide = wside;};

		// Methods to set the scintillator bar dimensions
		void SetScintX(G4double scintsidex)		{scint_x = scintsidex;};
		void SetScintY(G4double scintsidey)		{scint_y = scintsidey;};
		void SetScintZ(G4double scintsidez)		{scint_z = scintsidez;};
		
        void SetScintGap(G4double scintgap)        {scint_gap = scintgap;};

		// Methods to set the geometrical parameters
		void SetNumberOfBars(G4int nb)		    {n_side = nb;};
		void SetNumberOfSlicesPerBar(G4int nb)	{NbOfSlicesPerBar = nb;};
        void SetNumberOfMaskElementsPerSide(G4int nb)    {n_mask_elem_side = nb;};

        // Methods to set the side collimator dimensions
        void SetCollSideThick(G4double ct)      {coll_side_thick = ct;};
        void SetCollSideHeight(G4double ch)     {coll_side_height = ch;};
    
        // Methods to set the mask dimensions
        void SetMaskSideX(G4double msx)             {mask_side_x = msx;};
        void SetMaskSideY(G4double msy)             {mask_side_y = msy;};
        void SetMaskThick(G4double mt)              {mask_thick = mt;};
        void SetMaskFocalDistance(G4double mfd)     {mask_focalDistance = mfd;};

        // Methods to set the upper collimator dimensions
        void SetCollUpper1Thick(G4double ct1)      {coll_upper1_thick = ct1;};
        void SetCollUpper2Thick(G4double ct2)      {coll_upper2_thick = ct2;};
        void SetCollUpper2Height(G4double ch2)      {coll_upper2_height = ch2;};

        // Methods to set the SDD dimensions
        void SetSDDThick(G4double sddt)     {sdd_thick = sddt;};

        // Methods to set the bus dimensions
        void SetBusThick(G4double bt)     {bus_thick = bt;};
        void SetBusHeight(G4double bh)     {bus_height = bh;};
        void SetBusSide(G4double bs)     {bus_side = bs;};

        // Methods to set the optical coupler dimensions
        void SetOptCouplerThick(G4double opt)     {optCoupler_thick = opt;};

        // Methods to set the polypropylene dimensions
        void SetPolypropThick(G4double poly)      {poly_thick = poly;};

        // Methods to set the MLI dimensions
        void SetKapThick(G4double kap)      {kap_thick = kap;};
        void SetAlumThick(G4double alum)      {al_thick = alum;};

		// Methods to set the materials
		void SetScintMaterial                   (G4String);
        void SetCollSideMaterial                (G4String);
        void SetBusMaterial                     (G4String);
        void SetSDDMaterial                     (G4String);
        void SetMaskMaterial                    (G4String);
        void SetCollUpper1Material              (G4String);
        void SetCollUpper2Material              (G4String);
        void SetOptCouplerMaterial              (G4String);
        void SetPolyMaterial                    (G4String);
        void SetKapMaterial                     (G4String);
        void SetAlumMaterial                    (G4String);

	    // Print a list of parameters
		void PrintParameters();
	
		// Geometry update
		void UpdateGeometry();


	private:
		// Logical volumes
		G4LogicalVolume* experimentalHall_log;
		G4LogicalVolume* scint_log;
        G4LogicalVolume* sddUpper_log;
        G4LogicalVolume* sddLower_log;
        G4LogicalVolume* optCoupler_log;
        G4LogicalVolume* coll_sideXp_log;
        G4LogicalVolume* coll_sideXm_log;
        G4LogicalVolume* coll_sideYp_log;
        G4LogicalVolume* coll_sideYm_log;
        G4LogicalVolume* bus1_log;
        G4LogicalVolume* bus2_log;
        G4LogicalVolume* mask_log;
        G4LogicalVolume* coll_upper1Xp_log;
        G4LogicalVolume* coll_upper1Xm_log;
        G4LogicalVolume* coll_upper1Yp_log;
        G4LogicalVolume* coll_upper1Ym_log;
        G4LogicalVolume* coll_upper2Xp_log;
        G4LogicalVolume* coll_upper2Xm_log;
        G4LogicalVolume* coll_upper2Yp_log;
        G4LogicalVolume* coll_upper2Ym_log;
        G4LogicalVolume* polyprop_log;
        G4LogicalVolume* kapton_log;
        G4LogicalVolume* aluminum_log;
        G4LogicalVolume* pcb_log;

        // Parameterisations
		G4VPVParameterisation* scintParam;
        G4VPVParameterisation* maskParam;
        G4VPVParameterisation* pcbParam;

		// Physical volumes
		G4VPhysicalVolume* experimentalHall_phys;
		G4VPhysicalVolume* scint_phys;
        G4VPhysicalVolume* sddUpper_phys;
        G4VPhysicalVolume* sddLower_phys;
        G4VPhysicalVolume* optCoupler_phys;
        G4VPhysicalVolume* coll_sideXp_phys;
        G4VPhysicalVolume* coll_sideXm_phys;
        G4VPhysicalVolume* coll_sideYp_phys;
        G4VPhysicalVolume* coll_sideYm_phys;
        G4VPhysicalVolume* bus1_phys;
        G4VPhysicalVolume* bus2_phys;
        G4VPhysicalVolume* mask_phys;
        G4VPhysicalVolume* coll_upper1Xp_phys;
        G4VPhysicalVolume* coll_upper1Xm_phys;
        G4VPhysicalVolume* coll_upper1Yp_phys;
        G4VPhysicalVolume* coll_upper1Ym_phys;
        G4VPhysicalVolume* coll_upper2Xp_phys;
        G4VPhysicalVolume* coll_upper2Xm_phys;
        G4VPhysicalVolume* coll_upper2Yp_phys;
        G4VPhysicalVolume* coll_upper2Ym_phys;
        G4VPhysicalVolume* polyprop_phys;
        G4VPhysicalVolume* kapton_phys;
        G4VPhysicalVolume* aluminum_phys;
        G4VPhysicalVolume* pcb_phys;


		// World dimensions
		G4double worldSide;

		// Scint dimensions 
		G4double scint_x;
		G4double scint_y;
		G4double scint_z;
    
        G4double scint_gap;
		
		// Geometrical parameters
        G4int n_side;
        G4int NbOfSlicesPerBar;
        G4int n_mask_elem_side;
    
        // Side Collimator dimensions
        G4double coll_side_thick;
        G4double coll_side_height;

        // SDD dimensions
        G4double sdd_thick;
    
        // Optical coupler dimensions
        G4double optCoupler_thick;
    
        // Bottom bus thickness
        G4double bus_thick;
        G4double bus_height;
        G4double bus_side;
    
        // Mask dimensions
        G4double mask_side_x;
        G4double mask_side_y;
        G4double mask_thick;
        G4double mask_focalDistance;

        // Upper Collimator dimensions
        G4double coll_upper1_thick;
        G4double coll_upper2_thick;
        G4double coll_upper2_height;

        // Polypropylene layer dimensions
        G4double poly_thick;

        // MLI layer dimensions
        G4double kap_thick;
        G4double al_thick;

        // Materials
		G4Material* defaultMaterial;
        G4Material*	sddMaterial;
		G4Material*	scintMaterial;
        G4Material*	collSideMaterial;
        G4Material*	busMaterial;
        G4Material*	maskMaterial;
        G4Material*	collUpper1Material;
        G4Material* collUpper2Material;
        G4Material*	optCouplerMaterial;
        G4Material* polypropMaterial;
        G4Material* kapMaterial;
        G4Material* alumMaterial;
        G4Material* fr4Material;


};

#endif

