#ifndef HMDCSTOREEVENTS_H
#define HMDCSTOREEVENTS_H
#include "TObject.h"
#include "hgeomvector.h"
#include "hseqarr.h"
class HMdcEvntListCells;
class HMdcClus;
class HMdcStoreWires : public TObject {
  protected:
    HSeqArr      nDTPerEvent; 
    HSeqArrIter* iterEvents;  
    HSeqArr      mdcWireAddr; 
    HSeqArrIter* iterWires;   
    
    UInt_t       maxMemSize;  
    
    UInt_t       nEvents;     
    UShort_t     nDrTimes;    
    
    UShort_t     nDrTmPerEv;  
    UInt_t       nRdEvents;   
    UShort_t     nRdDrTimes;  
  public:
    HMdcStoreWires(void);
    ~HMdcStoreWires(void);
    void setMaxMemSize(UInt_t mSize); 
    virtual UInt_t getMemSize(void) const;
    Bool_t testMemSize(void) const;
    
    
    void addWireAddr(Int_t s, Int_t m, Int_t l, Int_t c);
    void setEndEvent(void);
    
    
    virtual void resetIter(void);
    Bool_t getNextEvent(void);
    Bool_t getNextWireAddr(Int_t& s, Int_t& m, Int_t& l, Int_t& c);
    inline static UShort_t packAddress(Int_t s, Int_t m, Int_t l, Int_t c);
    inline static void unpackAddress(UShort_t& addr, Int_t& s, Int_t& m, 
        Int_t& l, Int_t& c);
    
    
    void addEvent(const HMdcEvntListCells& event);
    Bool_t getNextEvent(HMdcEvntListCells& event);
  protected:
    
  ClassDef(HMdcStoreWires,0)
};
inline UShort_t HMdcStoreWires::packAddress(Int_t s,Int_t m,Int_t l,Int_t c) {
  return UShort_t((( ((s&7)<<5) + ((m&3)<<3) + (l&7) ) <<8) + (c&255));
}
inline void HMdcStoreWires::unpackAddress(UShort_t& addr, Int_t& s, 
    Int_t& m, Int_t& l, Int_t& c) {
  s=(Int_t)((addr>>13)&7);  
  m=(Int_t)((addr>>11)&3);  
  l=(Int_t)((addr>>8)&7);
  c=(Int_t)(addr&255);
}
class HMdcStoreEvents : public TObject {
  protected:
    HSeqArr      nDTPerEvent; 
    HSeqArrIter* iterEvents;  
    HSeqArr      mdcCells;    
    HSeqArrIter* iterWires;   
    
    UInt_t       maxMemSize;  
    
    UInt_t       nEvents;     
    UShort_t     nDrTimes;    
    
    UShort_t     nDrTmPerEv;  
    UInt_t       nRdEvents;   
    UShort_t     nRdDrTimes;  
  public:
    HMdcStoreEvents(void);
    ~HMdcStoreEvents(void);
    void setMaxMemSize(UInt_t mSize); 
    virtual UInt_t getMemSize(void) const;
    Bool_t testMemSize(void) const;
    
    
    void addWire(Int_t s,Int_t m,Int_t l,Int_t c,Float_t tm, Bool_t flag=kTRUE);
    void setEndEvent(void);
    
    
    virtual void resetIter(void);
    Bool_t getNextEvent(void);
    Bool_t getNextCell(Int_t& s, Int_t& m, Int_t& l, Int_t& c, Float_t& tm);
    Bool_t getNextCell(Int_t& s, Int_t& m, Int_t& l, Int_t& c, Float_t& tm,
        Bool_t& flag);
    Bool_t getNextCell(Int_t& s, Int_t& m, Int_t& l, Int_t& c, Float_t& tm,
        Bool_t& flag,UInt_t** addr);
    inline static UInt_t packCell(Int_t s, Int_t m, Int_t l, Int_t c, 
        Float_t tm, Bool_t flag=kTRUE);
    inline static Bool_t unpackCell(UInt_t& addr, Int_t& s, Int_t& m, 
        Int_t& l, Int_t& c, Float_t& tm);
    static void unsetFlag(UInt_t& addr) {addr &= 0xFFFEFFFF;}
    static void setFlag(UInt_t& addr)   {addr |=    0x10000;} 
    
    
    void   addEvent(const HMdcEvntListCells& event);
    Bool_t getNextEvent(HMdcEvntListCells& event,Bool_t checkFlag=kFALSE);
  protected:
    
