//************************************************
// Author: Federica Lionetto, Adam Davis, Biplab Dey, Paolo Gandini
// Created on: 30/07/2014
//************************************************

/*
IMPORTANT

I cannot display std::vector<double> PedByGain, std::vector<double> NoiseByGain, and  std::vector<double> Gain in the ROOT file that is created by TbNtupleMaker.
Further investigation is needed in order to understand if the format is fine or not.
*/



/*
TbNtupleMaker reads an Alibava file and creates a ROOT file (same filename) with the following information:
- int NEvents, the number of events read from the header of the Alibava file;
- int RunType, the run type;
- std::vector<double> PedByGain, the pedestals calculated by the Alibava;
- std::vector<double> NoiseByGain, the noise calculated by the Alibava;
- std::vector<double> Gain, the gain calculated by the Alibava;
- TH1F histo_PedByGain("histo_PedByGain","histo_PedByGain",N,0,N-1);
- TH1F histo_NoiseByGain("histo_NoiseByGain","histo_NoiseByGain",N,0,N-1);
- TH1F histo_Gain("histo_Gain","histo_Gain",N,0,N-1);
- string Date, the date read from the header of the Alibava file;
- std::vector<unsigned short> ADC, the raw ADC counts, one per event;
- double TDCTime, the TDC time (meaningful only in radioactive source runs), one per event;
- double Temp, the temperature, one per event;
- int n, a counter, one per event (starting from 1).

The ROOT file will be saved in a folder named RootFiles in the same folder where the Alibava file is (if no external path is provided) or in the folder specified by the external path.

Compile with:

make

Run with:

./TbNtupleMaker [Alibava file] [external path]

where:
- [Alibava file] is the complete path, including the folder and the filename, of the Alibava file one wants to process;
- [external path] is the optional external path where the RootFiles folder will be created.

For example:

./TbNtupleMaker /.../run_xxxxxx_xxxx_xxxx.ali

or

./TbNtupleMaker /.../run_xxxxxx_xxxx_xxxx.ali /...
*/

//************************************************
// Run types:
// 1 = calibration run
// 2 = laser synchronization run
// 3 = laser run
// 4 = radioactive source run
// 5 = pedestal run
//************************************************

#include <iostream>
#include <string>

#include <vector>

#include <cstdlib>

#include "TFile.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TTree.h"

#include "Alibava/AsciiRoot.h"

#ifdef __MAKECINT__
#pragma link C++ class vector<float>+;
#endif

using namespace std;

// Number of Beetle channels.
const int N = 256;

void TbNtupleMaker(char *filename, char *externalPath = 0);

int main(int argc, char *argv[])
{
  if(argc < 2)
  {
    cout << "**************************************************" << endl;

    cout << "Error! Input file missing..." << endl;
    cout << "Please use the following format:" << endl;
    cout << "./TbNtupleMaker [1] [2]" << endl;
    cout << "with:" << endl;
    cout << "[1] = Alibava file, complete path;" << endl;
    cout << "[2] = External path, optional." << endl;
    cout << "Type ./TbNtupleMaker --info for more information." << endl;

    cout << "**************************************************" << endl;
    
    return 0;
  }
  else if (string(argv[1]) == "--info") 
  {
    cout << "**************************************************" << endl;

    cout << "TbNtupleMaker reads an Alibava file and creates a ROOT file (same filename) with the following information:" << endl;
    cout << "- int NEvents, the number of events read from the header of the Alibava file;" << endl;
    cout << "- int RunType, the run type;" << endl;
    cout << "- std::vector<double> PedByGain, the pedestals calculated by the Alibava;" << endl;
    cout << "- std::vector<double> NoiseByGain, the noise calculated by the Alibava;" << endl;
    cout << "- std::vector<double> Gain, the gain calculated by the Alibava;" << endl;
    cout << "- TH1F histo_PedByGain;" << endl;
    cout << "- TH1F histo_NoiseByGain;" << endl;
    cout << "- TH1F histo_Gain;" << endl;
    cout << "- string Date, the date read from the header of the Alibava file;" << endl;
    cout << "- std::vector<unsigned short> ADC, the raw ADC counts, one per event;" << endl;
    cout << "- double TDCTime, the TDC time (meaningful only in radioactive source runs), one per event;" << endl;
    cout << "- double Temp, the temperature, one per event;" << endl;
    cout << "- int n, a counter, one per event (starting from 1)." << endl;

    cout << "**************************************************" << endl;

    cout << "The ROOT file will be saved in a folder named RootFiles in the same folder where the Alibava file is (if no external path is provided) or in the folder specified by the external path." << endl;
    
    cout << "**************************************************" << endl;

    cout << "Compile with:" << endl;
    cout << "make" << endl;
    cout << "Run with:" << endl;
    cout << "./TbNtupleMaker [Alibava file] [external path]" << endl;
    cout << "where:" << endl;
    cout << "- [Alibava file] is the complete path, including the folder and the filename, of the Alibava file one wants to process;" << endl;
    cout << "- [external path] is the optional external path where the RootFiles folder will be created." << endl;
    cout << "For example:" << endl;
    cout << "./TbNtupleMaker /.../run_xxxxxx_xxxx_xxxx.ali" << endl;
    cout << "or" << endl;
    cout << "./TbNtupleMaker /.../run_xxxxxx_xxxx_xxxx.ali /..." << endl;   

    cout << "**************************************************" << endl;
    
    return 0;
  }
  else
  {
    cout << "File to process: " << argv[1] << endl;
    if (argc == 2)
      TbNtupleMaker(argv[1]);
    else if (argc == 3)
      TbNtupleMaker(argv[1],argv[2]);
    else
    {
      cout << "Error! Too many arguments given..." << endl;

      return 0;
    }
    
    return 0; 
  }
}



