#!/usr/bin/perl
#  Copyright 2001-2011 Leslie Richardson

#  This file is part of Open Admin for Schools.

#  Open Admin for Schools is free software; you can redistribute it 
#  and/or modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2 of 
#  the License, or (at your option) any later version.

# confyear.pl - configure the school year.

my %lex = ('Eoy' => 'Eoy',
	   'School Year' => 'School Year',
	   'Error' => 'Error',
	   'Set' => 'Set',
	   'Tracks' => 'Tracks',
	   'Number of' => 'Number of',
	   'Terms' => 'Terms',
	   'Start Date' => 'Start Date',
	   'End Date' => 'End Date',
	   'Continue' => 'Continue',
	   'Grades' => 'Grades',
	   'Separate with Spaces' => 'Separate with Spaces',
	   'Term Block' => 'Term Block',
	   'Term' => 'Term',
	   'Start' => 'Start',
	   'End' => 'End',
	   'Default' => 'Default',
	   'Track' => 'Track',
	   'Main' => 'Main',
	   'Start' => 'Start',
	   'Description' => 'Description',
	   'Map' => 'Map',
	   'Desc' => 'Desc',
	   'File' => 'File',
	   'Updated' => 'Updated',
	   'Record(s) Stored' => 'Record(s) Stored',
	   'Save' => 'Save',

	   );

my $self = 'confyear.pl';

my $defaultEtcPath = '../../etc';

use DBI;
use CGI;
use Data::Dumper;
use Time::JulianDay;

$Data::Dumper::Purity = 1;
$Data::Dumper::Indent = 0;

eval require "../../etc/admin.conf";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}

# Set Path to etc directory
if ( not $g_EtcPath ) {
    $g_EtcPath = $defaultEtcPath;
}


my $q = CGI->new;
print $q->header( -charset, $charset ); 
my %arr = $q->Vars;

my $dsn = "DBI:$dbtype:dbname=$dbase";
my $dbh = DBI->connect($dsn,$user,$password);
$dbh->{mysql_enable_utf8} = 1;

# Page Header
print "$doctype\n<html><head><title>$lex{Set} $lex{'School Year'}</title>
<link rel=\"stylesheet\" href=\"$css\" type=\"text/css\">
$chartype\n</head><body>\n";

print "[ <a href=\"$homepage\">$lex{Main}</a> | <a href=\"$eoypage\">$lex{Eoy}</a> |\n";
print "<a href=\"$self\">$lex{Start}</a> ]\n";

print "<h1>$lex{Set} $lex{'School Year'}</h1>\n";

#foreach my $key ( keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }

if ( not $arr{page} ) {
    showStartPage();

} elsif ( $arr{page} == 1 ) {
    delete $arr{page};
    setTerms();

} elsif ( $arr{page} == 2 ) {
    delete $arr{page};
    setTracks();

} elsif ( $arr{page} == 3 ) {
    delete $arr{page};
    writeRecords();
}


