package EPrints::Plugin::Import::MARC;

=head1 NAME

EPrints::Plugin::Import::MARC -- allows to import MARC records

=head1 DESCRIPTION

This plugin allows you to import MARC and MARC XML records into GNU EPrints.

=head1 CONFIGURATION

Configuration might be changed in cfg.d/marc.pl. Webserver needs to be restarted after any configuration changes.

=head1 COPYRIGHT AND LICENSE

(C) 2008 Jose Miguel Parrella Romero <bureado@cpan.org>
(C) 2013 Dobrica Pavlinušić <dpavlin@rot13.org>
This module is free software under the same terms of Perl.

=cut

use Data::Dump qw(dump);

use Encode;
use strict;

our @ISA = qw/EPrints::Plugin::Import/;

sub new
{
	my( $class, %params ) = @_;

	my $self = $class->SUPER::new( %params );

	$self->{name} = "MARC";
	$self->{visible} = "all";
	$self->{produce} = [ 'list/eprint' ];

	my $rc = EPrints::Utils::require_if_exists("MARC::Record") and EPrints::Utils::require_if_exists("MARC::File::USMARC");
	unless( $rc ) 
	{
		$self->{visible} = "";
		$self->{error} = "Failed to load required modules.";
	}

	warn "XXX marc import with callbacks";

	return $self;
}

sub input_fh
{
	my( $plugin, %opts ) = @_;
	
	my @ids;
	my $file = MARC::File::USMARC->in( $opts{fh} );

	while ( my $marc = $file->next() ) {
		my $epdata = $plugin->convert_input( $marc );
		next unless( defined $epdata );

		my $dataobj = $plugin->epdata_to_dataobj( $opts{dataset}, $epdata );
		if( defined $dataobj )
		{
			push @ids, $dataobj->get_id;
		}
	}

	return EPrints::List->new( 
		dataset => $opts{dataset}, 
		session => $plugin->{session},
		ids=>\@ids );

	return undef;
}

sub input_file
{
	my( $plugin, %opts ) = @_;

	if( $opts{filename} eq '-' )
	{
		$plugin->error("Does not support input from STDIN");

		return undef;
	}

	my @ids;
	my $file = MARC::File::USMARC->in( $opts{filename} );

	while ( my $marc = $file->next() ) {
		my $epdata = $plugin->convert_input( $marc );
		next unless( defined $epdata );

		my $dataobj = $plugin->epdata_to_dataobj( $opts{dataset}, $epdata );
		if( defined $dataobj )
		{
			# Callback
			if ( my $code = $plugin->{session}->get_repository->get_conf( "marc" )->{dataobj_callback} ) {
				$epdata = $code->($dataobj);
			}

			push @ids, $dataobj->get_id;
		}
	}

	return EPrints::List->new( 
		dataset => $opts{dataset}, 
		session => $plugin->{session},
		ids=>\@ids );
}

our $debug;

sub convert_input 
{

	my ( $plugin, $marc ) = @_;
	my $epdata = (); # to be returned

	# Taken from cfg.d/marc.pl
        my %mappings = %{$plugin->{session}->get_repository->get_conf( "marc" )->{marc2ep}};

	my $dataset = $plugin->{session}->get_dataset('archive');

        foreach my $field ( $marc->fields() ) {             # each field of the record
		my $t = $field->tag();
		my @list = grep ( /^$t/, keys %mappings );  # lookup for mappings
		foreach my $i ( sort @list ) {
			( my $s ) = $i =~ /$t(.)/;          # mapped subfield
			my $ts = $t . $s;                   # complete tag+subfield
	                my $value = $field->as_string($s);

			my $field = $mappings{$ts} || $plugin->error("no mapping for $ts");
			my $metafield = $dataset->get_field($field);

			$plugin->error("no filed $field") unless $metafield;

			if ($metafield->get_property('multiple')) {
				warn "# multiple $field in ",ref( $metafield ), "inserting name" if ! $debug->{$field}++;
				$epdata->{$field} = [ { name => $value } ];
			} elsif ( defined $epdata->{$field} ) {
				$epdata->{$field} .= "\n" . $value;
			} else {
	                	$epdata->{$field} = $value; # bye!
			}
		}
        }

	# Authors
	my $field = $marc->field('100');
	if ( defined $field ) {
		foreach my $i ( $field->subfield('a') ) {
			my $name;
			( $name->{family}, $name->{given} ) = split ( "," , $i );
			push @{ $epdata->{creators_name} }, $name if defined $name;
		}
	}

	# Subjects
	if ( $plugin->{session}->get_repository->get_conf( "marc" )->{importSubjects} ) {

		if ( $field = $marc->field('650') ) {
			foreach my $i ( $field->subfield('a') ) {
				push @{ $epdata->{subjects} }, $i;
			}
		}

	}

	# Callback
	if ( my $code = $plugin->{session}->get_repository->get_conf( "marc" )->{epdata_callback} ) {
		$epdata = $code->($epdata);
	}

	return $epdata;

}

1;
