#include "horaslowpartition.h"
#include "horaslowreaderonline.h"
#include "horaslowreader2010.h"
#include "horaslowreader2016.h"
#include "horaslowperiod.h"
#include "horaslowarchrateobj.h"
#include "TGraph.h"
#include "TDatime.h"
#include "TH1F.h"
#include "TList.h"
#include <stdlib.h>
ClassImp(HOraSlowPartition)
HOraSlowPartition::HOraSlowPartition(const Char_t* name) {
  
  SetName(name);
  pRunPeriods=0;
  periodIter=0;
  pRates=0;
  ratesIter=0;
  pGraph=0;
  pOraReader=0;
  if (strcmp(name,"online")==0) {
    pOraReader = new HOraSlowReaderOnline();
  } else {
    
    TString bt(name,5);
    bt.Remove(0,3);
    Int_t year = bt.Atoi();
    if (year > 0) {
      if (year >= 16) pOraReader=new HOraSlowReader2016();
      else            pOraReader=new HOraSlowReader2010();
    } else {
      Error("HOraSlowPartition(const Char_t* name)","Invalid partition name");
    }
  }
  if (pOraReader) pOraReader->setPartition(this);
}
HOraSlowPartition::~HOraSlowPartition() {
  
  clearRunPeriods();
  clearRates();
  if (pOraReader) {
    delete pOraReader;
    pOraReader=0;
  }
}
void HOraSlowPartition::clearRunPeriods() {
  
  if (periodIter) {
    delete periodIter;
    periodIter=0;
  }
  if (pRunPeriods) {
    pRunPeriods->Delete();
    delete pRunPeriods;
    pRunPeriods=0;
  }
}
void HOraSlowPartition::clearRates() {
  
  deleteGraph();
  if (ratesIter) {
    delete ratesIter;
    ratesIter=0;
  }
  if (pRates) {
    pRates->Delete();
    delete pRates;
    pRates=0;
  }
}
void HOraSlowPartition::deleteGraph() {
  
  if (pGraph) {
    delete pGraph;
    pGraph=0;
  }
}
Bool_t HOraSlowPartition::openOraInput() {
  
  if (pOraReader) return pOraReader->open();
  else return kFALSE;
}
void HOraSlowPartition::closeOraInput() {
  
  if (pOraReader) pOraReader->close();
}
void HOraSlowPartition::setTimeRange(const Char_t* t1,const Char_t* t2) {
  
  if (startTime.CompareTo(t1) != 0 || endTime.CompareTo(t2) != 0 ){
    clearRunPeriods();
    startTime = t1;
    endTime   = t2;
  }
}
TObjArray* HOraSlowPartition::setNumPeriods(Int_t n) {
  
  clearRunPeriods();
  if (n>0) {
    pRunPeriods=new TObjArray(n);
    periodIter=pRunPeriods->MakeIterator();
  }
  return pRunPeriods;
}
void HOraSlowPartition::setRates(TObjArray* p) {
  
  clearRates();
  pRates=p;
  if (pRates) ratesIter=pRates->MakeIterator();
}
HOraSlowPeriod* HOraSlowPartition::getPeriod(Int_t i) {
  
  if (pRunPeriods) return (HOraSlowPeriod*)(pRunPeriods->At(i));
  else return 0;
}
HOraSlowPeriod* HOraSlowPartition::getRun(Int_t runId) {
  
  HOraSlowPeriod* p=0;
  if (periodIter) {
    periodIter->Reset();
    while ((p=((HOraSlowPeriod*)(periodIter->Next())))!=0) {
      if (p->getRunId()==runId) break;
    }
  }
  return p;
}
HOraSlowPeriod* HOraSlowPartition::getRun(const Char_t* fname) {
  
  HOraSlowPeriod* p=0;
  if (periodIter) {
    periodIter->Reset();
    while ((p=((HOraSlowPeriod*)(periodIter->Next())))!=0) {
      if (strcmp(p->getFilename(),fname)==0) break;
    }
  }
  return p;
}
void HOraSlowPartition::print(Int_t opt) {
  
  
  
  
  if (periodIter) {
    periodIter->Reset();
    HOraSlowPeriod* p=0;
    Int_t i=0;
    cout<<"---------------------------------------------------------------------\n";
    cout<<"  Run periods of partition "<<GetName()<<'\n';
    cout<<"  Format: array index, startime, endtime, run id, filename\n";
    cout<<"---------------------------------------------------------------------\n";
    while ((p=((HOraSlowPeriod*)(periodIter->Next())))!=0) {
      if (opt==0
          ||(opt==1&&strlen(p->getFilename())>4)
          ||(opt==2&&p->getFilterFlag()==1)) {
        cout<<setw(5)<<i<<"  ";
        p->print();
      }
      i++;
    }
    cout<<"---------------------------------------------------------------------\n";
  } else cout<<"  NO DATA\n";
}
  
