
#include "loggers.h"
#include "../osutils.h"

#include <fcntl.h>
#ifdef WIN32
#include <io.h>
#define open _open
#define write _write
#define close _close
#endif

namespace bdm {

void memlog::init() {
	int i;
	int n = entries.length();
	vectors.set_size ( n );
	for ( i = 0; i < n; i++ ) {
		vectors ( i ).set_size ( maxlen, entries ( i )._dsize() );

		// avoid uninitialized memory
		for ( int j = 0; j < vectors ( i ).rows(); ++j ) {
			for ( int k = 0; k < vectors ( i ).cols(); ++k ) {
				vectors ( i ) ( j, k ) = 0;
			}
		}
	}
}

void memlog::itsave ( const char* fname ) {
	it_file itf ( fname );
	int i;
	string vec_name = "";
	int istart, iend;
	for ( i = 0; i < entries.length(); i++ ) {
		istart = 0;
		for ( int j = 0; j < entries ( i ).length(); j++ ) { // same for as in add!!!
			vec_name = names ( i ) + entries ( i ).name ( j );
			iend = istart + entries ( i ).size ( j ) - 1;
			itf << Name ( vec_name ) << vectors ( i ).get_cols ( istart, iend );
			// move start after current end...
			istart = iend + 1;
		}

	}
}

void memlog::from_setting ( const Setting &set ) {
	// TODO tady se natvrdo ocekava existence stringu, nejsou zadne defaulty.. je to tak OK?
	UI::get ( maxlen,  set, "maxlen", UI::compulsory );
	UI::get ( filename, set, "filename" );
}

void dirfilelog::init() {
	int i, j, k;
	int nsc = 0;
	for ( i = 0; i < entries.length(); i++ ) {
		nsc += entries ( i )._dsize();
	}
	; //all entries!!

	char filename[200];
	char num[3];

// Initialize directory
	makedir ( dirname ); //

// directory OK, or it can be overwritten

//Create filenames
	scalarnames.set_length ( nsc );
	// For all entries
	int ii = 0;
	for ( i = 0; i < entries.length(); i++ ) { //for entries
		for ( j = 0; j < entries ( i ).length(); j++ ) { //for RVs in entries
			int rvsize = entries ( i ).size ( j );
			// for non-empty names
			if ( names ( i ).length() > 0 ) {
				scalarnames ( ii ) = names ( i ) + separator;
			}
			// add name
			scalarnames ( ii ) +=  entries ( i ).name ( j );
			// add number when needed
			if ( rvsize > 1 ) {
				// copy the same name for th whole RV
				for ( k = 1; k < rvsize; k++ ) {
					scalarnames ( ii + k ) = scalarnames ( ii );
				}
				// add numbers
				for ( k = 0; k < rvsize; k++ ) { //for all scalars in given RV
					sprintf ( num, "%d", k );
					scalarnames ( ii ) += separator + num;
					ii++;
				}
			} else {
				ii++;
			}
		}
	}
	//Create format
	string frm = "format";
	get_fname ( filename, dirname, frm );

	FILE* fpf;
	fpf = fopen ( filename, "w" );
	for ( i = 0; i < ii; i++ ) {
		fprintf ( fpf, "%s RAW d 1\n", scalarnames ( i ).c_str() );
	}
	fclose ( fpf );

	memlog::init();

	//Delete old data
	write_buffers ( 0 );
}


void dirfilelog::write_buffers ( int Len ) {
	int fp;
	int nen = entries.length(); //all entries!!
	double *Dt;
	int DtRows;
	int i, j, k;
	int ii; //index in scalarnames;
	int jj; //index in vectors()
	char filename[200];

	bdm_assert_debug ( Len <= maxlen, "diffilelog::write_buffers: Len too large" );

	ii = 0;
	for ( i = 0; i < nen; i++ ) { //for entries
		Dt = vectors ( i )._data();
		DtRows = vectors ( i ).rows();

		jj = 0;
		for ( j = 0; j < entries ( i ).length(); j++ ) { //for RVs in entries
			int rvsize = entries ( i ).size ( j );
			for ( k = 0; k < rvsize; k++ ) { { //for all scalars in given RV
					get_fname ( filename, dirname, scalarnames ( ii ) );
					if ( Len == 0 ) //initialization
						fp = open ( filename, O_CREAT | O_WRONLY | O_TRUNC, 00644 );
					else
						fp = open ( filename, O_CREAT | O_WRONLY | O_APPEND, 00644 );

					write ( fp, &Dt[jj* ( DtRows ) ], ( Len ) *sizeof ( double ) );
					close ( fp );

					//next row in Dt
					jj++;
					//next scalarname
					ii++;
				}
			}
		}
	}
}

void dirfilelog::step ( ) {

	if ( ind == ( maxlen - 1 ) ) {
		write_buffers ( ind + 1 );
		ind = 0;
	} else
		ind++;

}

void dirfilelog::finalize ( ) {
	if ( ind > 0 )
		write_buffers ( ind ); //assuming here that i+1 was not filled
}


void dirfilelog::from_setting ( const Setting &set ) {
	// TODO tady se natvrdo ocekava existence stringu, nejsou zadne defaulty.. je to tak OK?
	dirname = ( const char* ) set["dirname"];
	maxlen = set["maxlen"];
	scalarnames.set_length ( 0 );
}

}
