#ifndef MARS_MDataFormat
#define MARS_MDataFormat

#ifndef MARS_MAGIC
#include "MAGIC.h"
#endif

#ifndef ROOT_Rtypes
#include <Rtypes.h>
#endif

#include <iosfwd>
#include <fstream>

class MCorsikaFormat
{
protected:
   std::istream  *fIn;

   Bool_t fMMCS = true;

public:
    static const unsigned int kSyncMarker;

   MCorsikaFormat(std::istream * in)
        : fIn(in) { }
   virtual ~MCorsikaFormat();

   virtual Bool_t NextBlock(Int_t   readState, Int_t & blockType, Int_t & blockVersion,
                            Int_t & blockIdentifier, Int_t & blockLength) const = 0;

           void   Seek(std::streampos offset)    {fIn->seekg(offset, std::ios::cur);}

   virtual Bool_t SeekEvtEnd() = 0;

   virtual Bool_t IsEventioFormat() const = 0;

   virtual Bool_t Eof() const;

           Bool_t Read(void *ptr, Int_t i) const;


   static MCorsikaFormat *CorsikaFormatFactory(const char *fileName);

   const Bool_t isMMCS() {return fMMCS;}
};


class MCorsikaFormatRaw : public MCorsikaFormat
{
private:
	Bool_t fFortranRaw = false;

public:
   MCorsikaFormatRaw(std::istream * in)
        : MCorsikaFormat(in) {}
   MCorsikaFormatRaw(std::istream* in, Bool_t fortranRaw)
   	    : MCorsikaFormat(in), fFortranRaw (fortranRaw) {}

   Bool_t NextBlock(Int_t   readState, Int_t & blockType, Int_t & blockVersion,
                    Int_t & blockIdentifier, Int_t & blockLength) const;

   Bool_t SeekEvtEnd();

   Bool_t IsEventioFormat() const {return kFALSE;}
};


class MCorsikaFormatEventIO : public MCorsikaFormat
{

public:
    MCorsikaFormatEventIO(std::istream *in)
        : MCorsikaFormat(in) {}


    Bool_t NextBlock(Int_t   readState, Int_t & blockType, Int_t & blockVersion,
                     Int_t & blockIdentifier, Int_t & blockLength) const;

    Bool_t SeekEvtEnd();

    Bool_t IsEventioFormat() const { return kTRUE; }

};

#endif

