/*
 *  TTextToVector.cpp
 *  TTextToVector
 *
 *  Created by Hugh Dickinson on 14/01/2008.
 *  Copyright 2008 Hugh Dickinson. All rights reserved.
 *
 */

#define DEBUG
#define DEBUG2
#include "TTextToVector.h"

// Constructor - takes the text file to be processed as an argument.
TTextToVector::TTextToVector(const char * inFile):
fFilename(new TString("cir_x1_1_dataf.qdp")),
fNumCols(0),
fNumRows(0)
{
std::ifstream * file = OpenFile(fFilename);
if(!CheckFile(file)){
	std::cerr << "Failed to open file \"" << fFilename->Data() << "\" for reading! Aborting." << std::endl;
	return;
	}
TObjArray * rowStrings = ReadFile(file);
fVectorOfRows = MakeRowVectors(rowStrings);
fVectorOfCols = MakeColumnVectors(fVectorOfRows);
std::cout << "The file \"" << fFilename->Data() << "\" has been processed." << std::endl;
}

TTextToVector::~TTextToVector(){
delete fFilename;
delete fVectorOfCols;
delete fVectorOfRows;
}

// returns a TArrayD containing the values in one column.
Double_t * TTextToVector::GetCol(Int_t col){
Double_t * returnArray = fVectorOfCols->at(col)->GetArray(); 
std::cout << "Returning array at for column " << col << " at " << returnArray << std::endl; 
return returnArray;
}

// returns a TArrayD containing the values in one row.
Double_t * TTextToVector::GetRow(Int_t row){
return fVectorOfRows->at(row)->GetArray();
}

// function returns an single value from the text file.
Double_t TTextToVector::GetValue(Int_t col, Int_t row){
std::cout << col << "\t" << row << std::endl;
return fVectorOfCols->at(col)->At(row);
}

// function returns the number of rows in the text file
Int_t TTextToVector::GetNumRows(){
return fVectorOfRows->size();
}

// function returns the number of columns in the text file
Int_t TTextToVector::GetNumCols(){
return fVectorOfCols->size();
}
 
// function opens a text file
std::ifstream * TTextToVector::OpenFile(TString * filename){
std::ifstream * infile = new std::ifstream(filename->Data());
return infile; 
} 

// function tests to see if a file is open
bool TTextToVector::CheckFile(std::ifstream * fileStream){
if(fileStream->is_open()){
	return true;
	}
else{
	return false;
	}
}

// function returns TObjArray of TObjStrings containing the lines of the file.
TObjArray * TTextToVector::ReadFile(std::ifstream * fileStream){
TObjArray * arrayOfLines = new TObjArray();
char line[2000];
TObjString * objString = new TObjString();
while(!fileStream->eof()){
	fileStream->getline(line, 2000);
	objString->SetString(line);
// remove empty lines
	if(!objString->GetString().IsWhitespace()){
		arrayOfLines->AddLast(objString->Clone());
		}
	}
delete objString;
return arrayOfLines; 
}

// function converts each line of the file into a TArrayD of Double_ts - returns std::vector<TArrayD*>. 
std::vector<TArrayD*> * TTextToVector::MakeRowVectors(TObjArray * rowStrings){

fNumRows = rowStrings->GetEntriesFast();

std::vector<TArrayD*> * rowVectors = new std::vector<TArrayD*>; 
TString * tempString = 0;
TObjString * tempObjString = 0;
TArrayD * tempArray = 0;
Int_t tempNumRows = fNumRows;
for(int i=0; i<tempNumRows; i++){
	tempObjString = (TObjString*)rowStrings->At(i);
	tempString = &(tempObjString->GetString());
	tempArray = StringToDoubles(tempString);
	if(tempArray!=0){
		rowVectors->push_back(tempArray);
		}
	else{
		fNumRows--;
		}
	}
return rowVectors;
}

// function to transpose row vectors into columns - returns std::vector<TArrayD*>; 
std::vector<TArrayD*> * TTextToVector::MakeColumnVectors(std::vector<TArrayD*> * rowVectors){
// initialise vector of TArrayDs to contain columns 
std::vector<TArrayD*> * colVectors = new std::vector<TArrayD*>;
for(int i=0; i<fNumCols; i++){
	colVectors->push_back(new TArrayD(fNumRows));
	}
// perform the transposition
for(int i=0; i<fNumRows; i++){
TArrayD * tempArray1 = 0;
TArrayD * tempArray2 = 0;
Double_t tempValue = 0.0;
	for(int j=0; j<fNumCols; j++){
		tempArray1 = colVectors->at(j);
		tempArray2 = rowVectors->at(i);
		tempValue = tempArray2->At(j);
		tempArray1->AddAt(tempValue, i);
		}
	}
return colVectors;
}

// function to convert a string into a TArrayD of Double_ts.
TArrayD * TTextToVector::StringToDoubles(TString * string){

TObjArray * stringTokens = string->Tokenize("\t ");
TArrayD * doubles = new TArrayD(stringTokens->GetEntriesFast());
TIter it(stringTokens);

TObjString * tokenObj = 0;
Double_t tokenDouble;
int i=0;

while((tokenObj = (TObjString*)it.Next())){
	if((tokenObj->GetString().IsFloat())){
		tokenDouble = tokenObj->GetString().Atof();
		doubles->AddAt(tokenDouble, i);
		}
	else{
		std::cout << "Warning! Non-numeric entry \"" << tokenObj->GetString().Data() << "\" found! Skipping Row " << i << "!" << std::endl;
		return 0;
		}
	i++;
	}
if(fNumCols==0){
	fNumCols = doubles->GetSize();
	}

delete tokenObj;
delete stringTokens;
	
return doubles;
}

void TTextToVector::PrintCols(){
std::cout << "Printing Columns!" << std::endl;

TArrayD * tempCol=0;

std::vector<TArrayD*>::iterator it = fVectorOfCols->begin();

for(int i=0;it!=fVectorOfCols->end();++it, i++){
	std::cout << "*** Column " << i << " ***" << std::endl;
	tempCol = *it;
	for(int j=0; j<tempCol->GetSize(); j++){
		std::cout << tempCol->At(j) << std::endl;
		}
	std::cout << "***** End *****" << std::endl;
	}
}

void TTextToVector::PrintRows(){
std::cout << "Printing Rows!" << std::endl;

TArrayD * tempRow=0;

std::vector<TArrayD*>::iterator it = fVectorOfRows->begin();

for(int i=0;it!=fVectorOfRows->end();++it, i++){
	std::cout << "*** Row " << i << " ***" << std::endl;
	tempRow = *it;
	for(int j=0; j<tempRow->GetSize(); j++){
		std::cout << tempRow->At(j) << std::endl;
		}
	std::cout << "**** End ****" << std::endl;
	}
}

ClassImp(TTextToVector)
