#include "hitutils.h"
#include <string>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <utility>
#include <TH2.h>
#include <TF1.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TFile.h>
#include <TTree.h>
#include <TSystemDirectory.h>
#include <gsl/gsl_statistics.h>
#include <math.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_fft_complex.h>
#include <TF1.h>
#include <TGraphErrors.h>
#include <gsl/gsl_sort.h>
#include <TVector.h>
#include "TStopwatch.h"
#include "Math/MinimizerOptions.h"
#include "TVirtualFitter.h"
#include "TMatrixD.h"

Double_t S[128], T[128], SumT, SumS, SumS2, SumST, SumT2, SumY, SumYS, SumYT, sigmaABC, muABC,p,c, b, b_den, b_num, SumYYP, SumYYM, MeanY;
TMatrixD M1(3,3);
TMatrixD M1inv(3,3);
TVectorD ABC(3);
TVectorD M2(3);
Double_t M1elements_b0[9] = {0.};
Double_t M1elements_b1[9] = {0.};
Double_t M1elements_b2[9] = {0.};
Double_t M1elements_b3[9] = {0.};

TMatrixD matrix(2,2);
TMatrixD *M1pointer = &M1;
TVectorD *M2pointer = &M2;
TVectorD *ABCpointer = &ABC;


int eventID = 0;
int framestart=0;
int frameend = 0;
double board_b0_ch[128];
double board_b1_ch[128];
double board_b2_ch[128];
double board_b3_ch[128];
double board_b0_ch_bkg[128];
double board_b1_ch_bkg[128];
double board_b2_ch_bkg[128];
double board_b3_ch_bkg[128];
double signal_b0 = 0.;
double signal_b1 = 0.;
double signal_b2 = 0.;
double signal_b3 = 0.;

double signal_cor_b0 = 0.;
double signal_cor_b1 = 0.;
double signal_cor_b2 = 0.;
double signal_cor_b3 = 0.;

double signal_b0_left = 0.;
double signal_b1_left = 0.;
double signal_b2_left = 0.;
double signal_b3_left = 0.;

double signal_b0_right = 0.;
double signal_b1_right = 0.;
double signal_b2_right = 0.;
double signal_b3_right = 0.;

double signal_gsl_b0[128];
double signal_gsl_b1[128];
double signal_gsl_b2[128];
double signal_gsl_b3[128];
double signal_reg[128];


double channellist_gsl_b0[128];
double channellist_gsl_b1[128];
double channellist_gsl_b2[128];
double channellist_gsl_b3[128];
double channellist[128];
double channellist_reg[128];


double pos[128];

double maxchannelamp_b0 =0.;
double maxchannelamp_b1 =0.;
double maxchannelamp_b2 =0.;
double maxchannelamp_b3 =0.;
int maxchannel_b0 =0;
int maxchannel_b1 =0;
int maxchannel_b2 =0;
int maxchannel_b3 =0;
int numtocalc_b0 =0;
int numtocalc_b1 =0;
int numtocalc_b2 =0;
int numtocalc_b3 =0;
int numtocalc_reg =0;

int nfwhm_b0 = 0;
int nfwhm_b1 = 0;
int nfwhm_b2 = 0;
int nfwhm_b3 = 0;

double	beamPosX_b0,beamPosX_b1,beamPosX_b2,beamPosX_b3;
double	beamFocusX_b0,beamFocusX_b1,beamFocusX_b2,beamFocusX_b3;
double	beamPosX_fit_b0,beamPosX_fit_b1,beamPosX_fit_b2,beamPosX_fit_b3;
double	beamFocusX_fit_b0,beamFocusX_fit_b1,beamFocusX_fit_b2,beamFocusX_fit_b3; 
double	beamSkewX_b0,beamSkewX_b1,beamSkewX_b2,beamSkewX_b3;
double	beamKurtX_b0,beamKurtX_b1,beamKurtX_b2,beamKurtX_b3; 
int	beamNumX_b0,beamNumX_b1,beamNumX_b2,beamNumX_b3;
double	beamRsqr_b0,beamRsqr_b1,beamRsqr_b2,beamRsqr_b3;
double	beamChi2_fit_b0,beamChi2_fit_b1,beamChi2_fit_b2,beamChi2_fit_b3;

double	beamPosX_reg_b0,beamPosX_reg_b1,beamPosX_reg_b2,beamPosX_reg_b3;
double	beamFocusX_reg_b0,beamFocusX_reg_b1,beamFocusX_reg_b2,beamFocusX_reg_b3; 
double	beamPeakX_reg_b0,beamPeakX_reg_b1,beamPeakX_reg_b2,beamPeakX_reg_b3;

double beamSidebandNoise_b0, beamSidebandNoise_b1, beamSidebandNoise_b2, beamSidebandNoise_b3 ;
int sidenumtocalc_b0,sidenumtocalc_b1,sidenumtocalc_b2,sidenumtocalc_b3;
size_t size = 5;

