#!/usr/bin/perl -w -I ./lib ../lib

use strict;
use warnings;

=head1 NAME

psConfigureDaemon - Ask a series of questions to generate a configuration file.

=head1 DESCRIPTION

Ask questions based on a service to generate a configuration file.

=cut

use Config::General qw(ParseConfig SaveConfig);
use Sys::Hostname;
use English qw( -no_match_vars );
use Module::Load;
use File::Temp qw(tempfile);
use Term::ReadKey;
use Data::Dumper;
use Cwd;
use Date::Parse;

my $dirname =  '/etc/PingER';

my $was_installed = 0;
my $DEFAULT_FILE;
my $confdir;

if ( $was_installed ) {
    $confdir = "XXX_CONFDIR_XXX";
}
else {
    $confdir = '/etc/PingER';
}

$DEFAULT_FILE = $confdir . "/daemon.conf";

print " -- perfSONAR-PS Daemon Configuration --\n";
print " - [press enter for the default choice] -\n\n";

my $file = shift;

unless ( $file ) {
    $file = &ask( "What file should I write the configuration to? ", $DEFAULT_FILE, undef, '.+' );
}

my $tmp;
our $default_hostname = hostname();
our $hostname         = 'localhost';
our $db_name          = q{pingerMA};
our $db_port          = q{};
our $db_username      = 'pinger';
our $db_password      = 'pinger_pass';

my %config = ();
if ( -f $file ) {
    %config = ParseConfig( $file );
}

