////////////////////////////////////////////////////////////////////////
// Package: CandFitTrackCam
//
// AlgFitTrackCam.h
//
// marshall@hep.phy.cam.ac.uk
////////////////////////////////////////////////////////////////////////
#ifndef ALGFITTRACKCAM_H
#define ALGFITTRACKCAM_H

#include "Algorithm/AlgBase.h"
#include "CandFitTrackCam/CandFitTrackCamHandle.h"
#include "RecoBase/CandStripHandle.h"
#include "RecoBase/AlgReco.h"
#include "RecoBase/AlgTrack.h"
#include <vector>
#include "Validity/VldContext.h"
#include "DataUtil/PlaneOutline.h"

using std::vector;

class CandTrackHandle;

typedef struct{
  CandStripHandle* csh;
}StripStruct;

typedef struct{
  double TPos;
  double ZPos;
  double PlaneView;
  double TPosError;
}TrkDataStruct;

typedef struct{
  double x_k0;
  double x_k1;
  double x_k2;
  double x_k3;
  double x_k4;
}FiltDataStruct;


class AlgFitTrackCam : public AlgBase, public AlgReco, public AlgTrack
{
  
 public:
  AlgFitTrackCam();
  virtual ~AlgFitTrackCam();

  virtual void RunAlg(AlgConfig &ac, CandHandle &ch, CandContext &cx);

  void InitialFramework(const CandSliceHandle* slice, CandContext &cx);
  void RunTheFitter(CandFitTrackCamHandle &cth);

  void StoreFilteredData(const int NewPlane);
  void FillGapsInTrack();
  bool FindTheStrips(CandFitTrackCamHandle &cth, bool MakeTheTrack);
  void GetFitData(int Plane1, int Plane2);

  void ShowerStrips();
  void RemoveTrkHitsInShw();
  void ShowerSwim();

  void GoBackwards();
  void GoForwards();

  bool GetCombiPropagator(const int Plane, const int NewPlane, const bool GoForward);
  bool Swim(double* StateVector, double* Output, const int Plane, const int NewPlane, const bool GoForward,
	    double* dS=0, double* Range=0, double* dE=0);
  bool Swim(double* StateVector, double* Output, const double zbeg, const int NewPlane, const bool GoForward,
	    double* dS=0, double* Range=0, double* dE=0);
  bool Swim(double* StateVector, double* Output, const int Plane, const double zend, const bool GoForward,
	    double* dS=0, double* Range=0, double* dE=0);

  void GetInitialCovarianceMatrix(const bool FirstIteration);
  void GetNoiseMatrix(const int Plane, const int NewPlane);
  void ExtrapCovMatrix();
  void CalcKalmanGain(const int NewPlane);
  void UpdateStateVector(const int Plane, const int NewPlane, const bool GoForward);
  void UpdateCovMatrix();
  void MoveArrays();
  void CheckValues(double* Input, const int NewPlane);

  void SetTrackProperties(CandFitTrackCamHandle &cth);  
  void SetPropertiesFromFinderTrack(CandFitTrackCamHandle &cth);
  void TimingFit(CandFitTrackCamHandle &cth);
  void SetRangeAnddS(CandFitTrackCamHandle& cth);

  void SpectrometerSwim(CandFitTrackCamHandle &cth);
  void CleanNDLists(CandFitTrackHandle &cth, CandContext &cx);
  bool NDPlaneIsActive(int plane, float u, float v, float projErr);
  void GenerateNDSpectStrips(const CandSliceHandle* slice, CandContext &cx);
  virtual void Trace(const char *c) const;

  void ResetCovarianceMatrix();
  double NDStripBegTime(CandStripHandle* Strip, double U=0, double V=0);

 private:
  vector<StripStruct> SlcStripData[490];
  vector<StripStruct> InitTrkStripData[490];

  vector<TrkDataStruct> TrkStripData[490];

  vector<FiltDataStruct> FilteredData[490];

  Int_t nbfield;
  Double_t bave;
  Bool_t EndofRange;
  Int_t EndofRangePlane;
  Bool_t LastIteration;
  double x_k4_biased;
  double eqp_biased;
  int UseGeoSwimmer;
  double x_k[5];
  double x_k_minus[5];
  double C_k[5][5];
  double C_k_minus[5][5];
  double C_k_intermediate[5][5];
  double F_k[5][5];
  double F_k_minus[5][5];
  double Q_k[5][5];
  double Q_k_minus[5][5];
  double K_k[5];

  int H_k[5];
  int Identity[5][5];

  double VtxCov[5];
  double EndCov[5];

  int MaxPlane;
  int MinPlane;

  double DeltaZ;
  double DeltaPlane;
  
  VldContext* vldc;
  const CandTrackHandle* track;

  bool debug;

  bool ZIncreasesWithTime;
  bool PassTrack;

  bool SaveData;
  bool SwimThroughShower;

  int ShowerEntryPlane;
  
  int NIter;
  int TotalNSwimFail;

  int NumFinderStrips;
  double MeanTrackTime;
  PlaneOutline fPL;

  double StripListTime;

  ClassDef(AlgFitTrackCam,2)   // FitTrackCam Algorithm Class
};
    
#endif   // ALGFITTRACKCAM_H 