void HOraSlowPartition::write(fstream& fout,Int_t opt) {
  
  
  
  
  if (periodIter) {
    periodIter->Reset();
    HOraSlowPeriod* p=0;
    Int_t i=0;
    fout<<"---------------------------------------------------------------------\n";
    fout<<"  Run periods of partition "<<GetName()<<'\n';
    fout<<"  Format: array index, startime, endtime, run id, filename\n";
    fout<<"---------------------------------------------------------------------\n";
    while ((p=((HOraSlowPeriod*)(periodIter->Next())))!=0) {
      if (opt==0
          ||(opt==1&&strlen(p->getFilename())>4)
          ||(opt==2&&p->getFilterFlag()==1)) {
        fout<<setw(5)<<i<<"  ";
        p->write(fout);
      }
      i++;
    }
    fout<<"---------------------------------------------------------------------\n";
  }
}
void HOraSlowPartition::setHldFileFilter(TList* l) {
  
  
  if (periodIter) {
    periodIter->Reset();
    HOraSlowPeriod* p=0;
    while ((p=((HOraSlowPeriod*)(periodIter->Next())))!=0) {
      Int_t f=1;
      if (l) {
        const Char_t* s=p->getFilename();   
        if (strlen(s)==0||l->FindObject(s)==0) f=0;
      }
      p->setFilterFlag(f);
    }
  }
} 
void HOraSlowPartition::printRates() {
  
  if (ratesIter) {
    ratesIter->Reset();
    HOraSlowArchRateObj* p=0;
    Int_t i=0;
    cout<<"---------------------------------------------------------------------\n";
    cout<<"  Archiver rates of partition "<<GetName()<<'\n';
    cout<<"  Format: startime, entries/minute \n";
    cout<<"---------------------------------------------------------------------\n";
    while ((p=((HOraSlowArchRateObj*)(ratesIter->Next())))!=0) {
      p->print();
      i++;
    }
    cout<<"---------------------------------------------------------------------\n";
  } else cout<<"  NO DATA\n";
}  
 
void HOraSlowPartition::writeRates(fstream& fout) {
  
  if (ratesIter) {
    ratesIter->Reset();
    HOraSlowArchRateObj* p=0;
    Int_t i=0;
    fout<<"---------------------------------------------------------------------\n";
    fout<<"  Archiver rates of partition "<<GetName()<<'\n';
    fout<<"  Format: startime, entries/minute \n";
    fout<<"---------------------------------------------------------------------\n";
    while ((p=((HOraSlowArchRateObj*)(ratesIter->Next())))!=0) {
      p->write(fout);
      i++;
    }
    fout<<"---------------------------------------------------------------------\n";
  } else fout<<"  NO DATA\n";
}  
TGraph* HOraSlowPartition::getRatesGraph(Int_t mStyle,Int_t mColor) {
  
  
  if (pRates==0) return 0;
  deleteGraph();
  Int_t len=pRates->GetLast()+1;
  pGraph=new TGraph(len);
  ratesIter->Reset();
  HOraSlowArchRateObj* p=0;
  Int_t i=0;
  TString startTime;
  while ((p=((HOraSlowArchRateObj*)(ratesIter->Next())))!=0) {
    if (i==0) {
      startTime=p->getStartTime();
      pGraph->SetPoint(i,0,p->getRate());      
    } else {
      pGraph->SetPoint(i,p->getTimeDiff(startTime.Data()),p->getRate());
    }
    i++;
  }
  pGraph->SetTitle(GetName());
  pGraph->SetMarkerStyle(mStyle);
  pGraph->SetMarkerColor(mColor);
  TH1F* hist=pGraph->GetHistogram();
  TAxis* xaxis=hist->GetXaxis();
  TString s("Time (Start at ");
  s+=startTime;
  s+=")";
  xaxis->SetTitle(s);
  TDatime t1(startTime.Data());
  
  UInt_t utc=t1.Convert();
  time_t timeoff=(time_t)((Long_t)(utc));
  struct tm* loctis=localtime(&timeoff);
  Char_t tmp[20];
  strftime(tmp,256,"%z",loctis);
  if (strcmp(tmp,"+0200")==0) utc+=3600;
  xaxis->SetTimeDisplay(1);
  xaxis->SetTimeOffset(utc);
  xaxis->SetTimeFormat("%d/%m:%H");
  TAxis* yaxis=hist->GetYaxis();
  yaxis->SetTitle("Entries per minute");
  return pGraph;
}