#!/usr/bin/perl -w

use strict;
use warnings;
use Time::ParseDate;
use File::Basename;
use Cwd qw(abs_path);

# set current path of this command
my $curpath = dirname(Cwd::abs_path(__FILE__));

my $CONFFILE = "/etc/osw2csv.conf";
if (-f "$curpath/".basename($CONFFILE)) {
	require "$curpath/".basename($CONFFILE);
} elsif (-f $CONFFILE) {
	require $CONFFILE;
}

require "$curpath/osw2csv_functions";

unless (-p STDIN) {
	print STDERR <<"END_OF_USAGE";
usage:	# cat slabinfofile | $0 > csvfile.csv
description:
	This script generate csv file, which is from "/proc/slabinfo" output
	provided by OSWatcher or ExaWatcher.
	the slabinfo output is read from STDIN, and cvs is provided onto
	STDOUT.
END_OF_USAGE
	exit 1;
}


# belows are defined in $COMMONFUNCTIONS
#our $sys_bootsecond ;  # set by $zzz_second and the 1st "top -" line.
our $zzz_second;  # set by "zzz ... " line. 0 means "there are no zzz line"


# print header of slabinfo
sub print_header {
	my ($slabnamep, $header_entriesp) = @_;
	my @ary = ("Time","Timezone");
	foreach my $slabname (@$slabnamep) {
		foreach my $entry (@$header_entriesp) {
			push(@ary, "$slabname $entry");
		}
	}
	print join(',', @ary)."\n";
}


sub printSlabinfoCSVBody {
	my $header_printed = 0;  # T/F: whether header line has been printed
	my @header_entries = (); # entires in "# name" line
	my @slabnames_current = (); # current slab heading name array
	my @slabnames_1st = ();  # first slab heading name array
	my $header_changed = 0;  # T/F: whether heading line is changed
	my $emptystr = "";       # iterating "," for empty slab element

	# read/check the first line
	return if (!defined($_ = readNextLineFromSTDIN()));
	while (defined($_)) {
		# set current time if there is "zzz" or time line
		if (setZZZLine($_) || setZZZByTimeLine($_)) {
			$_ = readNextLineFromSTDIN(1);
			next;
		}

		# line "slabinfo - version: #.#" is simply ignored 
		# ignore if the line is not /^# name /
		if (!/^# name/) {
			$_ = readNextLineFromSTDIN(1);
			next;
		}

		# analyze "# name " line for printing headers
		if (!$header_printed) {
			@header_entries = grep { $_ ne ':' } (split(/\s+/));
			splice(@header_entries, 0, 2);  # remove "#" and "name"
			# Note: @header_entries is assumed not to be changed
		}
		$_ = readNextLineFromSTDIN();

		# process each slab line, fill @slabnames and @slablist
		my (@slabnames, @slablist);
		# %slabdata is only used after $header_changed is true
		my %slabdata;
		while (defined($_) && !isZZZLine($_)) {
			my @data = grep { $_ ne ':' } split(/\s+/);
			my $slabname = shift(@data);
			push(@slabnames, $slabname);
			push(@slablist, join(',', @data));
			$slabdata{$slabname} = join(',', @data);
			$_ = readNextLineFromSTDIN();
		}

		# print header if necessary
		if (!$header_printed) {
			print_header(\@slabnames, \@header_entries);
			$header_printed = 1;
			@slabnames_1st = @slabnames_current = @slabnames;
			$emptystr = ',' x $#header_entries
		}

		# print the slab line
		print getDateStringFromSeconds($zzz_second).",$ENV{TZ},";
		if (!$header_changed &&
		    isEqualList(\@slabnames_1st, \@slabnames)) {
			# when @slabnames is completely same as 1st one,
			# just print the slablist
			print join(',',@slablist)."\n";
		} else {
			# when @slabnames was changed(added) during analysis,
			# we need to modify how to print slabdata
			$header_changed = 1;
			my @added_names = getUniqueItemsFromListB(\@slabnames_current, \@slabnames);
			# "decreasing items" is just ignored, handled well.
			push(@slabnames_current, @added_names);
			my @changed_slablist;
			foreach (@slabnames_current) {
				if (defined($slabdata{$_})) {
					push(@changed_slablist, $slabdata{$_});
				} else {
					push(@changed_slablist, $emptystr);
				}
			}
			print join(',',@changed_slablist)."\n";
		}
	}
	if ($header_changed) {
		print_header(\@slabnames_current, \@header_entries);
		print STDERR "header_changed... Paste the last line to the top of the sheet.\n";
	}
}

printSlabinfoCSVBody;
exit 0;