void TbNtupleMaker(char *filename, char *externalPath){
  cout << "**************************************************" << endl;
  cout << "Decoding raw data..." << endl;
  cout << "**************************************************" << endl;
 
  // Do not comment this line.
  gROOT->ProcessLine("#include <vector>");

  // Do some fanciness to get the directory right.
  string filename_as_string = string(filename);
  string prefix = filename_as_string.substr(0,filename_as_string.find_last_of('/'));
  if (externalPath!=0)
    prefix = string(externalPath);
  string ali_filename = filename_as_string.substr(filename_as_string.find_last_of('/')+1);
  TString outfilename = ((TString)prefix)+"/RootFiles/"+((TString)ali_filename);
  outfilename.ReplaceAll(".ali",".root");
  
  // Create a folder named RootFiles. Do not worry, nothing bad is going to happen if the folder already exists.
  cout << "Create a folder named RootFiles" << endl;
  cout << "Setting output to: " << prefix+"/RootFiles" << endl;
  string path_to_make = "mkdir "+prefix+"/RootFiles";
  system(path_to_make.c_str()); 

  // Open ROOT file.
  TFile *output = TFile::Open(outfilename,"RECREATE");
  
  // Open Alibava file.
  AsciiRoot *a = new AsciiRoot(filename);

  // Create tree structure in ROOT file, to be filled once per file.
  int NEvents;
  int RunType;
  std::vector<double> PedByGain;
  std::vector<double> NoiseByGain;
  std::vector<double> Gain;
  TH1F histo_PedByGain("histo_PedByGain","histo_PedByGain",N,0,N);
  TH1F histo_NoiseByGain("histo_NoiseByGain","histo_NoiseByGain",N,0,N);
  TH1F histo_Gain("histo_Gain","histo_Gain",N,0,N);
  string Date;

  // Allocate only necessary space.
  PedByGain.reserve(N);
  NoiseByGain.reserve(N);
  Gain.reserve(N);

  // Create tree structure in ROOT file, to be filled once per event.
  std::vector<unsigned short> ADC;
  double TDCTime;
  double Temp;
  int n;

  // Fill the header, once per file.
  TTree *Header = new TTree("Header","Header");

  Header->Branch("NEvents",&NEvents);
  Header->Branch("RunType",&RunType);
  Header->Branch("PedByGain",&PedByGain);
  Header->Branch("NoiseByGain",&NoiseByGain);
  Header->Branch("Gain",&Gain);
  Header->Branch("Date",&Date);

  NEvents = a->get_nevents();
  cout << "Number of events in the Alibava file: " << NEvents << endl;

  RunType = a->type();
  cout << "Run type of the Alibava file: " << RunType << endl;

  for(int iChannel=0; iChannel<N;++iChannel)
  {
    PedByGain[iChannel]=a->ped(iChannel);
    NoiseByGain[iChannel] = a->noise(iChannel);
    Gain[iChannel]= a->get_gain(iChannel);
    histo_PedByGain.SetBinContent(iChannel+1,a->ped(iChannel));
    histo_NoiseByGain.SetBinContent(iChannel+1,a->noise(iChannel));
    histo_Gain.SetBinContent(iChannel+1,a->get_gain(iChannel));
  }

  Date = a->date();
  cout << "Date of the Alibava file: " << Date << endl;

  Header->Fill();

  cout << "Information in the header:" << endl;
  Header->Print();
  
  // Fill the data, once per event.
  TTree *EventInfo = new TTree("EventInfo","EventInfo");  
  EventInfo->Branch("ADC",&ADC);
  EventInfo->Branch("TDCTime",&TDCTime); 
  EventInfo->Branch("Temp",&Temp);
  EventInfo->Branch("n",&n);
 
  // Loop over events.
  for (int iEvent=0; iEvent<NEvents; iEvent++)
  {
    ADC.clear();
    a->read_event();

    // Loop over Beetle channels.
    for (int jChannel=0; jChannel<N; jChannel++)
      ADC.push_back(a->data(jChannel));

    TDCTime =a->time();
    Temp = a->temp();
    n = iEvent+1;
    EventInfo->Fill();
  }

  cout << "Information in the data: " << endl;
  EventInfo->Print();

  // Close Alibava file.
  a->close();

  // Write ROOT file.
  output->Write();

  // Close ROOT file.
  output->Close();

  return;
}
