
#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 ) + separator + 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 ) {
    root::from_setting( set );
    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 && !buffers_written) {
        write_buffers ( ind ); //assuming here that i+1 was not filled
        buffers_written = true;
    }
}


void dirfilelog::from_setting ( const Setting &set ) {
    dirname = ( const char* ) set["dirname"];
    maxlen = set["maxlen"];
    scalarnames.set_length ( 0 );
}

}