const int length = 100; //length of the rolling average
double array_b0[length] = {0.};
double array_b1[length] = {0.};
double array_b2[length] = {0.};
double array_b3[length] = {0.};

double arrayavg_b0 = 0.;
double arrayavg_b1 = 0.;
double arrayavg_b2 = 0.;
double arrayavg_b3 = 0.;


bool graphsaved_b0 = false;
bool graphsaved_b1 = false;
bool graphsaved_b2 = false;
bool graphsaved_b3 = false;

TVector beamontime(0,3,0.,0.,0.,0.,"END");
TVector * beamontime_ptr = &beamontime;

double calibration_b0[128] = {0.};
double calibration_b1[128] = {0.};
double calibration_b2[128] = {0.};
double calibration_b3[128] = {0.};

TF1 * gausfunc_b0 = new TF1("gausfunc_b0","gaus(0)+[3]");
TF1 * gausfunc_b1 = new TF1("gausfunc_b1","gaus(0)+[3]");



TGraphErrors * gausgraph_b0;
TGraphErrors * gausgraph_b1;
Int_t lastfit_b0 = 0;
Int_t lastfit_b1 = 0;
double errorx[128];
double errory[128];

bool samplenoise = false;
bool beam_off = true;
bool beam_wason = false;
int beamoffcounter = 0;
int beamoncounter = 0;

Double_t mybeta = 0.;
Double_t lorentz_gamma = 0.;
Double_t zsqr = 0.;
Double_t sp_air = 0.;
Double_t sp_ps = 0.;
Double_t sp2_air = 0.;
Double_t sp2_ps = 0.;
Double_t intcorr = 1.;

Double_t x, q, median;

Double_t signaloffset_b0[30];
Double_t signaloffset_b1[30];
Double_t signaloffset_b2[30];
Double_t signaloffset_b3[30];



TF1 * f_sp_air = new TF1("f_sp_air","[0]*pow(x,[1])+[2]", 50, 250); //stopping power of protons in Air [MeV cm2 /g]
TF1 * f_sp_ps = new TF1("f_sp_ps","[0]*pow(x,[1])+[2]", 50, 250); //stopping power of protons in polystyrene [MeV cm2 /g]
TF1 * f_h2sp_air = new TF1("f_h2sp_air","[0]*pow(x,[1])+[2]", 50, 250); //stopping power of helium in air [MeV cm2 /g]
TF1 * f_h2sp_ps = new TF1("f_h2sp_ps","[0]*pow(x,[1])+[2]", 50, 250); //stopping power of helium in polystyrene [MeV cm2 /g]
TF1 * f_c12sp_air = new TF1("f_c12sp_air","[0]*pow(x,[1])+[2]", 80, 480); //stopping power of carbon in air [MeV cm2 /g]
TF1 * f_c12sp_ps = new TF1("f_c12sp_ps","[0]*pow(x,[1])+[2]", 80, 480); //stopping power of carbon in polystyrene [MeV cm2 /g]
TF1 * f_o16sp_air = new TF1("f_o16sp_air","[0]*pow(x,[1])+[2]", 80, 480); //stopping power of oxygen in air [MeV cm2 /g]
TF1 * f_o16sp_ps = new TF1("f_o16sp_ps","[0]*pow(x,[1])+[2]", 80,480); //stopping power of oxygen in polystyrene [MeV cm2 /g]
/////       ic1/SP intensity correction factor = 19.8E6+/-0.1E6 particles/s per nA/(Mevcm2/g)


bool smooth_on;
bool doFit;
bool doLinInt;
bool ethercat;
char * ethercatfile;
char * filename;
char * offsetfilename;
char * timestampfilename ;
char * rootfilename ;
ifstream file;
ifstream timestampfile;
ifstream offsetfile;
int board_b;
long int  fileframesize;
BufferData* dataptr;
TFile *rootFile;

TH2D * th2_signal_vs_channel_b0;
TH2D * th2_signal_vs_channel_b1;
TH2D * th2_signal_vs_channel_b2;
TH2D * th2_signal_vs_channel_b3 ;

TH2D * th2_signal_vs_channel_sub_b0;
TH2D * th2_signal_vs_channel_sub_b1;
TH2D * th2_signal_vs_channel_sub_b2;
TH2D * th2_signal_vs_channel_sub_b3;

TH1D * th1_signal_b0;
TH1D * th1_signal_b1;
TH1D * th1_signal_b2;
TH1D * th1_signal_b3;

TH1D * h_regresidual_b0;
TH1D * h_regresidual_b1;
TH1D * h_regresidual_b2;
TH1D * h_regresidual_b3;

TGraph * graph_bkg_b0;
TGraph * graph_bkg_b1;
TGraph * graph_bkg_b2;
TGraph * graph_bkg_b3;

TGraph * gr_b0; TGraph * gr_b1; TGraph * gr_b2; TGraph * gr_b3;
TGraph * gr_sm_b0; TGraph * gr_sm_b1; TGraph * gr_sm_b2; TGraph * gr_sm_b3;

