#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

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

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

protected:
    void AddToBranchList(const char *b);
    void AddToBranchList(const TString &str)
    {
        AddToBranchList((const char*)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();

    void SetFilter(MFilter *filter) { fFilter=filter; }
    const MFilter *GetFilter() const      { return fFilter; }
    virtual void PrintStatistics(const Int_t lvl=0) const;

    UInt_t GetNumExecutions() { return fNumExecutions; }

    virtual Bool_t ReInit(MParList *pList);

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

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

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

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

#endif
