#include "runnerDefine.icc"

#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>

#include <iostream>
#include <sstream>
#include <vector>
#include <cstdio>

#include "TROOT.h"
#include "TApplication.h"

#include "UtlTime.hh"
#include "UtlArguments.hh"
#include "RcdArena.hh"
#include "RcdWriterAsc.hh"

#include "DaqRunStart.hh"
#include "RcdReaderAsc.hh"
#include "RcdReaderBin.hh"

#include "ChkCount.hh"
#include "ChkPrint.hh"

#include "HstList.C"
#include "HstTH1F.C"
#include "HstTH2F.C"
#include "HstTH2D.C"
#include "HstRecord.C"
#include "HstCrcNoise.C"
#include "HstCheck.C"
#include "HstCrcFeNoise.C"
#include "HstCrcSignal.C"
#ifndef HST_MAP
  #include "HstBeTrgHistory.C"
#endif
#include "HstLc1176.C"
#ifndef HST_MAP
  #include "HstCaen767.C"
  #include "HstLalHodoscope.C"
  #include "HstMpsBunchTrain.C"
#endif
#include "HstEmcEvent.C"
#include "HstAhcEvent.C"
#include "HstFlagsTimers.C"
#include "HstCrcChannel.C"

using namespace std;


int main(int argc, const char **argv) {
  UtlArguments argh(argc,argv);

  const std::string hist(argh.lastArgument("HstHist"));

  std::vector<std::string> displayNames;

#ifdef HST_MAP
  displayNames.push_back("HstList");
  if(hist=="HstList") {
    HstList();
    return 0;
  }
#endif

  TApplication application("HstDisplayApplication",0,0);
  gROOT->Reset();

#ifdef HST_MAP
  displayNames.push_back("HstTH1F");
  if(hist=="HstTH1F") {
    const std::string histName(argh.optionArgument('n',"HstCrcSignalCrate0","TH1F histogram name"));
    const bool plotErrors(argh.option('e',false,"Plot errors"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;
    
    HstTH1F(histName.c_str(),plotErrors,sleepMs);
    return 0;
  }
  
  displayNames.push_back("HstTH2F");
  if(hist=="HstTH2F") {
    const std::string histName(argh.optionArgument('n',"HstCrcSignalCrate0Signal","TH2F histogram name"));
    const std::string options(argh.optionArgument('o',"box","TH2F histogram options"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;
    
    HstTH2F(histName.c_str(),options.c_str(),sleepMs);
    return 0;
  }

  displayNames.push_back("HstTH2D");
  if(hist=="HstTH2D") {
    const std::string histName(argh.optionArgument('n',"HstRecordTimeJob","TH2D histogram name"));
    const std::string options(argh.optionArgument('o',"box","TH2D histogram options"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;
    
    HstTH2D(histName.c_str(),options.c_str(),sleepMs);
    return 0;
  }
#endif
  
  displayNames.push_back("HstRecord");
  if(hist=="HstRecord") {
    const unsigned bits(argh.optionArgument('b',0x1f,"Bits: 0=Job, 1=Run, 2=Cfg, 3=Acq, 4=Size/time"));
    const bool job(argh.option('j',false,"Display job information"));
    const bool run(argh.option('r',false,"Display run information"));
    const bool cfg(argh.option('c',false,"Display configuration information"));
    const bool acq(argh.option('a',false,"Display acquisition information"));
    const bool size(argh.option('s',false,"Display size and time information"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    UtlPack uBits(0);
    uBits.bit(0,job);
    uBits.bit(1,run);
    uBits.bit(2,cfg);
    uBits.bit(3,acq);
    uBits.bit(3,size);

    if(!argh.option('j') && !argh.option('r') && 
       !argh.option('c') && !argh.option('a') &&
       !argh.option('a') && !argh.option('s')) uBits.word(bits);

    HstRecord(uBits.word(),sleepMs);
    return 0;
  }

  displayNames.push_back("HstCrcNoise");
  if(hist=="HstCrcNoise") {
    const unsigned swi(argh.optionArgument('w',1,"Switch: 0 = FE/ADC, not 0 = FE/Chip/Channel"));
    const unsigned bits(argh.optionArgument('b',0x1ffffff,"Bits: 0-21 slot, 22-24 crate"));
    const unsigned crate(argh.optionArgument('c',0,"Crate: 0 ECAL, 1 AHCAL, 2 EDHCAL"));
    const unsigned slot(argh.optionArgument('s',12,"Slot"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    if(argh.option('c')) HstCrcNoise(swi,crate,slot,sleepMs);
    else                 HstCrcNoise(swi,bits,sleepMs);
    return 0;
  }

#ifndef HST_MAP
  displayNames.push_back("HstCrcChannel");
  if(hist=="HstCrcChannel") {
    const unsigned crate(argh.optionArgument('c',0,"Crate: 0 ECAL, 1 AHCAL, 2 EDHCAL"));
    const unsigned slot(argh.optionArgument('s',12,"Slot"));
    const unsigned fe(argh.optionArgument('f',0,"FE"));
    const unsigned chip(argh.optionArgument('p',0,"Chip"));
    const unsigned chan(argh.optionArgument('n',0,"Channel"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    HstCrcChannel(crate,slot,fe,chip,chan,sleepMs);
    return 0;
  }
#endif

#ifdef HST_MAP
  displayNames.push_back("HstCrcFeNoise");
  if(hist=="HstCrcFeNoise") {
    const unsigned crate(argh.optionArgument('c',0,"Crate: 0 ECAL, 1 AHCAL, 2 EDHCAL"));
    const unsigned slot(argh.optionArgument('s',12,"Slot"));
    const unsigned fe(argh.optionArgument('f',0,"FE"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    HstCrcFeNoise(crate,slot,fe,sleepMs);
    return 0;
  }

  displayNames.push_back("HstCrcSignal");
  if(hist=="HstCrcSignal") {
    const unsigned crate(argh.optionArgument('c',0,"Crate: 0 ECAL, 1 AHCAL, 2 EDHCAL"));
    const unsigned slot(argh.optionArgument('s',12,"Slot"));
    const unsigned fe(argh.optionArgument('f',0,"FE"));
    const unsigned chip(argh.optionArgument('a',0,"Chip (ADC)"));
    const unsigned chan(argh.optionArgument('m',0,"Channel (multiplex)"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    HstCrcSignal(crate,slot,fe,chip,chan,sleepMs);
    return 0;
  }

  displayNames.push_back("HstCheck");
  if(hist=="HstCheck") {
    const unsigned bits(argh.optionArgument('b',0xffffffff,"Bits"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    HstCheck(bits,sleepMs);
    return 0;
  }
#endif

#ifndef HST_MAP
  displayNames.push_back("HstBeTrgHistory");
  if(hist=="HstBeTrgHistory") {
    const unsigned bits(argh.optionArgument('b',0,"Bits"));
    const bool timers(argh.option('t',false,"Display times"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    if(!timers) HstBeTrgHistory(bits,sleepMs);
    else        HstFlagsTimers(HstBeTrgHistoryStore::shmKey,bits,sleepMs);
    return 0;
  }
#endif

  displayNames.push_back("HstLc1176");
  if(hist=="HstLc1176") {
    const unsigned bits(argh.optionArgument('b',0xfff,"Bits: 0-15 for each TDC channel"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    HstLc1176(bits,sleepMs);
    return 0;
  }

#ifndef HST_MAP
  displayNames.push_back("HstCaen767");
  if(hist=="HstCaen767") {
    const unsigned bits(argh.optionArgument('b',0x3ff,"Bits: 0-15 for each TDC channel"));
    const unsigned gran(argh.optionArgument('g',10,"TDC values histogram granularity"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    HstCaen767(bits,gran,sleepMs);
    return 0;
  }

  displayNames.push_back("HstLalHodoscope");
  if(hist=="HstLalHodoscope") {
    const unsigned bits(argh.optionArgument('b',0x7,"Bits: 0-2, with 0=digital x and y, 1=analogue x, 2=analogue y"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    HstLalHodoscope(bits,sleepMs);
    return 0;
  }

#endif

#ifndef HST_MAP
  displayNames.push_back("HstMpsBunchTrain");
  if(hist=="HstMpsBunchTrain") {
    const unsigned bits(argh.optionArgument('b',0x6,"Bits: 0=Job, 1=Run, 2=Cfg, 3=Bnt, 4=Lego"));
    const unsigned sens(argh.optionArgument('s',0,"Sensor readout number: 0-3"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
     
    if(argh.help()) return 0;
 
    HstMpsBunchTrain(bits,sens,sleepMs);
    return 0;
  }
#endif

#ifdef HST_MAP
  displayNames.push_back("HstEmcEvent");
  if(hist=="HstEmcEvent") {
    const int cut(argh.optionArgument('c',30,"Cut"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    HstEmcEvent(cut,sleepMs);
    return 0;
  }
#endif

  /*
  if(hist=="HstAhcEvent") {
    const int cut(argh.optionArgument('c',150,"Cut"));
    const unsigned sleepMs(argh.optionArgument('m',1000,"Sleep (ms)"));
    
    if(argh.help()) return 0;

    HstAhcEvent(cut,sleepMs);
    return 0;
  }
  */

  if(argh.option('h')) {
    std::cout << std::endl
	      << "Usage: hstDisplay [options] <displayname>" << std::endl
	      << " hstDisplay -h <displayname> gives applicable options" << std::endl
	      << " Known displaynames are:" << std::endl;

    for(unsigned i(0);i<displayNames.size();i++) {
      std::cout << "  " << displayNames[i] << std::endl;
    }

    std::cout << std::endl;
    return 0;
  }

  return 1;
}