# make sure all the endpoints start with a "/".
if ( defined $config{"port"} ) {
    foreach my $port ( keys %{ $config{"port"} } ) {
        if ( exists $config{"port"}->{$port}->{"endpoint"} ) {
            foreach my $endpoint ( keys %{ $config{"port"}->{$port}->{"endpoint"} } ) {
                my $new_endpoint = $endpoint;

                if ( $endpoint =~ /^[^\/]/mx ) {
                    $new_endpoint = "/" . $endpoint;
                }

                if ( $endpoint ne $new_endpoint ) {
                    $config{"port"}->{$port}->{"endpoint"}->{$new_endpoint} = $config{"port"}->{$port}->{"endpoint"}->{$endpoint};
                    delete( $config{"port"}->{$port}->{"endpoint"}->{$endpoint} );
                }
            }
        }
    }
}
my $pre_input = '';
while ( 1 ) {
    my $input;
    print "1) Set global values for the PingER MA/MP\n";
    print "2) Add/Edit PingER endpoint\n";   
    print "3) Enable/Disable PingER  port/endpoint\n";
    print "4) PingER MP/MA storage cleanup\n";
    print "5) Save and Exit ( configuration is saved automatically when you select 1 - 4 )\n";
    print "6) Exit without Save\n";
    $input = &ask( "? ", q{}, undef, '[123456]' );

    if ( $input == 6 ) {
        exit( 0 );
    }
    elsif ( $input == 5 ) { 
        SaveConfig_mine( $file, \%config );
        print "\n";
        print "Saved config to $file\n";
        print "\n";
	exit( 0 );
    }
    elsif( $input == 4) { 
      SaveConfig_mine( $file, \%config ) if  $pre_input && $pre_input != 5;
      my @endpoints = ();
        foreach my $port ( sort keys %{ $config{"port"} } ) {
            next unless ( exists $config{"port"}->{$port}->{"endpoint"} );
            foreach my $endpoint ( sort keys %{ $config{"port"}->{$port}->{"endpoint"} } ) {
                push @endpoints, "$port$endpoint";
            }
        }
	  if ( $#endpoints > -1 ) {
            print "\n";
            print "Existing Endpoints: \n";
            my $len = $#endpoints;
            for my $i ( 0 .. $len ) {
                print " $i) $endpoints[$i]\n" if  $endpoints[$i] =~ /\/ma$/ms;
            }
            print "\n";
        }  
        do {
            $input = &ask( "Enter PingER endpoint to cleanup (for example as: 8075/perfSONAR_PS/services/pingerma) or select from a number from the above ", q{8075/perfSONAR_PS/services/pingerma}, undef, '^(\d+[\/].*|\d+)$' );
            if ( $input =~ /^\d+$/mx ) {
                $input = $endpoints[$input];
            }
        } while ( not( $input =~ /\d+[\/].*/mx ) ); 
        my ( $port, $endpoint );
        if ( $input =~ /(\d+)([\/].*)/mx ) {
            $port     = $1;
            $endpoint = $2;
        } 
	###print      "Port: $port Endpoint:  $endpoint \n" . Dumper ($config{"port"}->{$port}->{"endpoint"}->{$endpoint});
        cleanup_pinger( $config{"port"}->{$port}->{"endpoint"}->{$endpoint},  "pingerma" );  
    }
    elsif ( $input == 1 ) { 
        SaveConfig_mine( $file, \%config ) if  $pre_input && $pre_input != 5;
        $config{"max_worker_processes"}     = &ask( "Enter the maximum number of children processes (0 means infinite) ",                   "30",                                                         $config{"max_worker_processes"},     '^\d+$' );
        $config{"max_worker_lifetime"}      = &ask( "Enter number of seconds a child can process before it is stopped (0 means infinite) ", "300",                                                        $config{"max_worker_lifetime"},      '^\d+$' );
        $config{"disable_echo"}             = &ask( "Disable echo by default (0 for no, 1 for yes) ",                                       0,                                                            $config{"disable_echo"},             '^[01]$' );
        $config{"ls_instance"}              = &ask( "The LS for MAs to register with ",                                                     "http://packrat.internet2.edu:8005/perfSONAR_PS/services/LS", $config{"ls_instance"},              '(^http|^$)' );
        $config{"ls_registration_interval"} = &ask( "Interval between when LS registrations occur [in minutes] ",                           60,                                                           $config{"ls_registration_interval"}, '^\d+$' );
        $config{"root_hints_url"}           = &ask( "URL of the root.hints file ",                                                          "http://www.perfsonar.net/gls.root.hints",                    $config{"root_hints_url"},           '(^http|^$)' );
        $config{"root_hints_file"}          = &ask( "Where shold the root.hints file be stored ",                                           $confdir . "/gls.root.hints",                                 $config{"root_hints_file"},          '^\/' );
        $config{"reaper_interval"}          = &ask( "Interval between when children are repeaed [in seconds] ",                             20,                                                           $config{"reaper_interval"},          '^\d+$' );
        $config{"pid_dir"}                  = &ask( "Enter pid dir location ",                                                              "/var/run",                                                   $config{"pid_dir"},                  q{} );
        $config{"pid_file"}                 = &ask( "Enter pid filename ",                                                                  "ps.pid",                                                     $config{"pid_file"},                 q{} );
    }
    elsif ( $input == 3 ) {
        my @elements = ();
        my %status   = ();
        SaveConfig_mine( $file, \%config ) if  $pre_input && $pre_input != 5;
        foreach my $port ( sort keys %{ $config{"port"} } ) {
            next unless ( exists $config{"port"}->{$port}->{"endpoint"} );
            push @elements, $port;

            if ( exists $config{"port"}->{$port}->{"disabled"} and $config{"port"}->{$port}->{"disabled"} == 1 ) {
                $status{$port} = 1;
            }
        }

        foreach my $port ( sort keys %{ $config{"port"} } ) {
            next unless ( exists $config{"port"}->{$port}->{"endpoint"} );
            foreach my $endpoint ( sort keys %{ $config{"port"}->{$port}->{"endpoint"} } ) {
                push @elements, "$port$endpoint";
                if ( exists $config{"port"}->{$port}->{"endpoint"}->{$endpoint}->{"disabled"}
                    and $config{"port"}->{$port}->{"endpoint"}->{$endpoint}->{"disabled"} == 1 )
                {
                    $status{"$port$endpoint"} = 1;
                }
            }
        }

        if ( $#elements > -1 ) {
            print "\n";
            print "Select element to enable/disable: \n";
            my $len = $#elements;
            for my $i ( 0 .. $len ) {
                print " $i) $elements[$i] ";
                print " *" if exists $status{ $elements[$i] };
                print "\n";
            }
	    my $exit_num = $len+1;
	    print  " $exit_num) Exit";
            print "\n";
            print " * element is disabled\n";
            print "\n";

            do {
                $input = &ask( "Select a number from the above ", q{}, undef, '^\d+$' );
            } while ( $input > $exit_num );

            my $new_status;

            if ( $input < $exit_num ) {
	        if( exists $status{ $elements[$input] } ) {
                    $new_status = 0;
                }
                else {
                    $new_status = 1;
                }
            } 
	    elsif($input == $exit_num ) {
	       next;  
	    }
            print "\n";
            if ( $new_status ) {
                print "Disabling";
            }
            else {
                print "Enabling";
            }

            if ( $elements[$input] =~ /^(\d+)(\/.*)$/mx ) {
                print " endpoint " . $elements[$input] . "\n";
                $config{"port"}->{$1}->{"endpoint"}->{$2}->{"disabled"} = $new_status;
            }
            elsif ( $elements[$input] =~ /^(\d+)$/mx ) {
                print " port " . $elements[$input] . "\n";
                $config{"port"}->{$1}->{"disabled"} = $new_status;
            }
            print "\n";
        }
    }
    elsif ( $input == 2 ) { 
        SaveConfig_mine( $file, \%config ) if  $pre_input && $pre_input != 5;
        my @endpoints = ();
        foreach my $port ( sort keys %{ $config{"port"} } ) {
            next unless ( exists $config{"port"}->{$port}->{"endpoint"} );
            foreach my $endpoint ( sort keys %{ $config{"port"}->{$port}->{"endpoint"} } ) {
                push @endpoints, "$port$endpoint";
            }
        }

        if ( $#endpoints > -1 ) {
            print "\n";
            print "Existing Endpoints: \n";
            my $len = $#endpoints;
            for my $i ( 0 .. $len ) {
                print " $i) $endpoints[$i]\n";
            }
            print "\n";
        }

        do {
            $input = &ask( "Enter endpoint in form 'port/endpoint_path' (e.g. 8075/perfSONAR_PS/services/pingerma) or select from a number from the above ", q{8075/perfSONAR_PS/services/pingerma}, undef, '^(\d+[\/].*|\d+)$' );
            if ( $input =~ /^\d+$/mx ) {
                $input = $endpoints[$input];
            }
        } while ( not( $input =~ /\d+[\/].*/mx ) );

        my ( $port, $endpoint );
        if ( $input =~ /(\d+)([\/].*)/mx ) {
            $port     = $1;
            $endpoint = $2;
        }

        unless ( exists $config{"port"} ) {
            my %hash = ();
            $config{"port"} = \%hash;
        }

        unless ( exists $config{"port"}->{$port} ) {
            my %hash = ();
            $config{"port"}->{$port} = \%hash;
            $config{"port"}->{$port}->{"endpoint"} = ();
        }

        unless ( exists $config{"port"}->{$port}->{"endpoint"}->{$endpoint} ) {
            $config{"port"}->{$port}->{"endpoint"}->{$endpoint} = ();
        }

        my $valid_module = 0;
        my $module       = $config{"port"}->{$port}->{"endpoint"}->{$endpoint}->{"module"};
        if ( defined $module ) {
            if ( $module eq "perfSONAR_PS::Services::MA::PingER" ) {
                $module = "pingerma";
            }
            elsif ( $module eq "perfSONAR_PS::Services::MP::PingER" ) {
                $module = "pingermp";
            }
        }

        my %opts;
        do {
            $module = &ask( "Enter endpoint module [pingerma,pingermp] ", q{}, $module, q{} );
            $module = lc( $module );

            if (   $module eq "pingerma"
                or $module eq "pingermp" )
            {
                $valid_module = 1;
            }
        } while ( $valid_module == 0 );

        unless ( $hostname ) {
            $hostname = &ask( "Enter the external host or IP for this machine ", $hostname, $default_hostname, '.+' );
        }

        my $accesspoint = &ask( "Enter the accesspoint for this service ", "http://$hostname:$port$endpoint", undef, '^http' );

        if ( $module eq "pingerma" ) {
            $config{"port"}->{$port}->{"endpoint"}->{$endpoint}->{"module"}       = "perfSONAR_PS::Services::MA::PingER";
            $config{"port"}->{$port}->{"endpoint"}->{$endpoint}->{"service_type"} = "MA";
            config_pinger( $config{"port"}->{$port}->{"endpoint"}->{$endpoint}, $accesspoint, \%config, "pingerma" );
        }
        elsif ( $module eq "pingermp" ) {
            $config{"port"}->{$port}->{"endpoint"}->{$endpoint}->{"module"}       = "perfSONAR_PS::Services::MP::PingER";
            $config{"port"}->{$port}->{"endpoint"}->{$endpoint}->{"service_type"} = "MP";
            config_pinger( $config{"port"}->{$port}->{"endpoint"}->{$endpoint}, $accesspoint, \%config, "pingermp" );
        }
    }
    $pre_input = $input;
}

