package IO::Iron::IronCache::Policy;

## no critic (Documentation::RequirePodAtEnd)
## no critic (Documentation::RequirePodSections)
## no critic (Subroutines::RequireArgUnpacking

use 5.010_000;
use strict;
use warnings;

# Global creator
BEGIN {
    use parent qw( IO::Iron::PolicyBase ); # Inheritance
}

# Global destructor
END {
}


# ABSTRACT: Base package (inherited) for IronCache::Client package.

our $VERSION = '0.12_01'; # TRIAL VERSION: generated by DZP::OurPkgVersion


use Log::Any  qw{$log};
use Hash::Util 0.06 qw{lock_keys unlock_keys};
use Carp::Assert::More;
use English '-no_match_vars';
use Params::Validate qw(:all);
use Carp;
use Try::Tiny;



sub is_cache_name_alternatives {
    my $self = shift;
    my %params = validate(@_, { } ); # No parameters
    $log->tracef('Entering is_cache_name_alternatives(%s)', \%params);
    my $rval = !(
            defined $self->{'policy'}->{'definition'}->{'no_limitation'}
            && $self->{'policy'}->{'definition'}->{'no_limitation'} == 1
            );
    $log->tracef('Exiting is_cache_name_alternatives():%d', $rval);
    return $rval;
}


sub is_item_key_alternatives {
    my $self = shift;
    my %params = validate(@_, { } ); # No parameters
    $log->tracef('Entering is_item_key_alternatives(%s)', \%params);
    my $rval = !(
            defined $self->{'policy'}->{'definition'}->{'no_limitation'}
            && $self->{'policy'}->{'definition'}->{'no_limitation'} == 1
            );
    $log->tracef('Exiting is_item_key_alternatives():%d', $rval);
    return $rval;
}


sub cache_name_alternatives {
    my $self = shift;
    my %params = validate(@_, { } ); # No parameters
    $log->tracef('Entering cache_name_alternatives(%s)', \%params);

    my @alternatives = $self->alternatives( 'required_policy' => 'name' );

    $log->tracef('Exiting cache_name_alternatives():%s', \@alternatives);
    return @alternatives;
}


sub item_key_alternatives {
    my $self = shift;
    my %params = validate(@_, { } ); # No parameters
    $log->tracef('Entering item_key_alternatives(%s)', \%params);

    my @alternatives = $self->alternatives( 'required_policy' => 'item_key' );

    $log->tracef('Exiting item_key_alternatives():%s', \@alternatives);
    return @alternatives;
}


sub is_valid_cache_name {
    my $self = shift;
    my %params = validate(
        @_, {
            'name' => { type => SCALAR, }, # cache name.
        }
    );
    $log->tracef('Entering is_valid_cache_name(%s)', \%params);
    my $validity = 1;
    try {
        $log->tracef('is_valid_cache_name:Enter try/catch.');
        $self->validate_cache_name('name' => $params{'name'});
    }
    catch {
        $log->tracef('is_valid_cache_name:Caught exception.');
        croak $_ unless blessed $_ && $_->can('rethrow'); ## no critic (ControlStructures::ProhibitPostfixControls)
        if ( $_->isa('IronPolicyException') ) {
            $log->tracef('Caught IronPolicyException.');
            $validity = 0;
        }
    };
    $log->tracef('Exiting is_valid_cache_name():%d', $validity);
    return $validity;
}


sub validate_cache_name {
    my $self = shift;
    my %params = validate(
        @_, {
            'name' => { type => SCALAR, }, # cache name.
        }
    );
    $log->tracef('Entering validate_cache_name(%s)', \%params);
    $self->validate_with_policy(
            'policy' => 'name',
            'candidate' => $params{'name'});
    $log->tracef('Exiting validate_cache_name():[NONE]');
    return;
}


