#!/usr/bin/perl

use strict;
use warnings;

our $VERSION = 3.1;

=head1 NAME

save_config - 

=head1 DESCRIPTION

TBD

=cut

use Data::Dumper;
use Config::General;
use File::Find;
use File::Compare;
use Params::Validate qw(:all);
use Archive::Tar;

use FindBin qw($RealBin);

use lib "$RealBin/../lib";

use perfSONAR_PS::NPToolkit::Config::Version;
use perfSONAR_PS::NPToolkit::BackingStore::Config qw(parse_config);
use perfSONAR_PS::NPToolkit::BackingStore::Utils  qw(load_live_device mount_data_store);

my $CONF_FILE = "$RealBin/../etc/backingstore.conf";
my $CONF_DIRECTORY = "$RealBin/../etc/backingstore.conf.d";

my $data_store_location;
my $original_cd_location;

my ($status, $res);

($status, $res) = parse_config({ base_config_file => $CONF_FILE, config_directory => $CONF_DIRECTORY });
if ($status != 0) {
    print "Problem parsing configuration: $res";
    exit -1;
}

my $conf = $res;


($status, $res) = load_live_device();
if ($status != 0) {
    print "Problem loading original CD: $res";
    exit -1;
}

$original_cd_location = $res->{directory};

($status, $res) = mount_data_store();
if ($status != 0) {
    print "Couldn't find data store: $res";
    exit -1;
}

$data_store_location = $res->{directory};

unless ($conf->{config}) {
    print "No files or directories to save";
    exit -1;
}

if (ref($conf->{config}) ne "ARRAY") {
    $conf->{config} = [ $conf->{config} ];
}

if (ref($conf->{skip}) ne "ARRAY") {
    $conf->{skip} = [ $conf->{skip} ];
}

my %files_to_save = ();

# Find the list of all files in the 'config' entries (files or directories)
# that have changed.
foreach my $to_save (@{ $conf->{config} }) {
    if (! -e $to_save) {
        print "Couldn't find $to_save";
        next;
    }

    if (-d $to_save) {
        find ({ wanted => sub { if (compare_file({ filename => $File::Find::name })) { $files_to_save{$File::Find::name} = 1 } } }, ( $to_save ));
    }
    else {
        $status = compare_file({ filename => $to_save });
                if ($status) {
            $files_to_save{$to_save} = 1;
        }
    }
}

# Remove any files that match a 'skip' entry from the list to save
if ($conf->{skip}) {
    foreach my $file (keys %files_to_save) {
        foreach my $skip (@{ $conf->{skip} }) {
            if ($file =~ /$skip/) {
                delete ($files_to_save{$file}) if ($file =~ /$skip/);
                last;
            }
        }
    }
}

# Create a tarball of the configuration files
Archive::Tar->create_archive($data_store_location."/NPTools/".$conf->{configuration_tarball}, "COMPRESS_GZIP", keys %files_to_save);

if (open(VERSION, ">", $data_store_location."/NPTools/version")) {
    my $version_conf = perfSONAR_PS::NPToolkit::Config::Version->new();
    $version_conf->init();

    my $version = $version_conf->get_version();
    print VERSION $version;
    close(VERSION);
}

exit 0;

sub compare_file {
    my $parameters = validate( @_, { filename => 1 });

    my $filename      = $parameters->{filename};
    my $orig_filename = $original_cd_location."/".$filename;

    if (! -e $orig_filename) {
        return 1;
    }

    if (-l $filename and ! -l $orig_filename) {
        return 1;
    }

    if (-f $filename and ! -f $orig_filename) {
        return 1;
    }
    
    if (-d $filename and ! -d $orig_filename) {
        return 1;
    }

    if (-d $filename) {
        # ignore this case
        ;
    }
    elsif (-l $filename) {
        my $old_symlink = readlink($orig_filename);
        my $new_symlink = readlink($filename);

        return 1 if ($old_symlink ne $new_symlink);
    }
    elsif (-f $filename) {
        my $res = compare($filename, $orig_filename);

        return 1 if ($res != 0);
    }

    return 0;
}

__END__

=head1 SEE ALSO

L<Config::General>, L<FindBin>

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

Aaron Brown, aaron@internet2.edu

=head1 LICENSE

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

=head1 COPYRIGHT

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

All rights reserved.

=cut
