package WebPAC::Input::XML;

use warnings;
use strict;

use WebPAC::Input;
use base qw/WebPAC::Common/;

use XML::Simple;
use File::Find;
use File::Slurp;

use Data::Dump qw/dump/;

=head1 NAME

WebPAC::Input::XML - support for reading XML files

=cut

our $VERSION = '0.02';

=head1 FUNCTIONS

=head2 new

Returns new low-level input API object

  my $input = new WebPAC::Input::XML(
  	path => '/path/to/XML/records.txt'
	filter => sub {
		my ($l,$field_nr) = @_;
		# do something with $l which is line of input file
		return $l;
	},
	mungle => 'conf/mungle/xml-mungle.pl',
  }

Options:

=over 4

=item path

path to directory with xml files ending in C<.xml>

=item mungle

path to perl data_structure mungler which will be called to pre-normalize
hash produced by this module.

It's ugly and souldn't be really here, but I didn't wanted to write separate
input module for each possible XML in the face of the earth, and having perl
power to transform hash is just... Best solution :-)

=back

=cut

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

	my $arg = {@_};

warn "#### arg = ",dump( $arg );

	my $log = $self->_get_logger();

	$log->logdie("can't find path ", $arg->{path}, ": $!\n") unless -d $arg->{path};

	$log->info("collecting xml files from ", $arg->{path});

	my @files;

	find({
		wanted => sub {
			my $path = $File::Find::name;
			return unless -f $path && $path =~ m/\.xml$/i;
			push @files, $path;
		},
		follow => 1,
	}, $arg->{path} );

	$log->info("found ", $#files + 1, " XML files in ", $arg->{path});

	$self->{_files} = [ sort @files ];

	if ( my $path = $arg->{mungle} ) {
		$log->logdie("can't find $path: $!") unless -r $path;
		$log->info("using $path as mungle rules");

		$self->{mungle_rules} = read_file( $path ) || $log->logdie("can't open $path: $!");
	}

	$self ? return $self : return undef;
}

=head2 fetch_rec

Return record with ID C<$mfn> from database

  my $rec = $input->fetch_rec( $mfn, $filter_coderef );

=cut

sub fetch_rec {
	my $self = shift;

	my ( $mfn, $filter_coderef ) = @_;

	my $path = $self->{_files}->[ $mfn - 1 ] || return;

	my $log = $self->_get_logger();

	our $xml = XMLin(
		$path,
#		ForceArray => 1,
#		ForceContent => 1,
		KeepRoot => 1,
#		SuppressEmpty => 1, # '' undef

	) || $log->logdie("can't open $path: $!");

	$log->debug("fetch_rec( $mfn ) => $path => xml is ",sub { dump($xml) });

	our $ds;

	if ( my $rules = $self->{mungle_rules} ) {

		sub get_ds {
			warn "### get_ds xml = ",dump($xml);
			return $xml;
		}
		sub set_ds {
			my $hash = {@_};
			warn "### set_ds hash = ",dump($hash);
			foreach my $f ( keys %$hash ) {
				warn "+++ $f ", dump( $hash->{$f} ),"\n";
				$ds->{$f} = $hash->{$f};
			}
			warn "### set_ds mungle_ds = ",dump($ds);
		}
		eval "$rules";
		$log->logdie("mungle rules $path error: $@") if $@;

		warn "### set_ds after mungle_rules ds = ",dump($ds);
	} else {

		$ds = $xml;
	
	}

	# add mfn
	$ds->{'000'} = [ $mfn ];

	return $ds;
}


=head2 size

Return number of records in database

  my $size = $input->size;

=cut

sub size {
	my $self = shift;
	return $#{$self->{_files}} + 1;
}

=head1 AUTHOR

Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>

=head1 COPYRIGHT & LICENSE

Copyright 2007 Dobrica Pavlinusic, All Rights Reserved.

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

=cut

1;