#----------------
sub showStartPage {
#----------------


    # Read in values from conf_system;
    my $sth = $dbh->prepare("select datavalue from conf_system
      where dataname = ? and filename = 'admin'");
    foreach my $dataname qw( g_MTrackTerm schoolstart schoolend schoolyear ) { # load 4 values.
	$sth->execute($dataname);
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $datavalue = $sth->fetchrow;
	eval $datavalue;
	if ( $@ ) {
	    print $lex{Error}. " $@<br>\n";
	    die $lex{Error}. " $@\n";
	}
    }


    # Figure out terms and tracks.
    my $deftracks = keys %g_MTrackTerm;
    if ( not $g_DefaultTrack ) { $g_DefaultTrack = 1; }

    my $defterms;
    for my $trk ( 1..$deftracks ) {
	my $terms = keys %{$g_MTrackTerm{$trk}};
	if ( $terms > $defterms ) { $defterms = $terms; }
    }
    
    print "<form action=\"$self\" method=\"post\">\n";
    print "<input type=\"hidden\" name=\"page\" value=\"1\">\n";

    print "<table cellpadding=\"3\" cellspacing=\"0\" border=\"0\" ";
    print "style=\"padding:0.5em;border:1px solid gray;\">\n";

    # School Year
    if ( not $schoolyear and $schoolstart and $schoolend ) {
	my @start = split(/-/, $schoolstart );
	my @end = split(/-/, $schoolend );
	$schoolyear = "$start[0]-$end[0]";
    }
    print "<tr><td class=\"bra\">$lex{'School Year'}</td><td class=\"la\">";
    print "<input type=\"text\" name=\"schoolyear\" size=\"10\" value=\"$schoolyear\">";
    print "</td></tr>\n";

    print "<tr><td class=\"bra\">$lex{'Start Date'}</td>\n";
    print "<td class=\"la\">";
    print "<input type=\"text\" name=\"startdate\" value=\"$schoolstart\" size=\"10\">\n";
    print "</td></tr>\n";

    print "<tr><td class=\"bra\">$lex{'End Date'}</td>\n";
    print "<td class=\"la\">";
    print "<input type=\"text\" name=\"enddate\" value=\"$schoolend\" size=\"10\">\n";
    print "</td></tr>\n";

    print "<tr><td class=\"bra\">$lex{'Number of'} $lex{Terms}</td>\n";
    print "<td class=\"la\"><input type=\"text\" name=\"terms\" size=\"4\" value=\"$defterms\"></td></tr>\n";

    print "<tr><td class=\"bra\">$lex{'Number of'} $lex{Tracks}</td>\n";
    print "<td class=\"la\"><input type=\"text\" name=\"tracks\" size=\"4\" value=\"$deftracks\"></td></tr>\n";

    print "<tr><td colspan=\"2\" class=\"cn\"><input type=\"submit\" value=\"$lex{Continue}\"></td></tr>\n";
    print "</table></form>\n";

    print "</body></html>\n";

    exit;

} # end of showStartPage



#-----------
sub setTerms {
#-----------

    #foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }

    # Read in values from conf_system;
    my $sth = $dbh->prepare("select datavalue from conf_system
      where dataname = ? and filename = 'admin'");
    foreach my $dataname qw( g_MTrackTerm g_termstart g_termend g_MultiTrack g_TrackDisplay g_TermDisplay g_DefaultTrack) { 
	# load 7 values.
	$sth->execute( $dataname );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $datavalue = $sth->fetchrow;
	eval $datavalue;
	if ( $@ ) {
	    print $lex{Error}. " $@<br>\n";
	    die $lex{Error}. " $@\n";
	}
    }


    # Form / Table Start
    print "<form action=\"$self\" method=\"post\">\n";
    print "<input type=\"hidden\" name=\"page\" value=\"2\">\n";
    foreach my $key ( keys %arr ) { # add passed values as hidden also.
	print "<input type=\"hidden\" name=\"$key\" value=\"$arr{$key}\">\n";
    }
    print "<table cellpadding=\"3\" cellspacing=\"0\" border=\"0\">\n";

    print "<tr><td class=\"bra\">$lex{'School Year'}</td><td class=\"la\" colspan=\"2\">$arr{schoolyear}</td></tr>\n";


    # Tracks Row
    print "<tr><td class=\"bra\">$lex{Tracks}-></td>\n";
    for my $trk ( 1 .. $arr{tracks} ) {
	print "<td class=\"bcn\" colspan=\"2\">$trk &ndash; $lex{Desc} <input type=\"text\" name=\"trkdesc:$trk\" ";
	print "size=\"8\" maxlength=\"8\" value=\"$g_TrackDisplay{$trk}\"></td>";
    }
    print "</tr>\n";


    # Term Description
    print "<tr><td class=\"bla\">$lex{Terms}</td>\n";
    for my $trk ( 1 .. $arr{tracks} ) {
	print "<td class=\"cn\">$lex{Description}</td>";
	print "<td class=\"cn\">$lex{'Start Date'}</td>\n";
    }
    print "</tr>\n";


    # Term Rows
    for my $trm ( 1 .. $arr{terms} ) {
	print "<tr><td class=\"bcn\">$trm</td>";
	for my $trk ( 1 .. $arr{tracks} ) {
	    print "<td class=\"cn\">";
	    print "<input type=\"text\" name=\"trmdesc:$trk:$trm\" size=\"12\" value=\"$g_TermDisplay{$trk}{$trm}\"></td>";
	    print "<td class=\"la\"><input type=\"text\" name=\"date:$trk:$trm\" ";
	    print "size=\"12\" value=\"$g_MTrackTerm{$trk}{$trm}{'start'}\"></td>";
	}
	print "</tr>\n";
    }

    # Default Track Selection
    print "<tr><td class=\"bra\">$lex{Default} $lex{Track}</td>";
    for my $trk ( 1 .. $arr{tracks} ) {
	if ( $trk == $g_DefaultTrack ) { 
	    print "<td class=\"cn\"><input type=\"radio\" name=\"defaulttrack\" value=\"$trk\" ";
	    print "checked=\"checked\"></td><td></td>";
	} else {
	    print "<td class=\"cn\"><input type=\"radio\" name=\"defaulttrack\" value=\"$trk\">";
	    print "</td><td></td>\n";
	}
    }
    print "</tr>\n";


    print "<tr><td colspan=\"2\" class=\"ra\"><input type=\"submit\" value=\"$lex{Continue}\"></td></tr>\n";
    print "</table></form>\n";

    print "</body></html>\n";

    exit;

}


#------------
sub setTracks {
#------------

    # Set Mapping of Grades to School, Track End dates, TermDisplayBlock values (ie. semester)
    # foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }


    # Read in values from conf_system;
    my $sth = $dbh->prepare("select datavalue from conf_system
      where dataname = ? and filename = 'admin'");
    foreach my $dataname qw( g_MTrackTermType g_TermDisplayBlock ) { # load values.
	$sth->execute( $dataname );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $datavalue = $sth->fetchrow;
	eval $datavalue;
	if ( $@ ) {
	    print $lex{Error}. " $@<br>\n";
	    die $lex{Error}. " $@\n";
	}
    }


    # Form / Table Start
    print "<form action=\"$self\" method=\"post\">\n";
    print "<input type=\"hidden\" name=\"page\" value=\"3\">\n";


    # School Year
    print "<p style=\"font-weight:bold;\">$lex{'School Year'} $arr{schoolyear}</p>";


    # Start Table
    print "<table cellpadding=\"3\" cellspacing=\"0\" border=\"0\" ";
    print "style=\"border:1px solid gray;padding:0.5em;\">\n";
    print "<tr><td colspan=\"4\" style=\"font-size:130%;font-weight:bold;padding-top:0em;\">";
    print "$lex{Set} $lex{'End Date'}</td></tr>\n";

    # Display Term Start/End Dates and Tracks.
    # Track Descriptions Row
    print "<tr><td class=\"bla\">$lex{Terms}</td>\n";
    for my $trk ( 1 .. $arr{tracks} ) {
	my $trkkey = "trkdesc:$trk";
	print "<td class=\"bcn\" colspan=\"2\">$lex{Track} $trk: $arr{$trkkey}</td>";
    }
    print "</tr>\n";

    # Start/End Date Descriptors
    print "<tr><td></td>\n";
    for my $trk ( 1 .. $arr{tracks} ) {
	print "<td class=\"cn\">$lex{'Start Date'}</td>";
	print "<td class=\"cn\">$lex{'End Date'}</td>";
    }
    print "</tr>\n";

    # Term Rows
    my $eoyflag; # flag use of end of year date
    for my $trm ( 1 .. $arr{terms} ) {
	my $termkey = "trmdesc:$trm";
	print "<tr><td class=\"bcn\">$trm</td>";
	for my $trk ( 1 .. $arr{tracks} ) {
	    my $sdatekey = "date:$trk:$trm";

	    if ( $arr{$sdatekey} ) { # if this track has start date, then do enddate;

		# Figure out next term start date;
		my $nextterm = $trm + 1;
		my $nextdatekey = "date:$trk:$nextterm";
		my $nextstart;
		if ( $arr{$nextdatekey} ) {
		    $nextstart = $arr{$nextdatekey};
		} else {
		    $nextstart = $arr{enddate}; # use school end date;
		    $eoyflag = 1;
		}
		
		my $enddate;
		if ( not $eoyflag ) { # use back one day from next term start.
		    my $nextstartjd = julian_day( split(/-/,$nextstart) );
		    $enddate = join('-', inverse_julian_day($nextstartjd - 1) );
		} else { # we are using eoy date  (schoolend)
		    $enddate = $arr{enddate};
		    $eoyflag = 0; 
		}

		print "<td class=\"cn\">$arr{$sdatekey}</td>";
		print "<td class=\"cn\"><input type=\"text\" name=\"edate:$trk:$trm\" ";
		print "size=\"12\" value=\"$enddate\"></td>";

	    } else { # delete and skip
		delete $arr{$sdatekey};
		print "<td colspan=\"2\"></td>";

	    }
	}
	print "</tr>\n";
    }
    print "</table>\n";


    # Map Grades to Tracks.
    my %map = ();
    foreach my $grade (sort {$a <=> $b} keys %g_MTrackTermType ) {
	my $trk = $g_MTrackTermType{$grade};
	if ( not exists $map{$trk} ) { 
	    $map{$trk} = "$grade ";
	} else {
	    $map{$trk} = $map{$trk}. "$grade ";
	}
    }
    print "<table cellpadding=\"3\" cellspacing=\"0\" border=\"0\" ";
    print "style=\"border:1px solid gray;padding:0.5em;\">\n";
    print "<tr><td colspan=\"4\" style=\"font-size:130%;font-weight:bold;\">";
    print "$lex{Map} $lex{Grades} -> $lex{Tracks}</td></tr>\n";
    print "<tr><th>$lex{Tracks}</th><th>$lex{Description}</th><th>$lex{Grades}</th></tr>\n";
    for my $trk ( 1..$arr{tracks} ) {
	my $key = 'trkdesc:'. $trk;
	print "<td class=\"bcn\">$trk</td><td>$arr{$key}</td>";
	print "<td><input type=\"text\" name=\"trkgrades:$trk\" size=\"12\" value=\"$map{$trk}\"></td></tr>\n";
	if ( $trk == 1 ) { # put in extra row
	    print "<tr><td></td><td></td><td class=\"cn\">$lex{'Separate with Spaces'}</td></tr>\n";
	}
    }

#    print "<tr><td colspan=\"3\" class=\"cn\">";
#    print "<input type=\"submit\" value=\"$lex{Continue}\"></td></tr>\n";
    print "</table>\n";



    # Set Term Display Block (ie. Semester, etc)
    print "<table cellpadding=\"3\" cellspacing=\"0\" border=\"0\" ";
    print "style=\"border:1px solid gray;padding:0.5em;\">\n";
    my @keys = sort keys %g_TermDisplayBlock;
    print "<tr><td colspan=\"4\" style=\"font-size:130%;font-weight:bold;padding-top:0em;\">";
    print "$lex{Set} $lex{'Term Block'} $lex{Description}</td></tr>\n";
    print "<tr><th>$lex{Start} $lex{Term}</th><th>$lex{End} $lex{Term}</th>";
    print "<th>$lex{Description}</th></tr>\n";

    for my $idx ( 1..$arr{terms} ) { # worst case scenario for number of desc required.
	my $key = shift @keys; # get value like '1-2'
	my $blockname = $g_TermDisplayBlock{$key};
	my ($sterm, $eterm) = split(/-/, $key);
	
	print "<tr><td class=\"cn\"><input type=\"text\" name=\"sterm:$idx\" size=\"4\" value=\"$sterm\"></td>\n";
	print "<td class=\"cn\"><input type=\"text\" name=\"eterm:$idx\" size=\"4\" value=\"$eterm\"></td>\n";
	print "<td><input type=\"text\" name=\"blkdesc:$idx\" size=\"12\" value=\"$blockname\"></td></tr>\n";
    }

    print "<tr><td colspan=\"3\" class=\"cn\">";
    print "<input type=\"submit\" value=\"$lex{Save}\"></td></tr>\n";
    print "</table>\n";

    # put rest of hidden values ( in %arr )
    foreach my $key ( keys %arr ) { # add passed values as hidden also.
	print "<input type=\"hidden\" name=\"$key\" value=\"$arr{$key}\">\n";
    }
    print "</form>\n";

    print "</body></html>\n";

    exit;

}



#---------------
sub writeRecords {
#---------------

    # print "Entry Keys:<br>\n";
    # foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }

    my %save = (); # records to store

    # School Start/End
    my $schoolstartEnc = setScalar( 'schoolstart', $arr{startdate} );
    # print "SchoolStart:$schoolstartEnc<br>\n";
    $save{schoolstart} = $schoolstartEnc;

    my $schoolendEnc = setScalar( 'schoolend', $arr{enddate} );
    # print "SchoolEnd:$schoolendEnc<br>\n";
    $save{schoolend} = $schoolendEnc;

    # School Year
    my $schoolyearEnc = setScalar( 'schoolyear', $arr{schoolyear} );
    # print "SchoolYear:$schoolyearEnc<br>\n";
    $save{schoolyear} = $schoolyearEnc;

    # Default Track
    my $g_DefaultTrackEnc = setScalar( 'g_DefaultTrack', $arr{defaulttrack} );
    # print "Default Track:$g_DefaultTrackEnc<br>\n";
    $save{g_DefaultTrack} = $g_DefaultTrackEnc;

    # g_MultiTrack
    my $mt = '0'; # multiTrack;
    if ( $arr{tracks} > 1 ) { $mt = '1';}
    my $g_MultiTrackEnc = setScalar( 'g_MultiTrack', $mt );
    # print "g_MultiTrack: $g_MultiTrackEnc<br>\n";
    $save{g_MultiTrack} = $g_MultiTrackEnc;



    # g_TermDisplay hash
    my %newhash = ();
    for my $trk ( 1..$arr{tracks} ) {
	for my $trm ( 1..$arr{terms} ) {
	    my $key = "trmdesc:$trk:$trm";
	    if ( $arr{$key} ) { $newhash{$trk}{$trm} = $arr{$key}; }
	}
    }
    my $g_TermDisplayEnc = setScalar( '*g_TermDisplay', \%newhash );
    # print "g_TermDisplay:$g_TermDisplayEnc<br>\n";
    $save{'g_TermDisplay'} = $g_TermDisplayEnc;


    # g_TermDisplayBlock hash
    my %newhash = ();
    for my $trm ( 1..$arr{terms} ) {
	my $key = 'blkdesc:'. $trm;
	my $datakey = $arr{"sterm:$trm"}. '-'. $arr{"eterm:$trm"};
	if ( $arr{$key} ) { $newhash{$datakey} = $arr{$key}; }
    }
    my $g_TermDisplayBlockEnc = setScalar('*g_TermDisplayBlock', \%newhash);
    # print "g_TermDisplayBlock: $g_TermDisplayBlockEnc<br>\n";
    $save{'g_TermDisplayBlock'} = $g_TermDisplayBlockEnc;


    # now do term blocks for each track ( first g_termstart, and
    # g_termend, MTrackTerm{Track}{Term}->{ start => sdate, end =>
    # edate }, MTrackType ( maps grades to tracks),

    # Set g_termstart,
    %newhash = ();
    my $trk = $arr{defaulttrack};
    for my $trm ( 1..$arr{terms} ) {
	my $key = "date:$trk:$trm";
	if ( $arr{$key} ) { $newhash{$trm} = $arr{$key}; }
    }
    my $g_termstartEnc = setScalar('*g_termstart', \%newhash);
    # print "g_termstart: $g_termstartEnc<br>\n";
    $save{'g_termstart'} = $g_termstartEnc;


    # Set g_termend,
    %newhash = ();
    my $trk = $arr{defaulttrack};
    for my $trm ( 1..$arr{terms} ) {
	my $key = "edate:$trk:$trm";
	if ( $arr{$key} ) { $newhash{$trm} = $arr{$key}; }
    }
    my $g_termendEnc = setScalar('*g_termend', \%newhash);
    # print "g_termend: $g_termendEnc<br>\n";
    $save{'g_termend'} = $g_termendEnc;

    

    # Set MTrackTerm
    my %newhash = ();
    for my $trk ( 1..$arr{tracks} ) {
	for my $trm ( 1..$arr{terms} ) {
	    my $sdatekey = "date:$trk:$trm";
	    my $edatekey = "edate:$trk:$trm";
	    if ( not $arr{$sdatekey} or not $arr{$edatekey} ) { next; }

	    my $dref = {};
	    $dref->{'start'} = $arr{$sdatekey};
	    $dref->{'end'} = $arr{$edatekey};
	    $newhash{$trk}{$trm} = $dref;
	}
    }
    my $g_MTrackTermEnc = setScalar('*g_MTrackTerm', \%newhash);
    # print "g_MTrackTerm: $g_MTrackTermEnc<br>\n";
    $save{'g_MTrackTerm'} = $g_MTrackTermEnc;



    # Set MTrackTermType
    %newhash = ();
    for my $trk ( 1..$arr{tracks} ) {
	my $key = 'trkgrades:'. $trk;
	my @grades = split(/\s/, $arr{$key});
	for my $grade (@grades) {
	    $newhash{$grade} = $trk;
	}
    }

    # populate empty hash if since track and no values.
    if ( not %newhash and $arr{tracks} == 1 ) { # put them all in one track
	my $sth = $dbh->prepare("select distinct grade from student 
          where grade is not NULL and grade != ''");
	$sth->execute;
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	while ( my $gr = $sth->fetchrow ) {
	    $newhash{$gr} = 1;
	}
    }

    my $g_MTrackTermTypeEnc = setScalar('*g_MTrackTermType', \%newhash);
    # print "g_MTrackTermType: $g_MTrackTermTypeEnc<br>\n";
    $save{'g_MTrackTermType'} = $g_MTrackTermTypeEnc;



    # Set Track Description g_TrackDisplay
    %newhash = ();
    for my $trk ( 1..$arr{tracks} ) {
	my $key = 'trkdesc:'. $trk;
	if ( $arr{$key} ) {
	    $newhash{$trk} = $arr{$key};
	}
    }

    if ( not %newhash and $arr{tracks} == 1  ) {
	$newhash{'1'} = 'All';
    }

    my $g_TrackDisplayEnc = setScalar('*g_TrackDisplay', \%newhash);
    # print "g_TrackDisplay: $g_TrackDisplayEnc<br>\n";
    $save{'g_TrackDisplay'} = $g_TrackDisplayEnc;


#    print "Records to Save:<br>\n";
#    foreach my $key ( sort keys %save ) { print "K:$key V:$save{$key}<br>\n"; }




    # Save the records into conf_system
    my $sth = $dbh->prepare("update conf_system set datavalue = ? 
      where dataname = ? and filename = 'admin'");
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    foreach my $dataname ( keys %save ) {
	$sth->execute( $save{$dataname}, $dataname );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    }
    print "<h3>$lex{'Record(s) Stored'}</h3>\n";




    # Write the admin.conf file.
    my $filename = "$g_EtcPath/admin.conf";

    system("cp -f $g_EtcPath/admin.conf.root $g_EtcPath/admin.conf");
    # print "Result:", $? >> 8, "<br>\n";

    open(FH,">>$filename") or
	die "Cannot open file $filename: $!\n"; # open for append

    my $sth = $dbh->prepare("select id, datavalue from conf_system 
     where filename = 'admin' order by dataname");
    $sth->execute;
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    while ( my ($id, $value) = $sth->fetchrow ) {
	print FH $value, "\n";
    }

    print FH "\n1;\n";
    close FH;

    print "<h3>admin.conf $lex{File} $lex{Updated}</h3>\n";
    

    print "</body></html>\n";

    exit;
}


#------------
sub setScalar {
#------------

    my ($dataname, $datavalue) = @_;

    my $name_ref = [ ];
    my $value_ref = [ ];
    push @$name_ref, $dataname;
    push @$value_ref, $datavalue;
    my $d = Data::Dumper->new( $value_ref, $name_ref );
    return $d->Dump;

}



