/**
 * \file ExtTrack.h
 * \author Elena Vannuccini
 */
#ifndef exttrack_h
#define exttrack_h

#include <TrkLevel2.h>
#include <TrkParams.h>


/**
 * \brief Struct to pass mini2 track parameters to F77 routines
 */
#define NPLANEMAX 56

struct cMiniExtTrack {
    double al[5];
    double xm[NPLANEMAX],ym[NPLANEMAX],zm[NPLANEMAX];
    double xm_a[NPLANEMAX],ym_a[NPLANEMAX],zm_a[NPLANEMAX];
    double xm_b[NPLANEMAX],ym_b[NPLANEMAX],zm_b[NPLANEMAX];
    double resx[NPLANEMAX],resy[NPLANEMAX];
    double tailx[NPLANEMAX],taily[NPLANEMAX];
    double xgood[NPLANEMAX],ygood[NPLANEMAX];
    double dedxtrk_x[NPLANEMAX];
    double dedxtrk_y[NPLANEMAX];
    double zini;
    double pfixed;
    double chi2;
    double xv[NPLANEMAX],yv[NPLANEMAX],zv[NPLANEMAX];
    double axv[NPLANEMAX],ayv[NPLANEMAX];
    double cov[5][5];
    double fact;
    int nstep;
    int idcand;
    int trackmode;
    int istepmin;
    int nplanes;

};

extern "C" {

  extern struct cMiniExtTrack exttrack_; 
  void miniext_(int*,int*,int*); 
  void guessext_(); 

}


class ExtTrack : public TObject {

private:

public:


  float zini;
  float al[5];           ///<TRACK STATE VECTOR 
  float coval[5][5];     ///<covariance matrix 
  float chi2;          
  int  nstep;           
  int nplanes;
  int*   xgood ;        //[nplanes]       
  int*   ygood ;        //[nplanes]        
  int*   multmaxx;     //[nplanes]  
  int*   multmaxy;     //[nplanes]  
  float* xm ;           //[nplanes]
  float* ym ;           //[nplanes]
  float* zm ;           //[nplanes]
  float* xma ;           //[nplanes]
  float* yma ;           //[nplanes]
  float* zma ;           //[nplanes]
  float* xmb ;           //[nplanes]
  float* ymb ;           //[nplanes]
  float* zmb ;           //[nplanes]
  float* resx ;         //[nplanes]
  float* resy ;         //[nplanes]
  float* xv ;           //[nplanes]
  float* yv ;           //[nplanes]
  float* zv ;           //[nplanes]
  float* axv ;          //[nplanes]
  float* ayv ;          //[nplanes]
  float* dedx_x ;       //[nplanes]
  float* dedx_y ;       //[nplanes]

  float xGF[14];         ///<calculated x coordinates on GF reference planes
  float yGF[14];         ///<calculated y coordinates on GF reference planes

  ExtTrack(int dim=0);

  ExtTrack( TrkTrack& t){SetDimension(6);  Set(t); }
  ExtTrack( const ExtTrack& );

  ~ExtTrack(){ Delete(); };

  void SetDimension(int dim);    ///< Allocate vectors
  void Clear(Option_t* option=""); ///< Deallocate vectors
  void Delete();        ///< Deallocate vectors

  void Copy(ExtTrack&);


  void SetMiniDefault();        ///< Set tracking alg. parameters (static)
  void SetZ0(float zin){zini = zin; } ///< Set z-coord of reference plane


  void Set( TrkTrack& t, int index);          ///< Set from TrkTrack object
  void Set( TrkTrack& t){ Set(t,0);};          ///< Set from TrkTrack object
  void FillMiniStruct(cMiniExtTrack& track);
  void SetFromMiniStruct(cMiniExtTrack *track);
  void FillMiniStruct(){FillMiniStruct(exttrack_); };
  void SetFromMiniStruct(){SetFromMiniStruct(&exttrack_);};


  bool SetZ(int ip,float zmeas);
  bool SetXY(int ip,float xmeas, float ymeas, float rx, float ry); 
  bool SetX(int ip,float xa, float xb, float ya, float yb, float res); 
  bool SetY(int ip,float xa, float xb, float ya, float yb, float res); 
  bool ResetXY(int ip);

  bool SetXGood(int ip,int icl_piu_uno=1, int il=-1, int is=-1 ); ///< same notation as TrkTrack
  bool SetYGood(int ip,int icl_piu_uno=1, int il=-1, int is=-1 );///< same notation as TrkTrack

  void ResetFit();                       ///<Reset fit variables
  void ResetXY();                        ///<Reset all measured-position variables
  void Reset(){ ResetFit(); ResetXY(); } ///<Reset all variables



  void Dump();


  void Fit(double pfixed, int& fail, int iprint);

  Bool_t XGood(int ip){ return GetClusterX_ID(ip)!=-1; };
  Bool_t YGood(int ip){ return GetClusterY_ID(ip)!=-1; };
  int GetClusterX_ID(int ip);
  int GetClusterY_ID(int ip);
  int GetLadder(int ip);
  int GetSensor(int ip);

  int GetNX(){int n=0; for(int i=0; i<nplanes; i++)n+=(int)(XGood(i)); return n;}; 
  int GetNY(){int n=0; for(int i=0; i<nplanes; i++)n+=(int)(YGood(i)); return n;};
  int GetNXY(){int n=0; for(int i=0; i<nplanes; i++)n+=(int)(YGood(i)&&XGood(i)); return n;};
  int GetNtot(){return GetNX()+GetNY();};
  int GetNhit(){int n=0; for(int i=0; i<nplanes; i++)n+=(int)(YGood(i)||XGood(i)); return n;};

  Float_t GetDEDX();
  Float_t GetDEDX(int ip);
  Float_t GetDEDX(int ip,int iv);

  Float_t GetDEDXX(bool cutSat=false);
  Float_t GetDEDXY(bool cutSat=false);


  Int_t GetClusterX_Multiplicity(int ip);
  Int_t GetClusterY_Multiplicity(int ip);
  Int_t GetClusterX_MaxStrip(int ip);
  Int_t GetClusterY_MaxStrip(int ip);

  Float_t GetRigidity();
  Float_t GetDeflection();
  Float_t GetMDR(){return (coval[4][4]>0 ? 1./sqrt(coval[4][4]) : 0.); };

  Bool_t IsSaturated(int,int);
  Bool_t IsSaturated(int);
  Bool_t IsSaturated();
  Bool_t IsBad(int,int); 
  Int_t GetLeverArmXY();
  Int_t GetLeverArmX();
  Int_t GetLeverArmY();
  Float_t GetChi2X(); //EM
  Float_t GetChi2Y(); //EM
/*     Bool_t IsInsideCavity(float); */
/*     Bool_t IsInsideCavity(){ return IsInsideCavity(0.); } */
  Bool_t IsInsideAcceptance(float); // EM
  Bool_t IsInsideAcceptance(){ return IsInsideAcceptance(0.); } //EM
/*     Bool_t IsInsideGFSurface(const char*,float); */
/*     Bool_t IsInsideGFSurface(const char* surf){ return IsInsideGFSurface(surf,0.); } */
/*     Bool_t BadClusterX(int ip){ return IsBad(ip,0); } */
/*     Bool_t BadClusterY(int ip){ return IsBad(ip,1); } */
/*     Bool_t SaturatedClusterX(int ip){ return IsSaturated(ip,0); } */
/*     Bool_t SaturatedClusterY(int ip){ return IsSaturated(ip,1); } */
  



  ClassDef(ExtTrack,3);

};

#endif