sub is_valid_item_key {
    my $self = shift;
    my %params = validate(
        @_, {
            'key' => { type => SCALAR, }, # cache name.
        }
    );
    $log->tracef('Entering is_valid_item_key(%s)', \%params);
    my $validity = 1;
    try {
        $log->tracef('is_valid_item_key:Enter try/catch.');
        $self->validate_item_key('key' => $params{'key'});
    }
    catch {
        $log->tracef('is_valid_item_key:Caught exception.');
        croak $_ unless blessed $_ && $_->can('rethrow'); ## no critic (ControlStructures::ProhibitPostfixControls)
        if ( $_->isa('IronPolicyException') ) {
            $log->tracef('Caught IronPolicyException.');
            $validity = 0;
        }
    };
    $log->tracef('Exiting is_valid_item_key():%d', $validity);
    return $validity;
}


sub validate_item_key {
    my $self = shift;
    my %params = validate(
        @_, {
            'key' => { type => SCALAR, }, # cache name.
        }
    );
    $log->tracef('Entering validate_item_key(%s)', \%params);
    $self->validate_with_policy(
            'policy' => 'item_key',
            'candidate' => $params{'key'});
    $log->tracef('Exiting validate_item_key():[NONE]');
    return;
}


# INTERNAL METHODS
# For use in the inheriting subclass

# This is a late binding to inherited method get_policies:
sub _THIS_POLICY { ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
    my $self = shift;
    my %params = validate(
        @_, {
            # No parameters.
        }
    );
    return 'cache';
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

IO::Iron::IronCache::Policy - Base package (inherited) for IronCache::Client package.

=head1 VERSION

version 0.12_01

=head1 SYNOPSIS

	# new() in the inheriting sub class.

	sub new {
		my ($class, $params) = @_;
		my $self = IO::Iron::IronCache::Policy->new();
		# Add more keys to the self hash.
		my @self_keys = (
				'caches',        # References to all objects created of class IO::Iron::IronCache::Cache.
				legal_keys(%{$self}),
		);
		unlock_keys(%{$self});
		lock_keys_plus(%{$self}, @self_keys);
		my @caches;
		$self->{'caches'} = \@caches;

		unlock_keys(%{$self});
		bless $self, $class;
		lock_keys(%{$self}, @self_keys);

		return $self;
	}

=for stopwords IronCache Params IronHTTPCallException Mikko Koivunalho timestamp cas Cas

=for stopwords NoIronPolicyException IronPolicyException

=head1 METHODS

=head2 is_cache_name_alternatives

=head2 is_item_key_alternatives

=head2 cache_name_alternatives

Return all possible cache name alternatives according to the current policy.

=over 8

[No parameters.]

=back

Return: list of cache name alternatives

Will throw NoIronPolicyException if there is no limit to the alternatives.

=head2 item_key_alternatives

Return all possible item key alternatives according to the current policy.

=over 8

[No parameters.]

=back

Return: list of item key alternatives

Will throw NoIronPolicyException if there is no limit to the alternatives.

=head2 is_valid_cache_name

Check if the cache name is valid according to the policy. Return 1/0.

=over 8

=item name string to verify.

=back

=head2 validate_cache_name

Same as above but if validation fails, throws IronPolicyException.
If valid, returns undefined.

=over 8

=item name string to verify.

=back

=head2 is_valid_item_key

Check if the item key is valid according to the policy. Return 1/0.

=over 8

=item key string to verify.

=back

=head2 validate_item_key

Same as above but if validation fails, throws IronPolicyException.
If valid, returns undefined.

=over 8

=item key string to verify.

=back

=head1 AUTHOR

Mikko Koivunalho <mikko.koivunalho@iki.fi>

=head1 BUGS

Please report any bugs or feature requests to bug-io-iron@rt.cpan.org or through the web interface at:
 http://rt.cpan.org/Public/Dist/Display.html?Name=IO-Iron

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2017 by Mikko Koivunalho.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

The full text of the license can be found in the
F<LICENSE> file included with this distribution.

=cut
