package Pica::Records;

use strict;
use warnings;
use Pica::Record;

use Data::Dumper;

our $SF = chr(131);

# Konstruktor kann mit dem Namen der zu parsenden Datei aufgerufen werden
sub new
{
  	my $class    = shift;
  	my $classref = ref($class) || $class;
  	my $self = {};
  	bless $self,$classref;
  	
  	$self->reset_counter;
  	
  	my $file = shift;
  	$self->parse($file) if ($file);

  	return $self;
}

# Downloaddatei parsen. Diese Methode wird i.d.R. von der Konstruktormethode aufgerufen
# Uebergabeparameter ist der Name der zu parsenden Datei. Existiert die Datei nicht,
# bricht das Skript ab.
sub parse
{
	my $self = shift;
	my $file = shift || die "Missing file name";
	
	if (-e $file)
	{
		# der erste Schritt erzeugt aus einer Downloaddatei in Pica+ ein Array mit Pica::Record Objekten
		# diese Objekte sind in $records als ARRAYREF gespeichert
		# Jeder Datensatz in der Downloaddatei muss mit dem Feld 001@ beginnen. Datensaetze, die nicht
		# mit 001@ beginnen werden in den vorhergehenden eingemischt.
		my $record = Pica::Record->new();
		my $records = [];
		
		# Downloaddatei oeffnen und zeilenweise einlesen
		open (FILE,"<$file") || die "Cannot open $file";
		while (my $line = <FILE>)
		{
			chomp $line;
			
			# Zeilen, die nicht mit einem PICA+ Feldbezeichner beginnen ignorieren
			if ($line =~ m/^\d{3}\D.*/)
			{
				# Bei 001@ beginnt immer ein neuer Datensatz
				if ($line =~ m/^001@.*/)
				{
					push @{$records},$record if ($record->id);
					$record = Pica::Record->new();
					$record->add_field($line);
				}
				
				# 002@ (0500) auswerten fuer den Datensatztyp
				elsif ($line =~ m/^002@.*/)
				{
					$record->type(substr($line,8,1));
					$record->add_field($line);
				}
				
				# Primaerschluessel (PPN) in 003@
				elsif ($line =~ m/^003@.*/)
				{
					$record->id(substr($line,7));
					$record->add_field($line);
				}
				
				# uebergeordneter Satz in 039B (bei As/Os-Saetzen) und 036F (bei Av/Ov-Saetzen)
				elsif (($line =~ m/^039B.*/) || ($line =~ m/^036F.*/))
				{
					$record->add_parent(substr($line,index($line,$SF.'9')+2,9));
					$record->add_field($line);
				}
				
				# In 031A (4070) steht in As/Os-Saetzen die Band- und Seitenangabe
				elsif ($line =~ m/^031A.*/)
				{
					$record->add_position($line);
					$record->add_field($line);
				}
				
				# alle anderen Felder fuer die spaetere Umwandlung nach MODS speichern
				else
				{
					$record->add_field($line);
				}
			}
		}
		push @{$records},$record;
		close FILE;
		
		# Im naechsten Schritt werden die Bandsaetze ermittelt und mit den jeweils ueber- (Ab/Ob) und
		# untergeordneten (As/Os) Saetzen verbunden. Der Bandsatz ist die Grundlage fuer die spaetere 
		# Erzeugung der METS-Saetze.
		# Saetze, die nicht einem in der Datei enthaltenen Bandsatz ueber- oder untergeordnet sind,
		# werden dabei verworfen
		my $volumes = [];
		my @all_records = @{$records};
		foreach my $record (@{$records})
		{
			if ($record->type eq 'v')
			{
				# in diesem Schritt werden nur Bandsaetze (v) verarbeitet
				foreach my $rec (@all_records)
				{
					# ein Satz ist moeglicherweise ein Kind des v-Satzes
					if ($rec->child_of($record->id))
					{
						$record->add_child($rec);
					}
					
					# oder das host item des v-Satzes
					elsif ($record->child_of($rec->id))
					{
						$record->hostitem($rec);
					}
				}
				# die s-Saetze in die richtige Reihenfolge bringen
				$record->sort_children;
				push @{$volumes},$record;
			}
		}
		# aufraeumen
		$records = undef;
		$self->{'data'} = $volumes;
	}
	else { die "No such file: $file"; }
	return 1;
}

# den naechsten Bandsatz im $self->{'data'} Array zurueckgeben und den internen Zaehler 
# um 1 erhoehen. Gibt es keinen weiteren Bandsatz wird undef zurueckgegeben
sub next_record
{
	my $self = shift;
	my $next_record = undef;
	if ($self->{'counter'} <= $#{$self->{'data'}})
	{
		my @volumes = @{$self->{'data'}};
		$next_record = $volumes[$self->{'counter'}];
		$self->{'counter'}++;
	}
	return $next_record;
}

# alle Datensaetze aus der Eingabedatei zurueckgeben
sub all_records
{
	my $self = shift;
	return $self->{'data'};
}

# den internen Zaehler fuer Bandsaetze auf 0 setzen
sub reset_counter
{
	my $self = shift;
	$self->{'counter'} = 0;
	return 1;
}
1;
# TODO 
# - Plausibilitaetspruefung, ob die Downloaddatei wirklich PICA+ enthaelt
# - Rueckmeldung ueber verworfene Datensaetze geben
# - sanfter Abbruch bei nicht vorhandener Downloaddatei