  ClassDef(HMdcStoreEvents,0)
};
inline UInt_t HMdcStoreEvents::packCell(Int_t s,Int_t m,Int_t l,Int_t c,
    Float_t tm,Bool_t flag) {
  UInt_t sign = tm>0 ? 0 : 0x4000;       
  if(sign) tm = -tm;
  UInt_t dt   = UInt_t(tm*10. + 0.5);
  if(dt > 0x3FFF) dt=0x3FFF;
  dt = (dt|sign)<<17;
  if(flag) setFlag(dt);
  return UInt_t((( ((s&7)<<5) + ((m&3)<<3) + (l&7) ) <<8) + (c&0xFF)) +dt;
}
inline Bool_t HMdcStoreEvents::unpackCell(UInt_t& addr, Int_t& s, 
    Int_t& m, Int_t& l, Int_t& c, Float_t& tm) {
  
  s  = (Int_t)((addr>>13)&7);               
  m  = (Int_t)((addr>>11)&3);               
  l  = (Int_t)((addr>>8)&7);
  c  = (Int_t)(addr&0xFF);
  tm = ((addr>>17)&0x3FFF)*0.1;
  if(addr&0x80000000) tm = -tm;             
  return (addr&0x10000) > 0;                
}
class HMdcStoreTracks : public TObject {
  protected:
    HSeqArr      address;      
                               
                               
    HSeqArr      trackPos;     
    HSeqArr      nTracksEvent; 
    HSeqArrIter* iterAddress;  
    HSeqArrIter* iterTrackPos; 
    HSeqArrIter* iterNTrckEv;  
    UChar_t      flagAddress;  
    Float_t      x1,y1;        
    Float_t      x2,y2;        
    UShort_t     nEventTracks; 
    UShort_t     nReadTracks;  
    Bool_t       eventFlag;    
    Bool_t       arrayEnd;     
  public:
    HMdcStoreTracks(void);
    ~HMdcStoreTracks(void);
    virtual UInt_t getMemSize(void) const;
    
    
    Bool_t setEndTrack(void);
    void setEndEvent(Bool_t flag=kTRUE);
    void setTrackPar(UChar_t s, UChar_t m1, Float_t xf, Float_t yf,
        UChar_t m2, Float_t xl, Float_t yl, UChar_t flag=1);
    
    
    virtual void resetIter(void);  
    Bool_t nextEvent(void);
    Bool_t nextTrack(void);
    
    Bool_t  getEventFlag(void)            {return eventFlag;}
    Bool_t  getTrackFlag(void)            {return (flagAddress&128) > 0;}
    UChar_t getSector(void)               {return flagAddress&7;}
    UChar_t getMod1(void)                 {return (flagAddress>>3)&3;}
    UChar_t getMod2(void)                 {return (flagAddress>>5)&3;}
    Int_t   getNumEventTracks(void) const {return nEventTracks;}
    Float_t getX1(void) const             {return x1;}
    Float_t getY1(void) const             {return y1;}
    Float_t getZ1(void) const             {return 0.;}
    Float_t getX2(void) const             {return x2;}
    Float_t getY2(void) const             {return y2;}
    Float_t getZ2(void) const             {return 0.;}
    void getTrackPar(Float_t& xf,Float_t& yf, Float_t& xl,Float_t& yl) const;
    void getPoint1(HGeomVector& p1) const {p1.setXYZ(x1,y1,0.);}
    void getPoint2(HGeomVector& p2) const {p2.setXYZ(x2,y2,0.);}
    void getPoints(HGeomVector& p1,HGeomVector& p2) const {
        getPoint1(p1); getPoint2(p2);}
    
    void resetEventIter(void);   
    Bool_t resetTrackPar(Float_t xt,Float_t yt,Float_t xp,Float_t yp);
    Bool_t resetTrackFlag(Bool_t flag);
    Bool_t resetEventFlag(Bool_t flag);
    Bool_t isEnd(void) {return arrayEnd;}
    
  protected:
    void clear();
    Bool_t getTrackPar(void);
      
  ClassDef(HMdcStoreTracks,0)  
};
class HMdcStoreClusters : public HMdcStoreTracks {
  protected:
    HMdcStoreEvents wires;        
  
    UInt_t* wiresListPack[1200];  
    Int_t   numWires;
  public:
    HMdcStoreClusters(void) {}
    ~HMdcStoreClusters(void) {}
    virtual UInt_t getMemSize(void) const;
    
    
    void setEndCluster(void);
    
    
    virtual void resetIter(void);  
    Bool_t getNextCluster(void);
    Bool_t getNextCell(Int_t& s, Int_t& m, Int_t& l, Int_t& c, Float_t& tm) {
        return wires.getNextCell(s,m,l,c,tm);}
    Bool_t getNextCell(Int_t& s, Int_t& m, Int_t& l, Int_t& c, Float_t& tm,
        Bool_t& flag) {
        return wires.getNextCell(s,m,l,c,tm,flag);}
    
    
    void addClustWires(const HMdcEvntListCells& event, 
        const HMdcClus* cl);                        
    void addClustWires(const HMdcEvntListCells& event,
        const HMdcClus* cl1, const HMdcClus* cl2);  
    Bool_t getNextCluster(HMdcEvntListCells& event,Bool_t checkFlag=kFALSE);
    Bool_t unsetFlag(Int_t si,Int_t mi,Int_t li,Int_t ci);
    Bool_t setFlag(Int_t si,Int_t mi,Int_t li,Int_t ci);
    
  protected:
      
  ClassDef(HMdcStoreClusters,0)  
};
#endif  /*!HMDCSTOREEVENTS_H*/