package Cpanel::Easy::Utils::Cache;

# cpanel - Cpanel/Easy/Utils/Cache.pm             Copyright(c) 2014 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
#
# Front-end for caching things to disk (e.g. HTTP responses)

use strict;
use warnings;
use Cpanel::CachedDataStore ();

our $DEFAULT_TIMEOUT = 3600;    # 1 hour (in seconds)

sub cache_name {
    my $self = shift;
    my $name = shift;
    return sprintf( '%s/%s.yaml', $self->{'cfg_cache_dir'}, $name );
}

sub init_cache {
    my $self = shift;
    my $dir  = $self->{'cfg_cache_dir'};

    # NOTE: assuming since we control this directory that
    # it's always going to be a directory and owned by root
    my $old = umask 0000;
    my $ret = -e $dir ? chmod( 0600, $dir ) : mkdir( $dir, 0600 );
    umask $old;

    return $ret;
}

sub set_cache {
    my $self = shift;
    my %args = @_;
    my @ret  = qw( 1 Ok );

    die "Programmer Error: Missing argument 'data'" unless defined $args{'data'};
    die "Programmer Error: Missing argument 'name'" unless defined $args{'name'};

    my $path = $self->cache_name( $args{'name'} );

    unless ( Cpanel::CachedDataStore::store_ref( $path, $args{'data'}, { cache_file => 0, mode => 0600 } ) ) {
        @ret = ( 0, $self->maketext( q{Failed to store cache: [_1]}, $path ) );
    }

    return @ret;
}

sub get_cache {
    my $self = shift;
    my %args = @_;
    my $ref;

    die "Programmer Error: Missing argument 'name'" unless defined $args{'name'};

    my $path = $self->cache_name( $args{'name'} );
    my $timeout = defined $args{'timeout'} ? $args{'timeout'} : $DEFAULT_TIMEOUT;

    if ( -e $path ) {
        my $elapsed = time() - ( stat(_) )[9];

        if ( $elapsed < $timeout ) {
            $ref = Cpanel::CachedDataStore::load_ref($path);
        }
    }

    return $ref;
}

1;

__END__

=head1 NAME

Cpanel::Easy::Utils::Cache

=head1 SYNOPSIS

An OO-interface that provides routines to help cache information to disk.  This
is nice to have when you need data to live through multiple instances of EasyApache.
It's essentially a wrapper around the cPanel & WHM module, Cpanel::CachedDataStore.

=head1 API

This section describes how to use these modules in EasyApache.

=head2 Cpanel::Easy::Utils::Cache::init_cache()

This sets up the cache directory.  It must be called at least once before using
any of the other API calls.  Please note, calling it more than once will not
hurt.  It defaults to looking at /var/cpanel/easy/apache/cache, as defined in the
Cpanel::Easy::Apache module.  You can override this directory by setting the
internal hash key $easy->{'cfg_cache_dir'}.

=head3 INPUT

N/A

=head3 OUTPUT

1 if successful, otherwise failure.

=head3 EXAMPLE

    if( $easy->init_cache() ) {
        print "yay!\n"
    }
    else {
        print "boo! :(\n"
    }

=head2 Cpanel::Easy::Utils::Cache::set_cache()

Call to store something in the cache.

=head3 INPUT

It takes a hash (not reference) as its argument.  There are two required arguments
in the hash:

=over 2

=item I<name>

This is a simple name that you can use later to retrieve the cached data.  It's
best to avoid special characters, since the name is used to write to a file on disk.

=item I<data>

This should be a reference to the data you want to cache.

=back

=head3 OUTPUT

Returns an array containing at least 2 values.  The first value will be a boolean
1 or 0 to indicate success or failure.  The other are strings as returned by
the maketext call.

=head3 EXAMPLE

    my %hash = ( 'a' => 1, 'b' => 2 );
    my ( $status, @msg ) = $self->set_cache( 'name' => 'foobar', 'data' => \%hash );
    print ( $status ? "All is well!\n" : "All is bad! @msg\n" );

=head2 Cpanel::Easy::Utils::Cache::get_cache()

Retrieves cached data

=head3 INPUT

It takes a hash (not reference) as its argument.  There is one required argument
and one optional argument in the hash:

=over 2

=item I<name> (required)

This is a simple name that you used to store the cached data.  It's best to avoid
special characters, since the name is used to access files on disk.

=item I<timeout> (optional)

This specifies the amount of time in seconds cached data can be accessed until
it is deemed stale.  If information is stale, it will be inaccessible.  If left
unspecified, it defaults to 1 hour (3600 seconds).

=back

=head3 OUTPUT

Returns a reference to the cached data.  If the cached data doesn't exist, or is
stale, undef is returned.

=head3 EXAMPLE

    use Data::Dumper;
    my $ref = $easy->get_cache( 'name' => 'foobar' );
    print Dumper( $ref );

=head2 Cpanel::Easy::Utils::Cache::cache_name()

Allows you to determine the path on disk where a cache is stored.

=head3 INPUT

A cache name (string), that's used by set_cache and get_cache.

=head3 OUTPUT

A string that represents the path of the cached file on disk.

=head3 EXAMPLE

    my $path = $easy->cache_name( 'foobar' );
    print "'foobar' is located at $path\n";