TH2D * th2_signal_vs_channel_bkg_b0;
TH2D * th2_signal_vs_channel_bkg_b1;
TH2D * th2_signal_vs_channel_bkg_b2;
TH2D * th2_signal_vs_channel_bkg_b3;

TH2D * th2_resid_vs_channel_bkg_b0;
TH2D * th2_resid_vs_channel_bkg_b1;
TH2D * th2_resid_vs_channel_bkg_b2;
TH2D * th2_resid_vs_channel_bkg_b3;
TH1D* h_beamSignal_b0[30];
TH1D* h_beamSignal_b1[30];
TH1D* h_beamSignal_b2[30];
TH1D* h_beamSignal_b3[30];

int energy_indexbin = 0;
char histname[30] = "";
TH1D* h_beamSignal_ic1[30];


TH1D* h_beamSignal_cor_b0[30];
TH1D* h_beamSignal_cor_b1[30];
TH1D* h_beamSignal_cor_b2[30];
TH1D* h_beamSignal_cor_b3[30];
Double_t beamSignal_cor_b0_mean[30];
Double_t beamSignal_cor_b1_mean[30];
Double_t beamSignal_cor_b2_mean[30];
Double_t beamSignal_cor_b3_mean[30];
Double_t mybeta_graph[30];

int goodevents_b0=0;
int goodevents_b1=0;
int goodevents_b2=0;
int goodevents_b3=0;

TTree *rootTree;

  int k = 0;
  // int count = 0;
  double ic1, ic2, mw1_focusx, mw1_focusy, mw2_focusx, mw2_focusy, mw1_posx, mw1_posy, mw2_posx, mw2_posy;
  double ic1_avg, ic2_avg, mw1_focusx_avg, mw1_focusy_avg, mw2_focusx_avg, mw2_focusy_avg, mw1_posx_avg, mw1_posy_avg, mw2_posx_avg, mw2_posy_avg;
      
  double analog_in1;
  double energy_index;
  double energy;
  double energy_list_p[27] = {48.12, 59.82, 70.03, 79.17, 87.53, 95.3, 102.61, 109.56, 116.2, 122.57, 128.72, 134.65, 140.41, 146.01, 151.5, 156.89, 162.21, 167.46, 172.62, 177.7, 184.81, 191.87, 198.76, 205.48, 212.06, 218.51, 0.};
  double energy_list_he[27] = {50.57, 61.86, 71.73, 80.64, 88.85, 96.52, 103.76, 110.64, 117.23, 123.55, 129.64, 135.55, 141.27, 146.84, 152.26, 157.56, 162.73, 167.8, 172.77, 177.64, 184.56, 191.54, 198.36, 205.03, 211.57, 217.98, 0.};
  double energy_list_c[27] = {88.83,110.58,129.79,147.13,163.09,178.01,192.13,205.6,218.52,230.98,243.03,254.71,266.08,277.19,288.1,298.87,309.52,320.07,330.48,340.77,355.22,369.64,383.78,397.66,411.32,424.77,0.};
  double energy_list_o[27] = {103.77, 129.65, 152.42, 172.98, 191.96, 209.63, 226.53, 242.58, 258.11, 273.04, 287.5, 301.55, 315.32, 328.61, 341.84, 354.88, 367.94, 380.48, 393.09, 405.65, 423.23, 440.82, 458.11, 475.28, 491.93, 508.38, 0.};
  double intensity_index;
  double intensity;
  double intensity_list_p[16] = {0., 8.00E+07, 1.20E+08, 2.00E+08, 3.20E+08,4.00E+08, 6.00E+08, 8.00E+08, 1.20E+09, 2.00E+09, 3.20E+09, 4.00E+09, 6.00E+09, 8.00E+09, 1.20E+10, 2.00E+10};
  double intensity_list_he[16] = { 0.,  2.00E+07, 3.00E+07, 5.00E+07, 8.00E+07, 1.00E+08, 1.50E+08, 2.00E+08, 3.00E+08, 5.00E+08, 8.00E+08, 1.00E+09, 1.50E+09, 2.00E+09, 3.00E+09, 5.00E+09};

  double intensity_list_c[16] = {0.,2.00E+06, 3.00E+06, 5.00E+06, 8.00E+06, 1.00E+07, 1.50E+07, 2.00E+07, 3.00E+07, 5.00E+07, 8.00E+07, 1.00E+08, 1.50E+08, 2.00E+08, 3.00E+08, 5.00E+08};
  double intensity_list_o[16] = {0., 1.00E+06, 1.50E+06, 2.50E+06, 4.00E+06, 5.00E+06, 8.00E+06, 1.00E+07, 1.50E+07, 2.50E+07, 4.00E+07, 5.00E+07, 8.00E+07, 1.00E+08, 1.50E+08, 2.50E+08 };
  double ionsort;

  double rel_time2,time2;

  double timeoffset;
  int mwoffset;
  double timewindow;
  double timeoffset2;
  double timewindow2;
