#include <RAT/DQOccupancyByTrigger.hh>
#include <RAT/Log.hh>

namespace RAT {

  DQOccupancyByTrigger::DQOccupancyByTrigger() : Processor("DQOccupancyByTrigger"){}

  void DQOccupancyByTrigger::BeginOfRun(DS::Run&){

    fNChannels = 9728;

    // Decides on the useful trigger bits to look at
    // This is currently the N100s, N20s, ESUMH, OWLN, PGT, PRESCALE
    for(int i = 0; i < 12; i++){
      // Skip ESUML and OWLEs
      if(i != 5 && i != 8 && i != 9){
        fTriggers.push_back(i);
        fNTrig++;
      }
    }

    fTrigCount.resize(fNTrig, 0);
    fTrigOccupancy.resize(fNTrig, std::vector<int>(fNChannels, 0));

    const RAT::DU::ChanHWStatus& chanHWStatus = RAT::DU::Utility::Get()->GetChanHWStatus();

    // Find all channels that are offline according to CHS
    for(int i = 0; i < fNChannels; i++){
      if(!chanHWStatus.IsTubeOnline(i)){
        for(int j = 0; j < fNTrig; j++){
          fTrigOccupancy[j][i] = -1;
        }
      }
    }
  }

  Processor::Result DQOccupancyByTrigger::DSEvent(DS::Run&, DS::Entry& ds){
    for(size_t iEV = 0; iEV < ds.GetEVCount(); iEV++){
      Event(ds, ds.GetEV(iEV));
    }
    return OK;
  }

  Processor::Result DQOccupancyByTrigger::Event(DS::Entry&, DS::EV& ev){

    // Skip pedestal triggered events
    if(ev.GetTrigType() & DU::TrigBits::GetMask("Pedestal")){
      return OK;
    }

    const RAT::DS::UncalPMTs& PMTs = ev.GetUncalPMTs();

    for(size_t iPMT = 0; iPMT < PMTs.GetAllCount(); iPMT++){

      const RAT::DS::PMTUncal& pmt = PMTs.GetAllPMT(iPMT);
      int pmtid = pmt.GetID();

      // Flagged as offline in begin of run
      if(fTrigOccupancy[0][pmtid] == -1)
        continue;

      // Check whether the trigger is in the trigger word, and if so
      // increment the occupancy for each online channel. Keep track
      // of the total number of triggers
      for(int i = 0; i < fNTrig; i++){
        int index = fTriggers[i];
        if((1<<index) & ev.GetTrigType()){
          fTrigOccupancy[i][pmtid]++;
          fTrigCount[i]++;
        }
      }
    }
    return OK;
  }

  void DQOccupancyByTrigger::EndOfRun(DS::Run& run){

    RAT::DBTable fDB("OCCUPANCY_BY_TRIGGER");
    fDB.SetI("version", 1);
    fDB.SetIndex("");
    fDB.SetPassNumber(-1);
    fDB.SetRunRange(run.GetRunID(), run.GetRunID());
    char name[64];
    for(int i = 0; i < fNTrig; i++){
      int index = fTriggers[i];
      sprintf(name, "trigger_%d", index);
      fDB.SetIArray(name, fTrigOccupancy[i]);
      sprintf(name, "trigger_norm_%d", index);
      fDB.SetI(name, fTrigCount[i]);
      fTrigOccupancy[i].clear();
    }
    fDB.SaveAs("OccupancyByTrigger.ratdb");
    fTrigCount.clear();

  }

}