=head2 config_pinger

TBD

=cut

sub config_pinger {
    my ( $config, $accesspoint, $def_config, $modulename ) = @_;
    my $moduletype = ( $modulename =~ /ma$/ ? "MA" : "MP" );
    $config->{$modulename} = () unless exists $config->{$modulename};

    $config->{$modulename}->{"db_type"} = &ask( "Enter the database type to read from (sqlite,mysql) ", "mysql", $config->{$modulename}->{"db_type"}, '^(sqlite|mysql)$' );

    my $dirname = '/etc/PingER/db_config';

    if ( $config->{$modulename}->{"db_type"} eq "sqlite" ) {
        $config->{$modulename}->{"db_file"} = &ask( "Enter the filename of the SQLite database ", "pinger.db", $config->{$modulename}->{"db_file"}, '.+' );
        eval {
            require DBD::SQLite;
            require DBI;

            system( "sqlite3 $config->{$modulename}->{db_file} < $dirname/create_pingerMA_SQLite.sql" );

            my $dbh = DBI->connect(
                "dbi:SQLite:dbname=$config->{$modulename}->{db_file}",
                "", "",
                {
                    AutoCommit => 1,
                    RaiseError => 1
                }
            );
            $dbh->do( "INSERT into host (ip_name, ip_number, comments) values ('test_name', '1.0.0.1', 'test')" );

            if ( $dbh->err() ) { die "$DBI::errstr\n"; }
        };
        if ( $EVAL_ERROR ) {
            die " $EVAL_ERROR :: You have to install perl DBD::SQLite driver, run: sudo cpan -i 'DBD::SQLite' ";
        }
    }
    elsif ( $config->{$modulename}->{"db_type"} eq "mysql" ) {
        $config->{$modulename}->{db_name} = &ask( "Enter the name of the PingER MA/MP MySQL database ", $config->{pingerma}->{db_name} || $config->{pingermp}->{db_name} || $db_name, $config->{$modulename}->{db_name}, '.+' );
        $config->{$modulename}->{db_host} = 'localhost';
        $tmp = &ask( "Enter the port for the PingER MA/MP MySQL database (leave blank for the default) ", $db_port, $config->{$modulename}->{db_port}, '^\d*$' );
        $config->{$modulename}->{db_port} = $tmp if ( $tmp ne "" );
        $tmp = &ask( "Enter the username for the PingER MA/MP MySQL database (leave blank for default) ", $config->{pingerma}->{db_username} || $config->{pingermp}->{db_username} || $db_username, $config->{$modulename}->{db_username}, '' );
        $config->{$modulename}->{db_username} = $tmp if ( $tmp ne "" );
	$tmp = &ask( "Enter the password for the PingER MA/MP MySQL database (leave blank for default) ", $config->{pingerma}->{db_password} || $config->{pingermp}->{db_password} || $db_password, $config->{$modulename}->{"db_password"}, '' );
        $config->{$modulename}->{db_password} = $tmp if ( $tmp ne "" );
	##my $set_other =  $modulename eq 'pingermp'?'pingerma':'pingermp';
	##foreach my $db_var (qw/db_name db_port db_username db_password/) {
	##    $config->{$set_other}->{$db_var} = $config->{$modulename}->{$db_var};
	##}
        ReadMode 'noecho';
        my $root_pass = &ask( "Enter the 'root' password for the MySQL database  ", '', undef, '');
        ReadMode 'normal';
	my $yes_reset = &ask( "\nEnter 'yes' if you'd like to re-create PingER MA/MP database ( only needed ONCE for both MA and MP !)", '', undef, '');
        $config->{$modulename}->{db_password} = $tmp if ( $tmp ne "" );
        if($yes_reset =~  /yes/i) { 
            eval {
        	require DBD::mysql;
        	require DBI;
        	system( "mysql -u root -p'$root_pass' -e 'drop database if exists  $config->{$modulename}->{db_name}'" );
        	system( "mysql -u root -p'$root_pass' -e 'create  database  $config->{$modulename}->{db_name}'" );
        	print " DB created = $config->{$modulename}->{db_name} ...\n";
        	system( "mysql -u root -p'$root_pass' -e  \"grant all privileges on $config->{$modulename}->{db_name}.* to '$config->{$modulename}->{db_username}'\@'$config->{$modulename}->{db_host}' identified by '$config->{$modulename}->{db_password}'\"" );
        	print " DB privileges set for $config->{$modulename}->{db_username}\@$config->{$modulename}->{db_host}...\n";
        	system( "mysql -u root -p'$root_pass' -e 'flush privileges'" );
        	print " DB privileges flushed...\n";
        	system( "mysql -u $config->{$modulename}->{db_username} -p'$config->{$modulename}->{db_password}' -h $config->{$modulename}->{db_host} -D $config->{$modulename}->{db_name} < $dirname/create_pingerMA_MySQL.sql" );
        	print " DB tables created ...\n";
        	my $dbh = DBI->connect(
                    "dbi:mysql:host=$config->{$modulename}->{db_host};database=$config->{$modulename}->{db_name}",
                    $config->{$modulename}->{db_username},
                    $config->{$modulename}->{db_password},
                    {
                	AutoCommit => 1,
                	RaiseError => 1
                    }
        	);
        	$dbh->do( "INSERT into host (ip_name, ip_number, comments) values ('test_name', '1.0.0.1', 'test')" );

        	if ( $dbh->err() ) { die "$DBI::errstr\n"; }
		$dbh->disconnect();
            };
            if ( $EVAL_ERROR ) {
        	die " $EVAL_ERROR :: You have to install perl DBD::mysql driver, run: sudo cpan -i 'DBD::mysql' ";
            }
	} else {
	    print "\n Your PingER MA/MP DB has not been created or updated...\n"; 
	}
    }

    if ( $modulename eq "pingermp" ) {
        $config->{$modulename}->{"configuration_file"} = &ask( "Name of XML configuration file for landmarks and schedules ", "pinger-landmarks.xml", $config->{$modulename}->{"configuration_file"}, '.+' );
    }

    if ( $modulename eq "pingerma" ) {
        $config->{$modulename}->{"query_size_limit"} = &ask( "Enter the limit on query size ", "100000", $config->{$modulename}->{"query_size_limit"}, '^\d*$' );
    }

    $config->{$modulename}->{"enable_registration"} = &ask( "Will this service register with an LS (0,1) ", "0", $config->{$modulename}->{"enable_registration"}, '^[01]$' );

    if ( $config->{$modulename}->{"enable_registration"} eq "1" ) {
        my $registration_interval = $def_config->{"ls_registration_interval"};
        $registration_interval = $config->{$modulename}->{"ls_registration_interval"} if ( defined $config->{$modulename}->{"ls_registration_interval"} );
        $config->{$modulename}->{"ls_registration_interval"} = &ask( "Enter the number of minutes between LS registrations ", "30", $registration_interval, '^\d+$' );
    }
    $config->{$modulename}->{"service_name"} = &ask( "Enter a name for this service ", "PingER $moduletype", $config->{$modulename}->{"service_name"}, '.+' );

    $config->{$modulename}->{"service_type"} = &ask( "Enter the service type ", $moduletype, $config->{$modulename}->{"service_type"}, '.+' );

    $config->{$modulename}->{"service_description"} = &ask( "Enter a service description ", "PingER $moduletype on $default_hostname", $config->{$modulename}->{"service_description"}, '.+' );

    $config->{$modulename}->{"service_accesspoint"} = &ask( "Enter the service's URI ", $accesspoint, $config->{$modulename}->{"service_accesspoint"}, '^http:\/\/' );

}

