package Common::Timer;
use strict;
use warnings;

use Time::HiRes qw(gettimeofday);

# This class implements a somewhat simplistic profiling/timing mechanism.
# The idea is to get a rough sketch of where we are spending our time.
#

# Use static methods to start and stop profiling.
#
my $gProfiling  = 0;
my $gReportList = undef;
my $gIndent     = 0;

sub Start {
    $gIndent     = 0;
    $gReportList = [];
    $gProfiling  = 1;
}

sub Stop {
    $gProfiling = 0;
}

sub Report {
    my ($fh) = @_;

    return unless defined $gReportList;

    my %timingHash;

    foreach my $item (@$gReportList) {
        my $message = $item->[0];
        my $timing  = $item->[1];
        my $indent  = $item->[2];

        my $indentString;
        for ( my $i = 0 ; $i < $indent ; $i++ ) {
            $indentString .= ' ';
        }

        #        print $fh "$indentString $message $timing \n";
        $timingHash{$message}{time} += $timing;
        $timingHash{$message}{count}++;
    }

    print $fh "----------\n";
    my @results = sort { $timingHash{$b}{time} <=> $timingHash{$a}{time} } keys %timingHash;
    foreach my $k (@results) {
        my $out = sprintf( "%03.5f\t\t%d\t\t%s\n", $timingHash{$k}{time}, $timingHash{$k}{count}, $k );
        print $fh $out;
    }
}

sub _addMessageToReport {
    my ( $message, $td, $indent ) = @_;

    unshift @$gReportList, [ $message, $td, $indent ];
}

# Instance methods are used for individual timing entries.
#
sub new {
    my ( $class, $message ) = @_;

    if ( !$message ) {

        # default to the funtion/method name of our caller
        #
        $message = ( caller(1) )[3];
    }

    my $currentCPUSeconds = gettimeofday;
    my $self = bless {}, $class;
    $self->{_message}   = $message;
    $self->{_benchmark} = $currentCPUSeconds;
    $self->{_indent}    = $gIndent++;

    return $self;
}

sub DESTROY {
    my ($self) = @_;

    $gIndent--;
    if ($gProfiling) {
        my $currentCPUSeconds = gettimeofday;
        my $td                = $currentCPUSeconds - $self->{_benchmark};
        _addMessageToReport( $self->{_message}, $td, $self->{_indent} );
    }
}

1;
