# -*- cperl -*-
# ABSTRACT: Log

=head1 SYNOPSIS

Logging facility

=cut

package BeamerReveal::Log;
# VERSION

use parent 'Exporter';
use Carp;

use BeamerReveal::Log::Ansi;

use IO::File;

our $logger;

sub max { $_[$_[0] < $_[1] ] }


=method new()


=cut

sub new {
  $logger->fatal( "Error: internal error - attempt to create two logger objects\n" )
    if ( defined( $logger ) );
  my $class =  shift;
  my $args = { @_ };
  exists $args->{logfilename}
    and exists $args->{opening}
    and exists $args->{closing}
    and exists $args->{labelsize}
    and exists $args->{activitysize}
    or die( "Error: missing argument to (child of) BeamerReveal::Log::new()\n" );
  my $self = BeamerReveal::Log::Ansi->new( %$args );

  $self->{tasks} = [];

  $self->{termwidth} = $self->_terminal_width() - 2;
  $self->{barsize} = $self->{termwidth} - $self->{labelsize} - $self->{activitysize} - 12;
  
  $self->{logfile} = IO::File->new();
  $self->{logfile}->open( ">$self->{logfilename}" )
    or die( "Error cannot open log file $self->{logfilename}" );

  # build opening lines for logfile
  print {$self->{logfile}} _formatLines( $self->{opening}, 76 );
  # build opening lines for terminal
  print _formatLines( $self->{opening}, $self->{termwidth} );
  
  $logger = $self;
  
  return $self;
}

=method log()

=cut

sub log {
  my $self = shift;
  my ( $indent, $message ) = @_;

  say {$self->{logfile}} ( ' ' x $indent ) . $message;
}

sub fatal {
  my $self = shift;
  my ( $message ) = @_;

  say {$self->{logfile}} $message;
  $self->{logfile}->close();
  
  die( "$message\n" .
       "Check the logfile $self->{logfilename} for more information.\n" );
}

=method registerTask()

=cut

sub registerTask {
  my $self = shift;
  my $args = { @_ };
  exists $args->{label}
    and exists $args->{progress}
    and exists $args->{total}
    or $self->fatal( "Error: missing argument to BeamerReveal::Log::registerTask\n" );
  # fill out default value for activity message
  $args->{activity} = '';
 
  my $index = @{$self->{tasks}};
  push @{$self->{tasks}}, $args;
  return $index;
}

sub activate {
  my $self = shift;
  $self->fatal( "Error: internal error - activation through BeamerReveal::Log base class\n" );
}

sub progress {
  my $self = shift;
  $self->fatal( "Error: internal error - progress reported through BeamerReveal::Log base class\n" );
}

sub finalize {
  my $self = shift;
  $self->fatal( "Error: internal error - finalization through BeamerReveal::Log base class\n" );
}

sub _bar_line {
  my ($label, $labelsize, $activity, $activitysize, $done, $total, $width) = @_;
  
  my $pct = $done / $total;
  $pct = 1 if $pct > 1;
  
  my $filled = int($pct * $width);
  my $empty  = $width - $filled;

  return sprintf("%-${labelsize}s: %-${activitysize}s [%s%s] %5.1f%%",
		 $label,
		 $activity,
		 '#' x $filled,
		 '-' x $empty,
		 $pct * 100
		);
}

sub _formatLines {
  my ( $linearrayref, $width, $extra ) = @_;
  $extra ||= '';
  my $openinglines;
  foreach my $line ( @{$linearrayref} ) {
    my ( $left, $right) = split( /\|/, $line );
    if( $left eq $right ) {
      $openinglines .= $extra . ( $left x $width ) . "\n";
    }
    else {
      my $llen = length( $left );
      my $rlen = length( $right );
      my $midspace = $width - $llen - $rlen;
      $openinglines .= $extra . $left . ( ' ' x $midspace ) . $right . "\n";
    }
  }
  return $openinglines;
}
1;
