package IO::Iron::IronCache::Item;

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

use 5.010_000;
use strict;
use warnings;

# Global creator
BEGIN {
    # No exports
}

# Global destructor
END {
}

# ABSTRACT: IronCache (Online Item-Value Storage) Client (Cache Item).

our $VERSION = '0.14'; # 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);

# CONSTANTS for this module

# DEFAULTS

sub new {
    my $class  = shift;
    my %params = validate(
        @_,
        {
            'value'      => { type => SCALAR, },                 # Item value (free text), mandatory, can be empty.
            'expires_in' => { type => SCALAR, optional => 1, }
            ,    # How long in seconds to keep the item in the cache before it is deleted.
            'expires' => { type => SCALAR, optional => 1, },    # When will the item be deleted. This is a date string.
                                                                # TODO Add expires into docs!
            'replace' => { type => SCALAR, optional => 1, },    # Only set the item if the item is already in the cache.
            'add'     => { type => SCALAR, optional => 1, },    # Only set the item if the item is not already in the cache.
            'cas'     => { type => SCALAR, optional => 1, },    # Cas value can only be set when the item is read from the cache.
        }
    );
    $log->tracef( 'Entering new(%s, %s)', $class, %params );
    my $self;
    my @self_keys = (    ## no critic (CodeLayout::ProhibitQuotedWordLists)
        'value',         # Item value (free text), can be empty.
        'expires_in',    # How long in seconds to keep the item in the cache before it is deleted.
        'expires',       # When will the item be deleted. This is a date string.
        'replace',       # Only set the item if the item is already in the cache.
        'add',           # Only set the item if the item is not already in the cache.
        'cas',           # Cas value can only be set when the item is read from the cache.
    );
    lock_keys( %{$self}, @self_keys );
    $self->{'value'}      = defined $params{'value'}      ? $params{'value'}      : undef;
    $self->{'expires_in'} = defined $params{'expires_in'} ? $params{'expires_in'} : undef;
    $self->{'expires'}    = defined $params{'expires'}    ? $params{'expires'}    : undef;
    $self->{'replace'}    = defined $params{'replace'}    ? $params{'replace'}    : undef;
    $self->{'add'}        = defined $params{'add'}        ? $params{'add'}        : undef;
    $self->{'cas'}        = defined $params{'cas'}        ? $params{'cas'}        : undef;

    # All of the above can be undefined, except the value.
    assert_defined( $self->{'value'}, 'self->{value} is defined and is not blank.' );

    # If timeout, add or expires_in are undefined, the IronMQ defaults (at the server) will be used.

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

    $log->tracef( 'Exiting new: %s', $blessed_ref );
    return $blessed_ref;
}

sub value      { return $_[0]->_access_internal( 'value',      $_[1] ); }
sub expires_in { return $_[0]->_access_internal( 'expires_in', $_[1] ); }
sub expires    { return $_[0]->_access_internal( 'expires',    $_[1] ); }
sub replace    { return $_[0]->_access_internal( 'replace',    $_[1] ); }
sub add        { return $_[0]->_access_internal( 'add',        $_[1] ); }
sub cas        { return $_[0]->_access_internal( 'cas',        $_[1] ); }

# TODO Move _access_internal() to IO::Iron::Common.

sub _access_internal {
    my ( $self, $var_name, $var_value ) = @_;
    $log->tracef( '_access_internal(%s, %s)', $var_name, $var_value );
    if ( defined $var_value ) {
        $self->{$var_name} = $var_value;
        return $self;
    }
    else {
        return $self->{$var_name};
    }
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

IO::Iron::IronCache::Item - IronCache (Online Item-Value Storage) Client (Cache Item).

=head1 VERSION

version 0.14

=head1 SYNOPSIS

Please see IO::Iron::IronCache::Client for usage.

=for stopwords IronCache Params IronHTTPCallException Mikko Koivunalho timestamp cas Cas

=head1 REQUIREMENTS

=head1 SUBROUTINES/METHODS

=head2 new

Creator function.

=head2 Getters/setters

Set or get a property.
When setting, returns the reference to the object.

=over 8

=item value        Item value (free text), can be empty.

=item expires_in   How long in seconds to keep the item in the cache before it is deleted.

=item expires      Time of expiration as a timestamp.

=item replace      Only set the item if the item is already in the cache.

=item add          Only set the item if the item is not already in the cache.

=item cas          Cas value can only be set when the item is read from the cache.

=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) 2023 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
