#include "base/loggers.h"
#include "../test_util.h"
#include "osutils.h"
#include "UnitTest++.h"
#include <string>
#include <stdexcept>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef WIN32
#include <unistd.h>
#endif

using namespace bdm;

int get_file_size ( const char *fname ) {
    struct stat st;
    if ( stat ( fname, &st ) ) {
        std::string msg = "can't stat ";
        msg += fname;
        throw std::runtime_error ( msg );
    }

    int sz = static_cast<int> ( st.st_size );
    if ( sz != st.st_size ) {
        std::string msg = fname;
        msg += " too big";
        throw std::runtime_error ( msg );
    }

    return sz;
}

class log_tester : public root
{
    LOG_LEVEL(log_tester,logr,logth,logpol);
public:
    RV th, r;
    int pol, i;

    log_tester() {
        th = RV ( "{alog blog }" );
        r = RV ( "{r }", "2" );
        pol = 11;

        log_level[logr] = true;
        log_level[logth] = true;
        log_level[logpol] = true;
    }

    void log_register( logger &L, const string prefix ) {
        root::log_register( L, prefix );
        L.add_vector( log_level, logr, r, prefix );
        L.add_vector( log_level, logth, th, prefix );
        L.add_setting( log_level, logpol, prefix, 0 );
        L.add_setting( log_level, logpol, prefix, 1 );
    }

    void log_write() const {
        root::log_write();
        log_level.store( logr, vec_2 ( ( double ) i, ( double ) ( i + 1 ) ) );
        log_level.store( logth, vec_2 ( ( double ) ( 100 - i ), ( double ) ( i - 50 ) ) );
        log_level.store( logpol, pol, 0 );
        log_level.store( logpol, pol^2, 1 );
    }

};

TEST ( memlog_test ) {
    string ls ( "memlog_test" );
    remove_all ( ls.c_str() );

    memlog logger ( 100, ls );


    log_tester tester;
    tester.log_register( logger, "memlog" );

    logger.init();

    for ( tester.i = 0; tester.i < 10; tester.i++ ) {
        tester.log_write();
        logger.step();
    }

    logger.finalize();

    CHECK_EQUAL ( get_file_size ( "logger_test.matrix" ), get_file_size ( ( ls + ".it" ).c_str() ) );
    CHECK_EQUAL ( get_file_size ( ( ls + ".cfg.check" ).c_str() ), get_file_size ( ( ls + ".cfg" ).c_str() ) );
}

TEST ( dirfilelog_test ) {


    string ls ( "exp" );
    remove_all ( ls.c_str() );
    makedir ( ls, false );
    remove_all ( "dirfilelog_files" );

    dirfilelog logger ( "dirfilelog_files", 10 );

    log_tester tester;
    tester.log_register( logger, "dirfilelog" );

    logger.init();

    for ( tester.i = 0; tester.i < 150; tester.i++ ) {
        tester.log_write();
        logger.step();
    }

    logger.finalize();

    std::string expected ( load_test_file ( "logger_test_dirfile_format.matrix" ) );
    std::string actual ( load_test_file ( "dirfilelog_files/format" ) );
    CHECK_EQUAL ( expected, actual );
}
