#ifndef MARS_MTask
#define MARS_MTask

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
// MTask                                                                   //
//                                                                         //
// Abstract base class for a task                                          //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

#ifndef MARS_MInputStreamID
#include "MInputStreamID.h"
#endif

class TList;

class MFilter;
class MParList;

class MTask : public MInputStreamID
{
private:
    TList *fListOfBranches; //! List of Branch names for auto enabeling scheme

    MFilter *fFilter;       // Filter for conditional task execution
    Byte_t   fSerialNumber; // Serial number having more than one detector of the same type

    Bool_t fIsPreprocessed; //! Indicates the success of the PreProcessing (set by MTaskList)
    UInt_t fNumExecutions;  //! Number of Excutions

    virtual Int_t PreProcess(MParList *pList);
    virtual Int_t Process();
    virtual Int_t PostProcess();

protected:
    void AddToBranchList(const char *b);
    void AddToBranchList(const TString &str);
    void AddToBranchList(const char *master, const char *sub, const UInt_t first, const UInt_t last)
    {
        if (first==0 && last==0)
        {
            AddToBranchList(sub);
            return;
        }

        for (unsigned int i=first; i<last+1; i++)
            AddToBranchList(Form("%s;%d.%s", master, i, sub));
    }
    void AddToBranchList(TString &master, TString &sub, const UInt_t first, const UInt_t last)
    {
        AddToBranchList((const char*)master, (const char*)sub, first, last);
    }
    void AddToBranchList(const char *master, const char *sub, const UInt_t num)
    {
        AddToBranchList(master, sub, 0, num);
    }
    void AddToBranchList(TString &master, TString &sub, const UInt_t num)
    {
        AddToBranchList(master, sub, 0, num);
    }

public:
    MTask(const char *name=NULL, const char *title=NULL);
    MTask(MTask &t);
    virtual ~MTask();

    virtual void SetFilter(MFilter *filter) { fFilter=filter; }
    const MFilter *GetFilter() const      { return fFilter; }
    MFilter *GetFilter()  { return fFilter; } // for MContinue only

    void SetDisplay(MStatusDisplay *d);
    virtual void PrintStatistics(const Int_t lvl=0, Bool_t title=kFALSE) const;

    virtual void SetSerialNumber(Byte_t num) { fSerialNumber = num; }
    Byte_t  GetSerialNumber() const { return fSerialNumber; }
    TString AddSerialNumber(const char *str) const { TString s(str); if (fSerialNumber==0) return s; s += ";"; s += fSerialNumber; return s; }
    TString AddSerialNumber(const TString &str) const { return AddSerialNumber((const char*)str); }

    const char *GetDescriptor() const;

    UInt_t GetNumExecutions() const { return fNumExecutions; }

    virtual Bool_t ReInit(MParList *pList);

    virtual Int_t CallPreProcess(MParList *plist);
    virtual Int_t CallProcess();
    virtual Int_t CallPostProcess();

    const TList *GetListOfBranches() const { return fListOfBranches; }

    Bool_t OverwritesProcess(TClass *cls=NULL) const;

    void SavePrimitive(ofstream &out, Option_t *o="");

    ClassDef(MTask, 2) //Abstract base class for a task
};

#endif
