///////////////////////////////////////////////////////////////////////
//                                                                   //
// MTaskList                                                         //
//                                                                   //
// Collection of tasks to be processed in the eventloop              //
//                                                                   //
///////////////////////////////////////////////////////////////////////

#include "MTaskList.h"

#include "MLog.h"
#include "MParList.h"
#include "MInputStreamID.h"

ClassImp(MTaskList)

MTaskList::MTaskList(const char *title)
{
    //
    // the name for the task list must be the same for all task lists
    // because the task list (at the moment) is identified by exactly
    // this name in the parameter list (by MEvtLoop::SetParList)
    //
    *fName  = "MTaskList";
    *fTitle = title ? title : "List for Tasks";

    //
    //  default constructor: create empty task list
    //
}

MTaskList::MTaskList(MTaskList &ts)
{
  //
  //   CopyConstructor 
  //   creates a new TaskList and put the contents of an existing
  //   TaskList in the new TaskList. 
  //
  fTasks.AddAll(&ts.fTasks);
}

void MTaskList::SetLogStream(MLog *log)
{
    //
    //  create the Iterator over the tasklist
    //
    TIter Next(&fTasks);

    MTask *task=NULL;

    //
    // loop over all tasks for preproccesing
    //
    while ( (task=(MTask*)Next()) )
        task->SetLogStream(log);

    MParContainer::SetLogStream(log);
}


Bool_t MTaskList::AddToList(MTask *task, const char *type, MTask *where)
{
    // schedule task for execution, whether as first task, or after
    // 'where'. 'tType' is the event type which should be processed
    if (!task)
        return kTRUE;

    const char *name = task->GetName();

    // FIXME: We agreed to put the task into list in an ordered way.

    if (fTasks.FindObject(task))
    {
        *fLog << "WARNING: MTaskList::AddToList: Task already existing." << endl;
        return kTRUE;
    }

    if (fTasks.FindObject(name))
    {
        *fLog << "WARNING: MTaskList::AddToList: '" << name << "' exists in List already." << endl;
        return kTRUE;
    }

    if (where)
    {
        if (!fTasks.FindObject(where))
        {
            printf("ERROR: MTaskList::AddToList: Cannot find task after which the new task should be scheduled!\n");
            return kFALSE;
        }
    }

    *fLog << "Adding " << name << " to " << GetName() << " for " << type << "... " << flush;

    task->SetStreamId(type);
    fTasks.Add(task);

    *fLog << "Done." << endl;

    return kTRUE;
}


Bool_t MTaskList::PreProcess( MParList *pList )
{ 
    //
    // do pre processing (before eventloop) of all tasks in the task-list
    //
    *fLog << "Preprocessing... " << flush;

    //
    //  create the Iterator over the tasklist
    //
    TIter Next(&fTasks);

    MTask *task=NULL;

    //
    // loop over all tasks for preproccesing
    //
    while ( (task=(MTask*)Next()) )
    {
        *fLog << task->GetName() << "... " << flush;

        if (!task->PreProcess( pList ))
            return kFALSE;
    }

    *fLog << endl;

    return kTRUE;
}

Bool_t MTaskList::Process()
{
  //
  // do the event execution of all tasks in the task-list
  //
  
  //
  //  create the Iterator for the TaskList
  //
  TIter Next(&fTasks);
  MTask *task=NULL;
    
  //
  // loop over all tasks for processing 
  //
  while ( (task=(MTask*)Next()) )
  {
      if (!strcmp(GetStreamId(), task->GetStreamId()) ||
          !strcmp(task->GetStreamId(), "All"))
      {
          switch (task->Process())
          {
          case kTRUE:
              //
              // everything was OK: go on
              //
              continue;

          case kFALSE:
              //
              // an error occured: stop eventloop
              //
              return kFALSE;

          case kCONTINUE:
              //
              // something occured: skip the rest of the tasks for this event
              //
              break;
          }
      }
  }
  return kTRUE;
}

Bool_t MTaskList::PostProcess()
{
  //
  // do post processing (before eventloop) of all tasks in the task-list
  //

    *fLog << "Postprocessing... " << flush;

  //
  //  create the Iterator for the TaskList
  //
  TIter Next(&fTasks);
  
  MTask *task=NULL;

  //
  //  loop over all tasks for postprocessing
  //  
  while ( (task=(MTask*)Next()) )
  {
      *fLog << task->GetName() << "... " << flush;

      if (!task->PostProcess())
          return kFALSE;
  }

  *fLog << endl;

  return kTRUE;
}



void MTaskList::Print(Option_t *t)
{
  *fLog << "TaskList: " << this->GetName() << " <" <<  this->GetTitle() << ">" << endl;
  
  fTasks.Print();

  *fLog << endl;
}