=head2 cleanup_pinger

TBD

=cut

sub cleanup_pinger {
    my ( $config,    $modulename ) = @_;
    my $moduletype =   "MA";
    $config->{$modulename} = () unless exists $config->{$modulename};

    $config->{$modulename}->{"db_type"} = &ask( "Enter the database type to read from (sqlite,mysql) ", "mysql", $config->{$modulename}->{"db_type"}, '^(sqlite|mysql)$' );

    my $dirname = '/etc/PingER/db_config';
    my $date =  &ask( "\nEnter date as mm-dd-yyyy ( example: 06-01-2009 ) to delete all records older than that", '', undef, '^\d\d\-\d\d\-\d{4}$');           
    unless($date) {
     print " No cleanup because date have not been entered...\n";
     return;
    }
    my $dbh = '';
    if ( $config->{$modulename}->{"db_type"} eq "sqlite" ) {      
        eval {
            require DBD::SQLite;
            require DBI;

            $dbh = DBI->connect(
                "dbi:SQLite:dbname=$config->{$modulename}->{db_file}",
                "", "",
                {
                    AutoCommit => 1,
                    RaiseError => 1
                }
            );
            $dbh->disconnect();
        };
        if ( $EVAL_ERROR || $dbh->err) {
            die " $EVAL_ERROR :: You have to install perl DBD::SQLite driver, run: sudo cpan -i 'DBD::SQLite' ";
        }
    }
    elsif ( $config->{$modulename}->{"db_type"} eq "mysql" ) {       
            eval {
        	require DBD::mysql;
        	require DBI;
                my $tmp = &ask( "Enter the username for the PingER MA/MP MySQL database (leave blank for default) ", $config->{pingerma}->{db_username} || $config->{pingermp}->{db_username} || $db_username, $config->{$modulename}->{db_username}, '' );
                $config->{$modulename}->{db_username} = $tmp if ( $tmp ne "" );
		$tmp = &ask( "Enter the password for the PingER MA/MP MySQL database (leave blank for default) ", $config->{pingerma}->{db_password} || $config->{pingermp}->{db_password} || $db_password, $config->{$modulename}->{"db_password"}, '' );
                $config->{$modulename}->{db_password} = $tmp if ( $tmp ne "" );
        	$dbh = DBI->connect(
        	    "dbi:mysql:host=$config->{$modulename}->{db_host};database=$config->{$modulename}->{db_name}",
        	    $config->{$modulename}->{db_username},
        	    $config->{$modulename}->{db_password},
        	    {
        		AutoCommit => 1,
        		RaiseError => 1
        	    }
        	);
     	 	$date = str2time($date);
     	 	my @tables = @{$dbh->selectall_arrayref("SHOW TABLES")};
        	foreach my $table_row ( @tables ) {
		  
		    my $table_name =  $table_row->[0];
		    print " Table :: $table_name   ";  
     	 	    my ($tb_y, $tb_mn) = $table_name   =~ /data_(\d{4})(\d{2})/;
		    next unless $tb_y &&  $tb_mn;
     	 	    my $start_time = str2time("$tb_mn-01-$tb_y");
     	 	    print " start_date ::$tb_mn-01-$tb_y \n";
     	 	    if ($date > $start_time) {
     	 		$dbh->do( "DELETE FROM $table_name WHERE timestamp < $date");
			  print " ... deleted ... \n";
     	 	    }
     	 	    ### some extra cleanup
     	 	    $dbh->do( "DELETE $table_name d FROM $table_name d join metaData m using(metaID) where m.ip_name_src = '-1'" );
     	 	}
     	 	### some extra cleanup
        	$dbh->do( "DELETE FROM  metaData  where ip_name_src = '-1'" );
        	 
     	 	$dbh->disconnect();
            };
            if ( $EVAL_ERROR || $dbh->err) {
        	die " $EVAL_ERROR :: You have to install perl DBD::mysql driver, run: sudo cpan -i 'DBD::mysql' or check DB";
            } 
    } 
    else {
        print "\n Found unsupported DB type: $config->{$modulename}->{db_type} in the config file, ONLY mysql and SQLite are supported ..\n"; 
    }
 
}

