#!/usr/bin/perl -w
#< filecount.pl - given a directory, count the total files
# 19/05/2011 - Added -t nn to output tail in date order
# 09/05/2011 - Updated
use strict;
use warnings;
use File::Basename;  # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] )
use File::Spec; # File::Spec->rel2abs($rel); # we are IN the SLN directory, get ABSOLUTE from RELATIVE
use File::stat;
use Cwd;
my $perl_dir = 'C:\GTools\perl';
unshift(@INC, $perl_dir);
require 'lib_utils.pl' or die "Unable to load lib_utils.pl ...\n";
# log file stuff
our ($LF);
my $pgmname = $0;
if ($pgmname =~ /(\\|\/)/) {
    my @tmpsp = split(/(\\|\/)/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $outfile = $perl_dir."\\temp.$pgmname.txt";
open_log($outfile);

my $dir_count = 0;
my $file_count = 0;
my $other_count = 0;

my $input_dir = "";

my $load_log = 0;
my $debug_on = 0;
my $def_file = 'none';
my $verbosity = 0;
my $tail_count = 0;
my $sort_by_size = 0;
my $invert_time = 0;

sub VERB1() { return $verbosity >= 1; }
sub VERB2() { return $verbosity >= 2; }
sub VERB5() { return $verbosity >= 5; }
sub VERB9() { return $verbosity >= 9; }

sub scan_dir($$);

### program variables
my @warnings = ();
my $cwd = cwd();
my $os = $^O;
my @g_file_list = ();
my $last_file = '';
my $last_time = 0;
my $last_size = 0;
my $larg_file = '';
my $larg_time = 0;
my $larg_size = 0;

sub show_warnings($) {
    my ($val) = @_;
    if (@warnings) {
        prt( "\nGot ".scalar @warnings." WARNINGS...\n" );
        foreach my $itm (@warnings) {
           prt("$itm\n");
        }
        prt("\n");
    } else {
        ### prt( "\nNo warnings issued.\n\n" );
    }
}

sub pgm_exit($$) {
    my ($val,$msg) = @_;
    if (length($msg)) {
        $msg .= "\n" if (!($msg =~ /\n$/));
        prt($msg);
    }
    show_warnings($val);
    close_log($outfile,$load_log);
    exit($val);
}


sub prtw($) {
   my ($tx) = shift;
   $tx =~ s/\n$//;
   prt("$tx\n");
   push(@warnings,$tx);
}

sub scan_dir($$) {
    my ($dir,$lev) = @_;
    my ($sb);
    if (opendir(DIR, $dir)) {
        my @files = readdir(DIR);
        closedir(DIR);
        my @dirs = ();
        my ($file,$ff);
        $dir .= "/" if (!($dir =~ /(\\|\/)$/));
        foreach $file (@files) {
            next if (($file eq '.')||($file eq '..'));
            $ff = $dir.$file;
            if (-d $ff) {
                push(@dirs,$ff);
                $dir_count++;
            } elsif (-f $ff) {
                if ($sb = stat($ff)) {
                    #                   0           1    2      3
                    push(@g_file_list, [$sb->mtime, $ff, $file, $sb->size]);
                    if ($sb->mtime > $last_time) {
                        $last_time = $sb->mtime;
                        $last_file = $ff;
                        $last_size = $sb->size;
                    }
                    if ($sb->size > $larg_size) {
                        $larg_time = $sb->mtime;
                        $larg_file = $ff;
                        $larg_size = $sb->size;
                    }
                }
                $file_count++;
            } else {
                $other_count++;
            }
        }
        foreach $ff (@dirs) {
            scan_dir($ff,($lev+1));
        }
    }
}

sub mycmp_decend_n1 {
   return 1 if (${$a}[0] < ${$b}[0]);
   return -1 if (${$a}[0] > ${$b}[0]);
   return 0;
}

sub mycmp_ascend_n1 {
   return -1 if (${$a}[0] < ${$b}[0]);
   return 1 if (${$a}[0] > ${$b}[0]);
   return 0;
}

sub mycmp_ascend_n4 {
   return -1 if (${$a}[3] < ${$b}[3]);
   return 1 if (${$a}[3] > ${$b}[3]);
   return 0;
}

#  #                   0           1    2      3
#  push(@g_file_list, [$sb->mtime, $ff, $file, $sb->size]);
sub show_file_array($) {
    my ($ra) = @_;
    if (VERB5()) {
        # continue with SHOW
    } elsif ($tail_count > 0) {
        # show at least this many
    } else {
        # no show anything ;=((
        return;
    }
    my $fcnt = scalar @{$ra};
    my ($i,$item,$time,$ff,$size,$len,$min1,$min2);
    my (@arr);
    if ($sort_by_size) {
        @arr = sort mycmp_ascend_n4 @{$ra};
    } else {
        if ($invert_time) {
            # latest first, down to oldest
            @arr = sort mycmp_decend_n1 @{$ra};
        } else {
            # latest last
            @arr = sort mycmp_ascend_n1 @{$ra};
        }
    }
    $ra = \@arr;
    $min1 = 0;
    $min2 = 0;
    my $total_size = 0;
    my $show_cnt = 0;
    if ($tail_count > 0) {
        if ($tail_count > $fcnt) {
            $show_cnt = 0;
        } else {
            $show_cnt = $fcnt - $tail_count;
        }
    }
    for ($i = 0; $i < $fcnt; $i++) {
        $item  = ${$ra}[$i];
        $time = ${$item}[0];
        $ff   = ${$item}[1];
        $size = get_nn(${$item}[3]);
        $total_size += ${$item}[3];
        $len = length($ff);
        $min1 = $len if ($len > $min1);
        $len = length($size);
        $min2 = $len if ($len > $min2);
    }
    # =============================
    $size = get_nn($total_size);
    $len = length($size);
    $min2 = $len if ($len > $min2);
    $time = lu_get_YYYYMMDD_hhmmss(time());
    # ---------------------------------------
    for ($i = 0; $i < $fcnt; $i++) {
        $item  = ${$ra}[$i];
        $time = lu_get_YYYYMMDD_hhmmss(${$item}[0]);
        $ff   = path_u2d(${$item}[1]);
        $size = get_nn(${$item}[3]);
        if ($i >= $show_cnt) {
            $ff .= ' ' while (length($ff) < $min1);
            $size = ' '.$size while (length($size) < $min2);
            prt("$ff $time $size\n");
        }
    }

    $item = ' ' x length($time);
    $ff = "TOTAL $fcnt files:";
    $size = get_nn($total_size);
    $ff .= ' ' while (length($ff) < $min1);
    $size = ' '.$size while (length($size) < $min2);
    prt("$ff $item $size\n");

}


parse_args(@ARGV);
scan_dir($input_dir,0);
prt("Scanned [$input_dir]. Found $file_count files, $dir_count directories.");
prt(" Others $other_count") if ($other_count);
prt("\n");
if (VERB1() && ($last_time > 0)) {
    $last_file = path_u2d($last_file);
    prt("Latest : $last_file ".lu_get_YYYYMMDD_hhmmss($last_time)." ".get_nn($last_size)." bytes.\n");
}
if (VERB1() && ($larg_time > 0)) {
    $larg_file = path_u2d($larg_file);
    if ($last_file eq $larg_file) {
        prt("Largest: same file.\n");
    } else {
        prt("Largest: $larg_file ".lu_get_YYYYMMDD_hhmmss($larg_time)." ".get_nn($larg_size)." bytes.\n");
    }
}
show_file_array(\@g_file_list);
pgm_exit(0,"");

sub deal_with_verbosity($) {
    my ($rav) = @_;
    my ($arg,$sarg,$i,$cnt);
    $cnt = scalar @{$rav};
    #prt("Doing verbosity check of $cnt args...\n");
    for ($i = 0; $i < $cnt; $i++) {
        $arg = ${$rav}[$i];
        #prt("Checking [$arg]...\n");
        if ($arg =~ /^-/) {
            $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /^-/);
            if ($sarg =~ /^v/) {
                #prt("Got -v... [$arg]\n");
                if ($sarg =~ /^v.*(\d+)$/) {
                    $verbosity = $1;
                } else {
                    while ($sarg =~ /^v/i) {
                        $verbosity++;
                        $sarg = substr($sarg,1)
                    }
                }
                prt( "[v1] Set verbosity to $verbosity\n") if (VERB1());
            }

        }
    }
}


sub give_help {
    prt("$pgmname: version 0.0.1 2011-05-09\n");
    prt("Usage: $pgmname [options] in-directory\n");
    prt("Options:\n");
    prt(" --help (-h or -?) = This help, and exit 0.\n");
    prt(" -v[nn]            = Bump (or set) verbosity.\n");
    prt(" -t cnt            = Show this many files.\n");
}
sub need_arg {
    my ($arg,@av) = @_;
    pgm_exit(1,"ERROR: [$arg] must have following argument!\n") if (!@av);
}

sub parse_args {
    my (@av) = @_;
    deal_with_verbosity(\@av);
    my ($arg,$sarg);
    while (@av) {
        $arg = $av[0];
        if ($arg =~ /^-/) {
            $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /^-/);
            if (($sarg =~ /^h/i)||($sarg eq '?')) {
                give_help();
                pgm_exit(0,"Help exit(0)");
            } elsif ($sarg =~ /^v/) {
                # already done
            } elsif ($sarg =~ /^t/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                if ($sarg =~ /^\d+$/) {
                    $tail_count = $sarg;
                } else {
                    pgm_exit(1,"ERROR: Invalid argument [$arg $sarg]! Try -?\n");
                }
            } else {
                pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n");
            }
        } else {
            $input_dir = $arg;
            prt("Set input to [$input_dir]\n");
        }
        shift @av;
    }

    if ((length($input_dir) ==  0) && $debug_on) {
        $input_dir = $def_file;
    }
    if (length($input_dir) ==  0) {
        pgm_exit(1,"ERROR: No input files found in command!\n");
    }
    if (! -d $input_dir) {
        pgm_exit(1,"ERROR: Unable to find in directory [$input_dir]! Check name, location...\n");
    }
}


# eof
