#include "hhistconverter.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TH3D.h"
#include <iostream>
#include <iomanip>
using namespace std;
ClassImp(HHistConverter)
HHistConverter::HHistConverter()
{
}
HHistConverter::~HHistConverter()
{
}
void HHistConverter::printArray(const TArray& dat,Int_t nvals,Int_t width,Int_t start,Int_t end)
{
    
    
    Int_t size = dat.GetSize();
    if(start < 0 || start+1 >= size || start >= end   ) start = 0;
    if(end   < 0 || end+1   >= size || end   <= start ) end   = size;
    cout<<"        "<<flush;
    Int_t ct = 1;
    Int_t n  = end - start;
    for(Int_t i = start+1; i < end+1; i ++){
	if (ct%nvals == 0 && ct > 1 && ct != n )  { 
	    cout<<setw(width)<<dat.GetAt(i-1)<<" \\ "<<endl;
	    cout<<"        "<<flush;
	}
	else if  (ct == n )  cout<<setw(width)<<dat.GetAt(i-1)<<flush;         
	else                 cout<<setw(width)<<dat.GetAt(i-1)<<" "<<flush;   
	ct++;
    }
    cout<<endl;
}
void HHistConverter::writeArray(ostream& out,TString name,const TArray& dat,Int_t nvals)
{
    
    
    
    Int_t maxbin = dat.GetSize();
    out<<name.Data()<<": Double_t \\"<<endl;
    out<<"        "<<flush;
    for(Int_t i = 1; i < maxbin+1; i ++){
	if ( (i%(nvals) == 0) && i > 1 && i != maxbin )  {   
	    out<<dat.GetAt(i-1)<<" \\ "<<endl;
	    out<<"        "<<flush;
	}
	else if                          (i == maxbin )  {out<<dat.GetAt(i-1)<<flush; }        
	else                                             {out<<dat.GetAt(i-1)<<" "<<flush; }  
    }
    out<<endl;
}
void HHistConverter::printArrayInfo(const TArrayD& linData,TString name,Int_t nvals,Int_t width)
{
    
    
    
    
    Int_t dim  = (Int_t)linData[0];    
    Int_t xbin = (Int_t)linData[1];    
    Int_t ybin = (Int_t)linData[2];    
    Int_t zbin = (Int_t)linData[3];    
    Int_t offsetData = 0;
    Int_t offsetx    = 4;
    Int_t offsety    = offsetx + (xbin + 1);
    Int_t offsetz    = offsety + (ybin + 1);
    Int_t maxbin = 0;
    if(dim == 1) { maxbin = xbin;               offsetData = offsetx + (xbin + 1);}
    if(dim == 2) { maxbin = xbin * ybin;        offsetData = offsety + (ybin + 1);}
    if(dim == 3) { maxbin = xbin * ybin * zbin; offsetData = offsetz + (zbin + 1);}
    cout<<"---------------------------------------------------------------"<<endl;
    if(dim == 1) cout<<"info : "<<name.Data()<<", nBin = "<<xbin  <<endl;
    if(dim == 2) cout<<"info : "<<name.Data()
	<<", nBin = "<<maxbin
	    <<", nx = "  <<xbin
	    <<", ny = "  <<ybin<<", stored linear : ind = x * ybin + y"<<endl;
    if(dim == 3) cout<<"info : "<<name.Data()
	<<", nBin = "<<maxbin
	    <<", nx = "  <<xbin
	    <<", ny = "  <<ybin
	    <<", nz = "  <<zbin<<", stored linear : ind = x * (ybin*zbin) + y*zbin + z"<<endl;
    if(dim > 0){
	cout<<"x axis : "<<endl;
	printArray(linData,nvals,width,offsetx,offsetx + xbin + 1);
    }
    if(dim > 1) {
	cout<<"y axis : "<<endl;
	printArray(linData,nvals,width,offsety,offsety + ybin + 1);
    }
    if(dim == 3) {
	cout<<"z axis : "<<endl;
	printArray(linData,nvals,width,offsetz,offsetz + zbin + 1);
    }
    cout<<"data : "<<endl;
    printArray(linData,nvals,width,offsetData,offsetData + maxbin);
}
TH1* HHistConverter::createHist(TString name,const TArrayD& linData)
{
    
    
    TH1* h = 0;
    TArrayD& linDat = (TArrayD&)linData;
    Int_t dim  = (Int_t)linData[0];    
    Int_t xbin = (Int_t)linData[1];    
    Int_t ybin = (Int_t)linData[2];    
    Int_t zbin = (Int_t)linData[3];    
    Int_t offsetData = 0;
    Int_t offsetx    = 4;
    Int_t offsety    = offsetx + (xbin + 1);
    Int_t offsetz    = offsety + (ybin + 1);
    if(dim == 1) { offsetData = offsetx + (xbin + 1);}
    if(dim == 2) { offsetData = offsety + (ybin + 1);}
    if(dim == 3) { offsetData = offsetz + (zbin + 1);}
    if     (dim == 1){
	h = (TH1*) new TH1D(name.Data(),name.Data(),xbin,&linDat[offsetx]);
	for(Int_t i = 0; i < xbin; i ++){
	    h->SetBinContent(i+1,linData.At(offsetData + i));
	}
    } else if(dim == 2) {
	h = (TH1*) new TH2D(name.Data(),name.Data()
			    ,xbin,&linDat[offsetx]
			    ,ybin,&linDat[offsety]
			   );
	Int_t ind;
	for(Int_t i = 0; i < xbin; i ++){
	    for(Int_t j = 0; j < ybin; j ++){
		ind = i * ybin + j;
		h->SetBinContent(i+1,j+1,linData.At(offsetData + ind) );
	    }
	}
    } else if(dim == 3) {
	Int_t ind;
	h = (TH1*) new TH3D(name.Data(),name.Data()
			    ,xbin,&linDat[offsetx]
			    ,ybin,&linDat[offsety]
			    ,zbin,&linDat[offsetz]
			   );
	for(Int_t i = 0; i < xbin; i ++){
	    for(Int_t j = 0; j < ybin; j ++){
		for(Int_t k = 0; k < zbin; k ++){
		    ind = i * ybin*zbin + j*ybin + j;
		    h->SetBinContent(i+1,j+1,k+1,linData.At(offsetData + ind) );
		}
	    }
	}
    }
    h->SetDirectory(0);
    return h;
}
void    HHistConverter::fillArray(const TH1* h,TArrayD& linData,TString name,Int_t nvals,Int_t width, Bool_t print)
{
    
    
    
    
    Int_t dim  = h->GetDimension();
    Int_t xbin = h->GetNbinsX();
    Int_t ybin = h->GetNbinsY();
    Int_t zbin = h->GetNbinsZ();
    Int_t offsetData = 0;
    Int_t offsetx    = 4;
    Int_t offsety    = offsetx + (xbin + 1);
    Int_t offsetz    = offsety + (ybin + 1);
    Int_t maxbin = 0;
    if(dim == 1) { maxbin = xbin;               offsetData = offsetx + (xbin + 1); ybin = zbin = 0;}
    if(dim == 2) { maxbin = xbin * ybin;        offsetData = offsety + (ybin + 1); zbin = 0;}
    if(dim == 3) { maxbin = xbin * ybin * zbin; offsetData = offsetz + (zbin + 1);}
    linData.Set(offsetData + maxbin);
    linData[0] = dim;
    linData[1] = xbin;
    linData[2] = ybin;
    linData[3] = zbin;
    
    
    for(Int_t i = 0; i < xbin; i ++){
	linData.SetAt(h->GetXaxis()->GetBinLowEdge(i + 1),offsetx + i);
    }
    linData.SetAt(h->GetXaxis()->GetBinUpEdge(xbin),offsetx + xbin);
    if(dim >= 2){
	for(Int_t i = 0; i < ybin; i ++){
	    linData.SetAt(h->GetYaxis()->GetBinLowEdge(i + 1),offsety + i);
	}
	linData.SetAt(h->GetYaxis()->GetBinUpEdge(ybin),offsety + ybin);
    }
    if(dim == 3){
	for(Int_t i = 0; i < zbin; i ++){
	    linData.SetAt(h->GetZaxis()->GetBinLowEdge(i + 1),offsetz + i);
	}
	linData.SetAt(h->GetZaxis()->GetBinUpEdge(zbin),offsetz + zbin);
    }
    
    
    if(dim == 1){
	for(Int_t i = 0; i < xbin; i ++){
	    linData.SetAt(h->GetBinContent(i + 1),offsetData + i);
	}
    } else if (dim == 2){
	Int_t ind;
	for(Int_t i = 0; i < xbin; i ++){
	    for(Int_t j = 0; j < ybin; j ++){
		ind = i * ybin + j;
		linData.SetAt(h->GetBinContent(i + 1,j + 1),offsetData + ind);
	    }
	}
    } else if (dim == 3){
	Int_t ind;
	for(Int_t i = 0; i < xbin; i ++){
	    for(Int_t j = 0; j < ybin; j ++){
		for(Int_t k = 0; k < zbin; k ++){
		    ind = i * ybin * zbin + j * ybin + k;
		    linData.SetAt(h->GetBinContent(i + 1,j + 1,k + 1),offsetData + ind);
		}
	    }
	}
    }
    if(print){
	printArrayInfo(linData,name,nvals,width);
    }
}