#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

@ARGV || do {
    die "Usage: $0 SRCFILE ...\n"
      . "Extract log message from specified source code,\n"
      . "and output log lists in CSV format.\n"
      . "\n"
      . "Example:\n"
      . "  \$ $0 ../src/*.c ../module/*/*.c*\n";
};

my %all_log;
$| = 1;

# pick out all log message!
for my $src (@ARGV) {
    print STDERR "reading $src ... ";
    if (!-f $src) {
        print STDERR "\n$src: No such file\nPush Enter key to continue.\n";
        <STDIN>;
        next;
    }
    my $fh;
    if (!open $fh, "<", $src) {
        print STDERR "\n$src: Cannot open file\nPush Enter key to continue.\n";
        <STDIN>;
        next;
    }
    my $all_line;
    map { $all_line .= $_ } <$fh>;
    close $fh;

    # remove all CRLF
    $all_line =~ s/[\r\n]//g;
    my $count = 0;

    # log function regex
    while ($all_line =~ /
        (                                       # capture start
          (?:
            LOGGER_PUT_LOG_([^\s(]+) \s* \( \s* # LOGGER_PUT_LOG_LEVEL start
          |                                     # or
            PUT_LOG_([^\s(]+) \s* \( [^,]+, \s* # PUT_LOG_LEVEL start
          )
          ([^\s,]+) \s* , \s*                   # log category
          (\d+) \s* , \s*                   # log number
          ( (?: (?: "[^"]*" \s* )+ | [^,)]+) )  # log message
          .*?                                   # any argument
          \) \s* ;                              # log function end
        )                                       # capture end
    /xsg) {
        my ($log, $category, $number, $message) = ($1, $4, $5, $6);
        my $level = $2 || $3;

        # push to hash table (push for duplicate log)
        push @{ $all_log{$category}{$level}{$number}{file    } }, $src;
        push @{ $all_log{$category}{$level}{$number}{log     } }, $log;
        push @{ $all_log{$category}{$level}{$number}{message } }, $message;

        $count++;
    }
    print STDERR "$count logs.\n";
}

#print Dumper \%all_log;
#exit;

# output log list
my %summary;
my @duplicate_list;
for my $category (sort keys %all_log) {
    print "===== $category =====\n";
    for my $level ( sort keys %{ $all_log{$category} } ) {
        print "----- $level -----\n";
        for my $number ( sort { $a <=> $b } keys %{ $all_log{$category}{$level} } ) {
            my $entry = $#{ $all_log{$category}{$level}{$number}{file} };
            for (0 .. $entry) {
                my $file    = $all_log{$category}{$level}{$number}{file   }[$_];
                my $log     = $all_log{$category}{$level}{$number}{log    }[$_];
                my $message = $all_log{$category}{$level}{$number}{message}[$_];
                # CSV
                print "$category,$level,$number,$file,$message,";
                if ($entry > 0) {
                    # duplicate tag
                    print "DUPLICATE";
                    push @duplicate_list, "$file: $log\n";
                }
                print "\n";
                $summary{$category}{all}++;
                $summary{$category}{$level}++;
                $summary{$category}{duplicate}{all}    += $entry;
                $summary{$category}{duplicate}{$level} += $entry;
            }
        }
    }
    print "\n";
}

# print all duplicate log
#print "===== DUPLICATE LOG =====\n";
#for (@duplicate_list) {
#    print;
#}
#print "\n";

# print summary
print "===== SUMMARY =====\n";
for my $category (sort keys %summary) {
    # category has duplicate log
    if ( $summary{$category}{duplicate}{all} ) {
        print "$category (duplicate)\n";
        printf "ALL: %d(%d), ", $summary{$category}{all} || 0, $summary{$category}{duplicate}{all} || 0;
        printf "FATAL: %d(%d), ", $summary{$category}{FATAL} || 0, $summary{$category}{duplicate}{FATAL} || 0;
        printf "ERROR: %d(%d), ", $summary{$category}{ERROR} || 0, $summary{$category}{duplicate}{ERROR} || 0;
        printf "WARN: %d(%d), ", $summary{$category}{WARN} || 0, $summary{$category}{duplicate}{WARN} || 0;
        printf "INFO: %d(%d), ", $summary{$category}{INFO} || 0, $summary{$category}{duplicate}{INFO} || 0;
        printf "DEBUG: %d(%d)", $summary{$category}{DEBUG} || 0, $summary{$category}{duplicate}{DEBUG} || 0;
        print "\n";
    }
    # category has no duplicate log
    else {
        print "$category\n";
        printf "ALL: %d, ", $summary{$category}{all} || 0;
        printf "FATAL: %d, ", $summary{$category}{FATAL} || 0;
        printf "ERROR: %d, ", $summary{$category}{ERROR} || 0;
        printf "WARN: %d, ", $summary{$category}{WARN} || 0;
        printf "INFO: %d, ", $summary{$category}{INFO} || 0;
        printf "DEBUG: %d ", $summary{$category}{DEBUG} || 0;
        print "\n";
    }
}
