//
//  main.m
//  BoostLoggingTest
//
//  Created by Paul Solt on 4/6/10.
//  Based on the demo provided by John Torjo: http://torjo.com/log2/
//  Copyright Paul Solt 2010. All rights reserved.
// 

#include <boost/logging/format_fwd.hpp>

BOOST_LOG_FORMAT_MSG( optimize::cache_string_one_str<> )

#include <boost/logging/format_ts.hpp>
#include <boost/thread/xtime.hpp>
using namespace boost::logging;

using namespace boost::logging::scenario::usage;
typedef use<
	//  the filter is always accurate (but slow)
filter_::change::always_accurate, 
	//  filter does not use levels
filter_::level::no_levels, 
	// the logger is initialized once, when only one thread is running
logger_::change::set_once_when_one_thread, 
	// the logger favors speed (on a dedicated thread)
logger_::favor::speed> finder;

BOOST_DECLARE_LOG_FILTER(g_log_filter, finder::filter ) 
BOOST_DECLARE_LOG(g_log_err, finder::logger ) 
BOOST_DECLARE_LOG(g_log_app, finder::logger )
BOOST_DECLARE_LOG(g_log_dbg, finder::logger )

#define LDBG_ BOOST_LOG_USE_LOG_IF_FILTER(g_log_dbg(), g_log_filter()->is_enabled() ) 
#define LERR_ BOOST_LOG_USE_LOG_IF_FILTER(g_log_err(), g_log_filter()->is_enabled() )
#define LAPP_ BOOST_LOG_USE_LOG_IF_FILTER(g_log_app(), g_log_filter()->is_enabled() ) 

BOOST_DEFINE_LOG_FILTER(g_log_filter, finder::filter ) 
BOOST_DEFINE_LOG(g_log_err, finder::logger )
BOOST_DEFINE_LOG(g_log_app, finder::logger )
BOOST_DEFINE_LOG(g_log_dbg, finder::logger )

void do_sleep(int ms) {
    using namespace boost;
    xtime next;
    xtime_get( &next, TIME_UTC);
    next.nsec += (ms % 1000) * 1000000;
	
    int nano_per_sec = 1000000000;
    next.sec += next.nsec / nano_per_sec;
    next.sec += ms / 1000;
    next.nsec %= nano_per_sec;
    thread::sleep( next);
}

void your_scenario_example(const char *filename) {
		//         add formatters and destinations
		//         That is, how the message is to be formatted and where should it be written to
	
		// Err log
    g_log_err()->writer().add_formatter( formatter::idx(), "[%] "  );
    g_log_err()->writer().add_formatter( formatter::time("$hh:$mm.$ss ") );
    g_log_err()->writer().add_formatter( formatter::append_newline() );
    g_log_err()->writer().add_destination( destination::file(filename) );
	
		// App log
    g_log_app()->writer().add_formatter( formatter::time("$hh:$mm.$ss ") );
    g_log_app()->writer().add_formatter( formatter::append_newline() );
    g_log_app()->writer().add_destination( destination::file("out.txt") );
    g_log_app()->writer().add_destination( destination::cout() );
	
		// Debug log
    g_log_dbg()->writer().add_formatter( formatter::time("$hh:$mm.$ss ") );
    g_log_dbg()->writer().add_formatter( formatter::append_newline() );
    g_log_dbg()->writer().add_destination( destination::dbg_window() );
    g_log_dbg()->writer().add_destination( destination::cout() );
    g_log_app()->mark_as_initialized();
    g_log_err()->mark_as_initialized();
    g_log_dbg()->mark_as_initialized();
	
    int i = 1;
    LDBG_ << "this is so cool " << i++;
    LDBG_ << "this is so cool again " << i++;
    LERR_ << "first error " << i++;
	
    std::string hello = "hello", world = "world";
    LAPP_ << hello << ", " << world;
	
    g_log_filter()->set_enabled(false);
    LDBG_ << "this will not be written anywhere";
    LAPP_ << "this won't be written anywhere either";
    LERR_ << "this error is not logged " << i++;
	
    g_log_filter()->set_enabled(true);
    LAPP_ << "good to be back ;) " << i++;
    LERR_ << "second error " << i++;
	
		// just so that we can see the output to the console as well (the messages are written no a different thread)...
    do_sleep(1000);
}




int main() {
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
		// Get the filename and location on the iPhone of the Documents directory
	
	NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
	NSString *path = [docsDirectory stringByAppendingPathComponent:@"err.txt"];
	const char *outputFilename = [path UTF8String];
	your_scenario_example(outputFilename);
    
	[pool release];

	return 0;
}