#include <string.h>
#include <string>
#include <TFile.h>
#include <TTree.h>
#include <map>
#include <fstream>
#include <TSystemDirectory.h>
#include <iostream>

using namespace std;

void csvToRoot(TString filename)
{
}
Int_t main(Int_t argc, const char *argv[])
{
  double timeoffset;
  if (argc>2){
    timeoffset  = atof(argv[2]);
    printf("Time offset: %f\n", timeoffset);
  }
  else {
    timeoffset = 0.09;
    printf("Default time offset:%f\n", timeoffset);

  }
  
    const char *dbasename = "/work/leverington/beamprofilemonitor/hitdata/HIT_26-11-2016/database.csv";
    const char *dirname = "/work/leverington/beamprofilemonitor/hitdata/HIT_26-11-2016/with_timestamp/csv/";
    const char *outputdirname = "/work/leverington/beamprofilemonitor/hitdata/HIT_26-11-2016/with_timestamp/pin/";
    const char *dirCsv = "/work/leverington/beamprofilemonitor/hitdata/HIT_26-11-2016/hit_csv/with_timestamp/";
    const char *ext = ".csv";

    //read database
    string key, value;
    ifstream infile(dbasename, ios::in);
    map<string, string> database;
    while (infile >> key >> value)
    {
	database[key] = value;
	//	cout << value << endl;
    }

    TSystemDirectory dir(dirname, dirname);
    if (true)
    {
	TSystemFile *file;
	TString fname = argv[1];
	    if (fname.EndsWith(ext))
	    {

		TTree *tree = new TTree("t", "t");
		cout << fname << endl;
		//tree->ReadFile(TString(TString(dirname) + file->GetName()), "time/D:event_id:sync_out:sync_in:data_ok:led_voltage:current:ch00:ch01:ch02:ch03:ch04:ch05:ch06:ch07:ch08:ch09:ch10:ch11:ch12:ch13:ch14:ch15:ch16:ch17:ch18:ch19:ch20:ch21:ch22:ch23:ch24:ch25:ch26:ch27:ch28:ch29:ch30:ch31:ch32:ch33:ch34:ch35:ch36:ch37:ch38:ch39:ch40:ch41:ch42:ch43:ch44:ch45:ch46:ch47:ch48:ch49:ch50:ch51:ch52:ch53:ch54:ch55:ch56:ch57:ch58:ch59:ch60:ch61:ch62:ch63:ch64:ch65:ch66:ch67:ch68:ch69:ch70:ch71:ch72:ch73:ch74:ch75:ch76:ch77:ch78:ch79:ch80:ch81:ch82:ch83:ch84:ch85:ch86:ch87:ch88:ch89:ch90:ch91:ch92:ch93:ch94:ch95:ch96:ch97:ch98:ch99:ch100:ch101:ch102:ch103:ch104:ch105:ch106:ch107:ch108:ch109:ch110:ch111:ch112:ch113:ch114:ch115:ch116:ch117:ch118:ch119:ch120:ch121:ch122:ch123:ch124:ch125:ch126:ch127", '\t');
		tree->ReadFile(TString(TString(dirname) + fname.Data()), "time/D:event_id:sync_out:sync_in:data_ok:led_voltage:current:ch00:ch01:ch02:ch03:ch04:ch05:ch06:ch07:ch08:ch09:ch10:ch11:ch12:ch13:ch14:ch15:ch16:ch17:ch18:ch19:ch20:ch21:ch22:ch23:ch24:ch25:ch26:ch27:ch28:ch29:ch30:ch31:ch32:ch33:ch34:ch35:ch36:ch37:ch38:ch39:ch40:ch41:ch42:ch43:ch44:ch45:ch46:ch47:ch48:ch49:ch50:ch51:ch52:ch53:ch54:ch55:ch56:ch57:ch58:ch59:ch60:ch61:ch62:ch63", '\t');
		TString outname = TString(outputdirname) + fname ;
		outname.Replace(outname.Length() - 4, 4, TString(TString(argv[2])+".root"));
		TFile *outfile = new TFile(outname.Data(), "recreate");
		outfile->cd();
		//outfile = tree->GetCurrentFile();

		TTree *tree2 = new TTree("t2", "t2");

		fname.Replace(fname.Length() - 3, 3, TString("root"));
		string key = string(fname.Data());
		key.erase(key.end() - 5, key.end());
		if(database[key] == "nothing"){
		  outfile->Close();
		  return 1;
		}
		printf("%s\n", database[key].c_str());
		string value = string(dirCsv) + database[key] + ".csv";
		printf("name1: %s , name2: %s\n", key.data(), value.data());

		tree2->ReadFile(value.data(), "TIME2/D:IC1:IC2:MW1_FOCUSX:MW1_FOCUSY:MW2_FOCUSX:MW2_FOCUSY:MW1_POSX:MW1_POSY:MW2_POSX:MW2_POSY:TCS-SPAM:TCS-KO:BNEXTPOINT:ANALOG_IN1:ANALOG_IN2:ENERGY:INTENSITY:ION-SORT", '\t');

		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 time;
		double time2;

		tree->SetBranchAddress("time", &time);

		tree2->SetBranchAddress("TIME2", &time2);
		tree2->SetBranchAddress("IC1", &ic1);
		tree2->SetBranchAddress("IC2", &ic2);
		tree2->SetBranchAddress("MW1_FOCUSX", &mw1_focusx);
		tree2->SetBranchAddress("MW1_FOCUSY", &mw1_focusy);
		tree2->SetBranchAddress("MW2_FOCUSX", &mw2_focusx);
		tree2->SetBranchAddress("MW2_FOCUSY", &mw2_focusy);
		tree2->SetBranchAddress("MW1_POSX", &mw1_posx);
		tree2->SetBranchAddress("MW1_POSY", &mw1_posy);
		tree2->SetBranchAddress("MW2_POSX", &mw2_posx);
		tree2->SetBranchAddress("MW2_POSY", &mw2_posy);

		TBranch *bic1 = tree->Branch("ic1", &ic1_avg, "ic1/D");
		TBranch *bic2 = tree->Branch("ic2", &ic2_avg, "ic2/D");
		TBranch *bmw1_focusx = tree->Branch("mw1_focusx", &mw1_focusx_avg, "mw1_focusx/D");
		TBranch *bmw1_focusy = tree->Branch("mw1_focusy", &mw1_focusy_avg, "mw1_focusy/D");
		TBranch *bmw2_focusx = tree->Branch("mw2_focusx", &mw2_focusx_avg, "mw2_focusx/D");
		TBranch *bmw2_focusy = tree->Branch("mw2_focusy", &mw2_focusy_avg, "mw2_focusy/D");
		TBranch *bmw1_posx = tree->Branch("mw1_posx", &mw1_posx_avg, "mw1_posx/D");
		TBranch *bmw1_posy = tree->Branch("mw1_posy", &mw1_posy_avg, "mw1_posy/D");
		TBranch *bmw2_posx = tree->Branch("mw2_posx", &mw2_posx_avg, "mw2_posx/D");
		TBranch *bmw2_posy = tree->Branch("mw2_posy", &mw2_posy_avg, "mw2_posy/D");

		int currentEntryTree2 = 1;

		int nevents = tree->GetEntries();
		int nevents2 = tree2->GetEntries();
		ic1_avg = 0;
		ic2_avg = 0;
		mw1_focusx_avg = 0;
		mw1_focusy_avg = 0;
		mw2_focusx_avg = 0;
		mw2_focusy_avg = 0;
		mw1_posx_avg = 0;
		mw1_posy_avg = 0;
		mw2_posx_avg = 0;
		mw2_posy_avg = 0;
		time2 = 0;
		tree2->GetEntry(currentEntryTree2);

		for (int i = 0; i < nevents; i++)
		{

		    tree->GetEntry(i);

		    if (i % 10000 == 0)
		    {

			printf("merging event %d ,", i);
			printf("Time %f \n", time);
			printf("Entry hit %d ,", currentEntryTree2);
			printf("Time hit %f \n", time2);
		    }

		    int count = 0;
		    int count2 = 0;

		    while (time2 <= (time + timeoffset+0.312/2.) && currentEntryTree2 < nevents2)
		    {
		      if (abs(time2 - (time+timeoffset)) <= 0.300/2.)
			
			{
			  //   tree2->GetEntry(currentEntryTree2);

			    ic1_avg += ic1;
			    ic2_avg += ic2;
			    
			    count++;
			    //printf("%i  %2.3f  %2.3f\n", count, time, time2);
			    //}
		      //tree2->GetEntry(currentEntryTree2);

		      //if (abs(time2 - (time+timeoffset)) <= 0.300/2.)
			//{
			  tree2->GetEntry(currentEntryTree2 - 4); //why currentEtryTree2-4?
			    mw1_focusx_avg += mw1_focusx;
			    mw1_focusy_avg += mw1_focusy;
			    mw2_focusx_avg += mw2_focusx;
			    mw2_focusy_avg += mw2_focusy;
			    mw1_posx_avg += mw1_posx*ic1;
			    mw1_posy_avg += mw1_posy*ic1;
			    mw2_posx_avg += mw2_posx*ic2;
			    mw2_posy_avg += mw2_posy*ic2;
			    count2++;
			    //			    printf("%i  %2.3f  %2.3f  %2.3f  %2.3f\n", count2, time, time2, ic1, mw1_posx);
			}
		      currentEntryTree2++;
		      tree2->GetEntry(currentEntryTree2);
		      
		      //	currentEntryTree2++;
		    }
		    
		   
		   
		    mw1_focusx_avg /= count2;
		    mw1_focusy_avg /= count2;
		    mw2_focusx_avg /= count2;
		    mw2_focusy_avg /= count2;
		    mw1_posx_avg /= ic1_avg; //the positions are weighted by the charge
		    mw1_posy_avg /= ic1_avg;
		    mw2_posx_avg /= ic2_avg;
		    mw2_posy_avg /= ic2_avg;
		    ic1_avg /= count;
                    ic2_avg /= count;

		    bic1->Fill();
		    bic2->Fill();
		    bmw1_focusx->Fill();
		    bmw1_focusy->Fill();
		    bmw2_focusx->Fill();
		    bmw2_focusy->Fill();
		    bmw1_posx->Fill();
		    bmw1_posy->Fill();
		    bmw2_posx->Fill();
		    bmw2_posy->Fill();
		    ic1_avg = 0;
		    ic2_avg = 0;
		    mw1_focusx_avg = 0;
		    mw1_focusy_avg = 0;
		    mw2_focusx_avg = 0;
		    mw2_focusy_avg = 0;
		    mw1_posx_avg = 0;
		    mw1_posy_avg = 0;
		    mw2_posx_avg = 0;
		    mw2_posy_avg = 0;
		}

		tree->Write();
		outfile->Close();
	    }
    }
	
    
    return 0;
}
