package String::Validator::Common;

# ABSTRACT: Base Module for creating new String::Validator Modules.

use 5.008;
use strict;
use warnings;

our $VERSION = 1.00;


sub new {
    my $class = shift;
    my $self  = {@_};
    bless $self, $class;
    $self->{class} = $class;
    $self->_Init();
    return $self;
}

sub IncreaseErr {
    my $self = shift;
    $self->{errstring} .= "@_\n";
    $self->{error}++;
}

# Every time we get a new request
# these values need to be reset from the
# previous request.
sub _Init {
    my $self = shift;
    $self->{errstring} = '';
    $self->{error}     = 0;
    $self->{string}    = '';
}

sub Start {
    my ( $self, $string1, $string2 ) = @_;
    $self->_Init();

    # String comparison, must not fail if no string2 is provided.
    # string2 is also available for destructive operations.
    # Failing the string match alse necessitates immediate
    # error return as the other tests are meaningless as
    # we cannot know if either or neither string is the password.
    no warnings 'uninitialized';
    if ( 0 == length $string2 ) { }
    elsif ( $string1 ne $string2 ) {
        $self->IncreaseErr('Strings don\'t match.');
        return 99;
    }
    $self->{string} = $string1;
    return 0;
}

sub Length {
    my $self   = shift;
    my $string = $self->{string};
    if ( length( $self->{string} ) < $self->{min_len} ) {
        $self->IncreaseErr( "Length of "
              . length( $self->{string} )
              . " Does not meet requirement: Min Length "
              . $self->{min_len}
              . "." );
        return $self->{error};
    }
    if ( $self->{max_len} ) {
        if ( length( $self->{string} ) > $self->{max_len} ) {
            $self->IncreaseErr( "Length of "
                  . length( $self->{string} )
                  . " Does not meet requirement: Max Length "
                  . $self->{max_len}
                  . "." );
            return $self->{error};
        }
    }
    return 0;
}

sub CheckCommon {
    my ( $self, $string1, $string2 ) = @_;
    if ( $self->Start( $string1, $string2 ) ) {
        return $self->{error};
    }
    if ( $self->Length ) { return $self->{error} }
    return 0;
}

# Check serves as example, but more importantly lets
# us test the module.
# Takes 2 strings and runs Start.
# If the strings match it returns 0, else 1.
sub Check {
    my ( $self, $string1, $string2 ) = @_;
    my $started = $self->Start( $string1, $string2 );
    return $self->{error};
}

sub Errcnt {
    my $self = shift;
    return $self->{error};
}

sub Errstr {
    my $self = shift;
    return $self->{errstring};
}

sub IsNot_Valid {
    ( my $self, my $string1, my $string2 ) = @_;
    if   ( $self->Check( $string1, $string2 ) ) { return $self->{errstring} }
    else                                        { return 0 }
}

sub Is_Valid {
    ( my $self, my $string1, my $string2 ) = @_;
    if   ( $self->Check( $string1, $string2 ) ) { return 0 }
    else                                        { return 1 }
}

sub String {
    my $self = shift;
    return $self->{string};
}

# Serious todo version needs to return all SV class versions
# for loaded modules.
sub Version { return $VERSION }

# The lowercase version of methods.
sub errcnt      { my $self = shift; $self->Errcnt() }
sub errstr      { my $self = shift; $self->Errstr() }
sub isnot_valid { my $self = shift; $self->IsNot_Valid() }
sub is_valid    { my $self = shift; $self->Is_Valid() }
sub string      { my $self = shift; $self->String() }
sub version { &String::Validator::Common::Version() }


1;    # End of String::Validator::Common

__END__

=pod

=encoding UTF-8

=head1 NAME

String::Validator::Common - Base Module for creating new String::Validator Modules.

=head1 VERSION

version 1.00

=head1 DESCRIPTION

A base module for use in creating new String Validators.

=head1 NAME

String::Validator::Common - Routines shared by String::Validator Modules.

=head1 VERSION

version 1.00

=head1 String::Validator::Common Methods and Usage

Modules Using String Validator Common use its' new method and then extend the
attributes in their own new methods.

 use String::Validator::Common;
 sub new {
 my $class = shift ;
 my $self = { @_ } ;
 use base ( 'String::Validator::Common' ) ;
 unless ( defined $self->{ some_param } )
   { $self->{ some_param } = 'somedefault'; }
 ...
 bless $self , $class ;
 return $self ;
 }

=head1 Methods String::Validator::Common provides

=head2 errcnt, errstr, new, string, version

These methods are described in the String::Validator Master Module and implemented here.

=head2 Check

Check is a stub subroutine, that you will replace in any Validator Module you write
with the code to validate the string. Is_Valid and IsNot_Valid base their results on Check. Check returns $self->{error}, if there are no errors this will be 0. When you
replace Check in your Validator Module you should implement the same behaviour so that IsValid and IsNot_Valid work. 

=head2 IsNot_Valid

Takes a string and optionally a second string (if you want to make sure two copies of a string are identical as well). Runs the Check subroutine and returns $self->{errstring} if there is an error, otherwise it returns 0. This will evaluate to true if there was an error and false if the string was valid.

=head2 Is_Valid

Takes a string and optionally a second string (if you want to make sure two copies of a string are identical as well). Runs the Check subroutine and returns 1 if Check returned 0, and 0 if Check returned a true value. If you want ->Errcnt() count or ->Errstr you will need to request them via there methods before another string is processed.

=head2 IncreaseErr

A String::Validator contains two error variables error and errstring. When an
error is found, simply pass a brief description to this method to increment
the errorcount, and append the present description to the errstring.

 if ( 1 != 2 ) { $self->IncreaseErr( qq /1 Still Doesn't equal 2!/ ) }

=head2 Start

This method initializes three key values: $self->{errstring} ,
$self->{error}, and $self->{string} to NULL, 0, NULL. If no errors are found
error and errstring will remain 0 and NULL. string will be used to hold
the string being evaluated. Arguments are the
string to be evaluated and optionally a second string to be compared with the
first. If the strings are mismatched the sub will return 99, and string will
remain NULL, the inheriting module should immediately return the error and
not contine.

=head2 Length

Checks $self->{ string } against $self->{ min_length } and $self->{ max_length }
If the length checks pass it returns 0, if one fails it immediately returns
the incremented value of error.

=head2 CheckCommon

CheckCommon is just a shortcut to run Start and Length.

=head2 Errstr, Errcnt, String

Provides these methods for inheritance as described in the String::Validator documentation.

=head2 Version

Version returns the internal version number of the module.

=head2 version, is_valid, isnot_valid, errcnt, errstr

Allow LowerCase invokation of these methods.

=head1 AUTHOR

John Karr <brainbuz@brainbuz.org>

=head1 COPYRIGHT AND LICENSE

This software is Copyright (c) 2014 by John Karr.

This is free software, licensed under:

  The GNU General Public License, Version 3, June 2007

=cut
