# (C) SWSoft 2004-2007

package SB::Logging;

use strict;
use warnings;
use Carp;
use POSIX qw(strftime);
require SB::Defaults;

BEGIN {
	use Exporter;
	our (@ISA, $VERSION, @EXPORT, @EXPORT_OK);
	$VERSION =  4.00;
	@ISA = qw(Exporter);
    @EXPORT    = qw($Logger);
    @EXPORT_OK = qw(VERYVERBOSE DEBUG INFO WARNING FATAL ERROR);
}

use subs qw(new init Log stopLogging);
use vars qw($Logger);

sub VERYVERBOSE { return 0; }
sub	DEBUG   { return 1; }
sub	INFO    { return 2; }
sub	WARNING { return 3; }
sub	ERROR   { return 4; }
sub	FATAL   { return 5; }

our $Logger;

INIT {
	$Logger = new SB::Logging;
}

sub new {
	my $class = shift;
	my $self = { 'initialized' => 0 };
	bless $self, $class;
	#$self->init(@_);
	return $self;
}

sub init {
	my $self = shift;
	my $logfile = shift;

    #Redirect stdout to log file
	$self->{'saved_stdout'} = \*SAVED_STDOUT;
	$self->{'logformat'} = '%Y %b %e %H:%M:%S';
	$self->{'finalmessage'} = 1;
	$self->{'errortrigger'} = 0;
	$self->{'copytoconsole'} = 0;

	open(SAVED_STDOUT, ">& STDOUT");

	$self->{'logfile'} = $logfile;
    unless (open(STDOUT, ">> $logfile")) {
        warn("Cannot open log file '$logfile' for writing: $!\n");
		$self->{'consoleonly'} = 1;
		$self->{'finalmessage'} = 0;
    }
    else {
        open(STDERR, ">> $logfile");
    }
    chmod 0600, $logfile if ( -f $logfile );
	if (exists($ENV{'SB_CONFIGURE_VERBOSE'}) || (-e '/tmp/SB_CONFIGURE_VERBOSE')) {
		$self->{'loglevel'} = VERYVERBOSE ;
		Log($self, INFO, "Turning on debugging output");
	}
	else {
		$self->{'loglevel'} = INFO ;
	}
	$self->{'initialized'} = 1;
}

sub setShowLogName {
	my $self = shift;
	$self->{'finalmessage'} = shift;
}

sub setLevel {
	my $self = shift;
	my $level = shift;
	$self->{'loglevel'} = $level if ($level <= FATAL && $level >= VERYVERBOSE);
}

sub debug {
	my $self = shift;
	$self->Log(DEBUG, @_);
}

my %prep = ( &VERYVERBOSE => "[VERBOSE] ",
			 &DEBUG => "[DEBUG] ", 
			 &INFO => "", 
			 &WARNING => "[WARN] ",
			 &ERROR => "[ERROR] ", 
			 &FATAL => "[FATAL] ");
sub Log {
	my $self = shift;
	return unless $self->{'initialized'};
	my $severity = shift;
	my $message = shift;
	my $loglevel = $self->{'loglevel'};
	my $time = "[".(strftime $self->{'logformat'}, localtime)."] ";

    $message = $prep{$severity} . $message;
    $message .= "\n" unless substr($message, -1) eq "\n";

    if ($severity >= $loglevel) {
		if ($self->{'copytoconsole'} == 1 || 
			($severity > DEBUG) && !exists($self->{'consoleonly'})) {
			print {$self->{'saved_stdout'}} $message
		}

        print "$time $message";
    }

	$self->{'errortrigger'} = 1 if ($severity >= ERROR);

    if ($severity >= FATAL) {
		confess("Fatal error encountered");
    }
}

sub setCopyToConsole {
	my $self = shift;
	$self->{'copytoconsole'} = shift;
}

sub _stopLogging {
	my $self = shift;
	return unless $self->{'initialized'};

	## I hate perl magic!
	*SAVED_STDOUT = $self->{'saved_stdout'};
	close(STDOUT);
    open(STDOUT, ">&SAVED_STDOUT");
    open(STDERR, ">&SAVED_STDOUT");
	print "There were some configuration errors, check logs\n" if $self->{'errortrigger'};
	unless ($self->{'consoleonly'}) {
		print "Logs saved to " . $self->{'logfile'} . "\n" if $self->{'finalmessage'};
	}
}

sub DESTROY {
	_stopLogging @_;
}

1;

