package MARC::Validator::Plugin::Field020;

use base qw(MARC::Validator::Abstract);
use strict;
use warnings;

use Business::ISBN;
use Data::MARC::Validator::Report::Error 0.02;
use Data::MARC::Validator::Report::Plugin::Errors 0.02;
use English;
use Error::Pure::Utils qw(clean err_get);
use MARC::Leader;

our $VERSION = 0.21;

sub module_name {
	my $self = shift;

	return __PACKAGE__;
}

sub name {
	my $self = shift;

	return 'field_020';
}

sub process {
	my ($self, $marc_record) = @_;

	my $record_id = $self->{'cb_record_id'}->($marc_record);
	my @record_errors;

	my $leader_string = $marc_record->leader;
	my $leader = eval {
		MARC::Leader->new(
			'verbose' => $self->{'verbose'},
		)->parse($leader_string);
	};
	if ($EVAL_ERROR) {
		# Error in leader, not validate.
		clean();
		return;
	}

	my @isbn_fields = $marc_record->field('020');
	foreach my $isbn_field (@isbn_fields) {
		my $isbn = $isbn_field->subfield('a');
		if (! defined $isbn) {
			next;
		}
		my $isbn_obj = Business::ISBN->new($isbn);
		if (! defined $isbn_obj) {
			push @record_errors, Data::MARC::Validator::Report::Error->new(
				'error' => 'Bad ISBN in 020a field.',
				'params' => {
					'Value' => $isbn,
				},
			);
		} elsif (! $isbn_obj->is_valid) {
			$isbn_obj->fix_checksum;
			if (! $isbn_obj->is_valid) {
				push @record_errors, Data::MARC::Validator::Report::Error->new(
					'error' => 'Bad ISBN in 020a field after fixing of checksum.',
					'params' => {
						'Value' => $isbn,
					},
				);
			} else {
				push @record_errors, Data::MARC::Validator::Report::Error->new(
					'error' => 'Bad checksum of ISBN in 020a field.',
					'params' => {
						'Value' => $isbn,
					},
				);
			}
		} else {
			if ($isbn_obj->as_string ne $isbn) {
				if ($isbn =~ m/^[\d\-]+$/ms) {
					push @record_errors, Data::MARC::Validator::Report::Error->new(
						'error' => 'Bad ISBN in 020a field, bad formatting.',
						'params' => {
							'Value' => $isbn,
							'proposed_value' => $isbn_obj->as_string,
						},
					);
				} else {
					# Skip ISBD punctuations.
					if ($leader->descriptive_cataloging_form eq 'i') {
						my $new_isbn = $isbn_obj->as_string;
						if ($isbn !~ m/^$new_isbn\s*:?\s*$/ms) {
							push @record_errors, Data::MARC::Validator::Report::Error->new(
								'error' => 'Bad ISBN in 020a field, extra characters.',
								'params' => {
									'Value' => $isbn,
									'proposed_value' => $isbn_obj->as_string,
								},
							);
						}
					} else {
						push @record_errors, Data::MARC::Validator::Report::Error->new(
							'error' => 'Bad ISBN in 020a field, extra characters.',
							'params' => {
								'Value' => $isbn,
								'proposed_value' => $isbn_obj->as_string,
							},
						);
					}
				}
			}
		}
	}

	if (@record_errors) {
		push @{$self->{'errors'}},  Data::MARC::Validator::Report::Plugin::Errors->new(
			'errors' => \@record_errors,
			'filters' => $self->{'filters'},
			'record_id' => $record_id,
		);
	}

	return;
}

sub version {
	my $self = shift;

	return $VERSION;
}

1;

__END__
