////////////////////////////////////////////////////////////////////////
//
//  MObjBuffer
//
//  This is a ring buffer for TObjects
//  It should be similar to TObjArray, but with different counting
//
////////////////////////////////////////////////////////////////////////
#include "MObjBuffer.h"

#include "MFileDescr.h"
#include "MFile.h"

ClassImp (MObjBuffer)

MObjBuffer::MObjBuffer(MParContainer *o, Int_t nevts,
                       const char *name, const char *title) :
    fIsInput(kFALSE), fIsOutput(kFALSE), fHasChanged(kFALSE),
    nPos(0), nObjPos(0)
{
    fName  = name  ? name  : o->GetName();
    fTitle = title ? title : o->GetTitle();

    //
    // add the given object as first to the buffer
    //
    objs.Add(o);

    //
    // create nevts-1 new objects of the given object and add them to the buffer
    //
    for (Int_t i = 1; i<2*nevts+1; i++)
    {
        objs.Add(o->New());
    }

    nPreObjs = nPostObjs = nevts;
    nEntries = nPreObjs+nPostObjs+1;
}

void MObjBuffer::SetAsInput(MFile *f, Bool_t i)
{
    fIsInput = i;

    if (fIsInput)
        pFileIn = f->OpenInput(fName, objs[0]->ClassName());
    //    else
    //        f->CloseInput();
}

void MObjBuffer::SetAsOutput(MFile *f, Bool_t o)
{
    fIsOutput = o;

    if (fIsOutput)
        pFileOut = f->OpenOutput(fName, objs[0]->ClassName(), (MParContainer**)&objs[0]);
}

Int_t MObjBuffer::GetNextEvent(Int_t time)
{
    //
    // one step forward in the ring buffer
    //
    nObjPos++;
    nObjPos %= nEntries;

    //
    // calculate the address of the object after the last one in the ring buffer
    //
    Int_t adr = (nObjPos+nPostObjs+nEntries+1)%nEntries;

    //
    // get the next entry (some event in the future) from file
    //

    pFileIn->SetAddress((MParContainer**)&objs[adr]);
    pFileIn->GetEvent(nPos++);

    //
    // return number of actual event (present) in tree
    //
    return nPos-nPostObjs-1;
}

void MObjBuffer::PutEvent()
{
    //
    // one step forward in the ring buffer
    //
    nObjPos++;
    nObjPos %= nEntries;

    //
    // write actual (present) object to file
    //
    pFileOut->SetAddress((MParContainer**)&objs[nObjPos]);
    pFileOut->Fill();
}

void MObjBuffer::Fill()
{
    //
    // in the future this function has to handle the dynamic buffer
    //
    if (nPos)
        return;

    //
    // fill PreBuffer (( objects in the future)
    //
    for (Int_t i=1; i<nPostObjs+2; i++)
    {
        pFileIn->SetAddress((MParContainer**)&objs[i]);
        pFileIn->GetEvent(nPos++);
    }
    nObjPos = 0;
}