=head2 ask

TBD

=cut

sub ask {
    my ( $prompt, $value, $prev_value, $regex ) = @_;

    my $result;
    do {
        print $prompt;
        if ( defined $prev_value ) {
            print "[", $prev_value, "]";
        }
        elsif ( defined $value ) {
            print "[", $value, "]";
        }
        print ": ";
        local $| = 1;

        local $_ = <STDIN>;
        chomp;
        if ( defined $_ and $_ ne q{} ) {
            $result = $_;
        }
        elsif ( defined $prev_value ) {
            $result = $prev_value;
        }
        elsif ( defined $value ) {
            $result = $value;
        }
        else {
            $result = q{};
        }
    } while ( $regex and ( not $result =~ /$regex/mx ) );

    return $result;
}

=head2 SaveConfig_mine

TBD

=cut

sub SaveConfig_mine {
    my ( $file, $hash ) = @_;
    system( "cp -f $file $file.old" ) if ( -f $file );
    my $fh;

    if ( open( $fh, ">", $file ) ) {
        printValue( $fh, q{}, $hash, -4 );
        if ( close( $fh ) ) {
            return 0;
        }
    } 
    $hash = ParseConfig( $file );
    return -1;
}

=head2 printSpaces

TBD

=cut

sub printSpaces {
    my ( $fh, $count ) = @_;
    while ( $count > 0 ) {
        print $fh " ";
        $count--;
    }
    return;
}

