#include "TMDisplayingList.h"
#include "TMControlSPD.h"
#include "TMControlMutex.h"
#include "SPDMood.h"

extern pthread_mutex_t gMutex;

Bool_t TMDisplayingList::instanceFlag = kFALSE;
TMDisplayingList* TMDisplayingList::single = NULL;
//___________________________________________________________________________________
TMDisplayingList* TMDisplayingList::Instance() {
 if(!instanceFlag) {
   instanceFlag = kTRUE;
   single = new TMDisplayingList();
   return single;
 }
 else {
   return single;
 }
}
//___________________________________________________________________________________
TMDisplayingList::TMDisplayingList() :
  fList()
{}
//___________________________________________________________________________________
TMDisplayingList::~TMDisplayingList() {}
//___________________________________________________________________________________
void TMDisplayingList::Clear() {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    delete (*it)->GetDisplayingObj();
    delete (*it);
  }
  fList.clear();
}
//___________________________________________________________________________________
void TMDisplayingList::SaveEntries(ofstream& sFile) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    sFile << (*it)->GetId() << "\t";
    sFile << (*it)->GetPlotNr() << "\t";
    sFile << (*it)->GetCloneId() << "\t";
    sFile << (*it)->GetDisplayingObj()->IsAutoUpdate() << "\t";
    sFile << (*it)->GetDisplayingObj()->GetTextEventMod() << "\t";
    sFile << (*it)->GetDisplayingObj()->GetTextEventModEq() << "\t";

    Window_t wdum;
    Int_t x,y;
    UInt_t w,h;
    gVirtualX->GetWindowSize((*it)->GetDisplayingObj()->GetId(), x, y, w, h);
    gVirtualX->TranslateCoordinates((*it)->GetDisplayingObj()->GetId(),gClient->GetRoot()->GetId(),0,0,x,y,wdum);

    sFile << x << "\t";
    sFile << y << "\t";
    sFile << w << "\t";
    sFile << h << "\t";
    sFile << "\n";
  }
}
//___________________________________________________________________________________
void TMDisplayingList::AddDisplayingObj(TMDisplaying *disp, UInt_t id, UInt_t plotNr, UInt_t cloneId) {
//!!!  // check first that it is not there already:
//!!!  Bool_t found = kFALSE;
//!!!  std::list<TMDisplayingListNode*>::iterator it;
//!!!  for (it=fList.begin(); it!=fList.end(); it++) {
//!!!    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr && (*it)->GetCloneId()==cloneId) {
//!!!      found = kTRUE;
//!!!      printf("TMDisplayingList::AddDisplayingObj: Object already present. Deleting the new one.\n");
//!!!      delete disp;      
//!!!      break;
//!!!    }
//!!!  }
//!!!  if (!found) {
  fList.push_back(new TMDisplayingListNode(disp,id,plotNr,cloneId));
//!!!  }
}
//___________________________________________________________________________________
void TMDisplayingList::SetAutoUpdate(UInt_t id, UInt_t plotNr, UInt_t cloneId, Bool_t autoupdate) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr && (*it)->GetCloneId()==cloneId) {
      (*it)->GetDisplayingObj()->ToggleAutoUpdateButton(autoupdate);
    }
  }
}
//___________________________________________________________________________________
void TMDisplayingList::SetEventMod(UInt_t id, UInt_t plotNr, UInt_t cloneId, UInt_t value) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr && (*it)->GetCloneId()==cloneId) {
      TString strval = Form("%d",value);
      (*it)->GetDisplayingObj()->SetTextEventMod(strval.Data());
    }
  }
}
//___________________________________________________________________________________
void TMDisplayingList::SetEventModEq(UInt_t id, UInt_t plotNr, UInt_t cloneId, UInt_t value) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr && (*it)->GetCloneId()==cloneId) {
      TString strval = Form("%d",value);
      (*it)->GetDisplayingObj()->SetTextEventModEq(strval.Data());
    }
  }
}
//___________________________________________________________________________________
void TMDisplayingList::SetAutoReset(UInt_t id, UInt_t plotNr, Bool_t autoreset) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr) {
      (*it)->GetDisplayingObj()->ToggleAutoResetButton(autoreset);
    }
  }
}
//___________________________________________________________________________________
void TMDisplayingList::SetPaused(UInt_t id, UInt_t plotNr, Bool_t paused) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr) {
      (*it)->GetDisplayingObj()->TogglePauseButton(paused);
    }
  }
}
//___________________________________________________________________________________
void TMDisplayingList::ResizeDisplay(UInt_t id, UInt_t plotNr, UInt_t cloneId, Int_t posX, Int_t posY, UInt_t posW, UInt_t posH) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr) {
      (*it)->GetDisplayingObj()->MoveResize(posX,posY,posW,posH);
    }
  }
}
//___________________________________________________________________________________
void TMDisplayingList::ReducePlotNr(UInt_t id, UInt_t plotNr) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()>plotNr) {
      UInt_t newplotnr = (*it)->GetPlotNr()-1;
      (*it)->SetPlotNr(newplotnr);
      (*it)->GetDisplayingObj()->SetPlotNr(newplotnr);
      (*it)->GetDisplayingObj()->UpdateWindowName();
    }
  }
}
//___________________________________________________________________________________
void TMDisplayingList::RemoveDisplayingObj(UInt_t id, UInt_t plotNr) {
  std::list<TMDisplayingListNode*>::iterator it;
  Bool_t continueRemoving = kFALSE;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr) {
      delete (*it)->GetDisplayingObj();
      delete (*it);
      fList.erase(it);
      continueRemoving = kTRUE;
      break;
    }
  }
  if (continueRemoving) RemoveDisplayingObj(id,plotNr);
}
//___________________________________________________________________________________
void TMDisplayingList::RemoveDisplayingObj(UInt_t id, UInt_t plotNr, UInt_t cloneId) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr && (*it)->GetCloneId()==cloneId) {
      delete (*it)->GetDisplayingObj();
      delete (*it);
      fList.erase(it);
      break;
    }
  }
}
//___________________________________________________________________________________
TMDisplaying* TMDisplayingList::GetDisplayingObj(UInt_t id, UInt_t plotNr, UInt_t cloneId) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr && (*it)->GetCloneId()==cloneId) {
      return (*it)->GetDisplayingObj();
    }
  }
  return NULL;
}
//___________________________________________________________________________________
Bool_t TMDisplayingList::Find(UInt_t id, UInt_t plotNr, UInt_t cloneId) {
  Bool_t found = kFALSE;
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr && (*it)->GetCloneId()==cloneId) {
      found = kTRUE;
      break;
    }
  }
  return found;
}
//___________________________________________________________________________________
Bool_t TMDisplayingList::HighLight(UInt_t id, UInt_t plotNr) {
  Bool_t found = kFALSE;
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr) {
      found = kTRUE;
      (*it)->GetDisplayingObj()->RaiseWindow();
    }
  }
  return found;
}
//___________________________________________________________________________________
void TMDisplayingList::UpdateDisplays() {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    (*it)->GetDisplayingObj()->Update();
  }
}
//___________________________________________________________________________________
void TMDisplayingList::UpdateAutoDisplays() {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    (*it)->GetDisplayingObj()->UpdateAuto();
  }
}
//___________________________________________________________________________________
void TMDisplayingList::UpdateAutoAllDisplays() {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    (*it)->GetDisplayingObj()->UpdateAutoAll();
  }
}
//___________________________________________________________________________________
void TMDisplayingList::UpdateDisplayID(UInt_t id, UInt_t plotNr, UInt_t cloneId) {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    if ((*it)->GetId()==id && (*it)->GetPlotNr()==plotNr && (*it)->GetCloneId()==cloneId) {
      (*it)->GetDisplayingObj()->Update();
      return;
    }
  }
}
//___________________________________________________________________________________
void TMDisplayingList::ScreenShotAll(const Char_t *localDir, const Char_t *extension) {
  Bool_t ihavelock = TMControlMutex::Instance()->DoIHaveLock();
  if (!ihavelock) {
    pthread_mutex_lock(&gMutex);
    //    printf("TMDispList::ScreenShAll");
    TMControlMutex::Instance()->ITakeLock();
  }

  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    (*it)->GetDisplayingObj()->ProcessScreenShot2default(localDir,extension);
  }

  if (!ihavelock) {
    TMControlMutex::Instance()->IReleaseLock();
    pthread_mutex_unlock(&gMutex);
  }
}
//___________________________________________________________________________________
void TMDisplayingList::ProcessStartRun() {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    (*it)->GetDisplayingObj()->ProcessStartRun();
  }
}
//___________________________________________________________________________________
void TMDisplayingList::ProcessEndRun() {
  std::list<TMDisplayingListNode*>::iterator it;
  for (it=fList.begin(); it!=fList.end(); it++) {
    (*it)->GetDisplayingObj()->ProcessEndRun();
  }
}