=head2 printScalar

TBD

=cut

sub printScalar {
    my ( $fileHandle, $name, $value, $depth ) = @_;

    printSpaces( $fileHandle, $depth );
    if ( $value =~ /\n/mx ) {
        my @lines = split( $value, '\n' );
        print $fileHandle "$name     <<EOF\n";
        foreach my $line ( @lines ) {
            printSpaces( $fileHandle, $depth );
            print $fileHandle $line . "\n";
        }
        printSpaces( $fileHandle, $depth );
        print $fileHandle "EOF\n";
    }
    else {
        print $fileHandle "$name     " . $value . "\n";
    }
    return;
}

=head2 printValue

TBD

=cut

sub printValue {
    my ( $fileHandle, $name, $value, $depth ) = @_;

    if ( ref $value eq "" ) {
        printScalar( $fileHandle, $name, $value, $depth );

        return;
    }
    elsif ( ref $value eq "ARRAY" ) {
        foreach my $elm ( @{$value} ) {
            printValue( $fileHandle, $name, $elm, $depth );
        }

        return;
    }
    elsif ( ref $value eq "HASH" ) {
        if ( $name eq "endpoint" or $name eq "port" ) {
            foreach my $elm ( sort keys %{$value} ) {
                printSpaces( $fileHandle, $depth );
                print $fileHandle "<$name $elm>\n";
                printValue( $fileHandle, q{}, $value->{$elm}, $depth + 4 );
                printSpaces( $fileHandle, $depth );
                print $fileHandle "</$name>\n";
            }
        }
        else {
            if ( $name ) {
                printSpaces( $fileHandle, $depth );
                print $fileHandle "<$name>\n";
            }
            foreach my $elm ( sort keys %{$value} ) {
                printValue( $fileHandle, $elm, $value->{$elm}, $depth + 4 );
            }
            if ( $name ) {
                printSpaces( $fileHandle, $depth );
                print $fileHandle "</$name>\n";
            }
        }

        return;
    }
}

__END__
	
=head1 SEE ALSO

L<Config::General>, L<Sys::Hostname>, L<Data::Dumper>, L<English>,
L<Module::Load>, L<File::Temp>, L<Term::ReadKey>, L<Cwd>

To join the 'perfSONAR Users' mailing list, please visit:

  https://mail.internet2.edu/wws/info/perfsonar-user

The perfSONAR-PS subversion repository is located at:

  http://anonsvn.internet2.edu/svn/perfSONAR-PS/trunk

Questions and comments can be directed to the author, or the mailing list.
Bugs, feature requests, and improvements can be directed here:

  http://code.google.com/p/perfsonar-ps/issues/list

=head1 VERSION

$Id$

=head1 AUTHOR

Jason Zurawski, zurawski@internet2.edu
Aaron Brown, aaron@internet2.edu
Maxim Grigoriev, maxim_at_fnal_dot_gov

=head1 LICENSE

You should have received a copy of the Internet2 Intellectual Property Framework
along with this software.  If not, see
<http://www.internet2.edu/membership/ip.html>

=head1 COPYRIGHT

Copyright (c) 2004-2009, Internet2 and the University of Delaware

All rights reserved.

=cut
