#!/usr/bin/perl

# $Id: addbiblio.pl,v 1.52.2.58.2.1 2007/04/27 13:08:28 tipaul Exp $

# Copyright 2000-2002 Katipo Communications
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
# Suite 330, Boston, MA  02111-1307 USA

use strict;
use CGI;
use C4::Auth;
use C4::Output;
use C4::Interface::CGI::Output;
use C4::Biblio;
use C4::SearchMarc; # also includes Biblio.pm, SearchMarc is used to FindDuplicate
use C4::Context;
use C4::Koha; # XXX subfield_is_koha_internal_p
#use Smart::Comments;
use HTML::Template;
use MARC::File::USMARC;
use MARC::File::XML;
use MARC::Field;
use MARC::Record;
if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
	MARC::File::XML->default_record_format( 'UNIMARC' );
}
warn "--MARK--";
use vars qw( $tagslib);
use vars qw( $authorised_values_sth);
use vars qw( $is_a_modif );

my $itemtype; # created here because it can be used in build_authorized_values_list sub

=item find_value

    ($indicators, $value) = find_value($tag, $subfield, $record,$encoding);

Find the given $subfield in the given $tag in the given
MARC::Record $record.  If the subfield is found, returns
the (indicators, value) pair; otherwise, (undef, undef) is
returned.

=cut

sub find_value {
	my ($tagfield,$insubfield,$record,$encoding) = @_;
	my @result;
	my $indicator;
	if ($tagfield <10) {
		if ($record->field($tagfield)) {
			push @result, $record->field($tagfield)->data();
		} else {
			push @result,"";
		}
	} else {
		foreach my $field ($record->field($tagfield)) {
			my @subfields = $field->subfields();
			foreach my $subfield (@subfields) {
				if (@$subfield[0] eq $insubfield) {
					push @result,@$subfield[1];
					$indicator = $field->indicator(1).$field->indicator(2);
				}
			}
		}
	}
	return($indicator,@result);
}


=item MARCfindbreeding

    $record = MARCfindbreeding($dbh, $breedingid);

Look up the breeding farm with database handle $dbh, for the
record with id $breedingid.  If found, returns the decoded
MARC::Record; otherwise, -1 is returned (FIXME).
Returns as second parameter the character encoding.

=cut

sub MARCfindbreeding {
	my ($dbh,$id) = @_;
	my $sth = $dbh->prepare("select file,marc,encoding from marc_breeding where id=?");
	$sth->execute($id);
	my ($file,$marc,$encoding) = $sth->fetchrow;
	if ($marc) {
		my $record = fixEncoding($marc);
		if (ref($record) eq undef) {
			return -1;
		} else {
			if (C4::Context->preference("z3950NormalizeAuthor") and C4::Context->preference("z3950AuthorAuthFields")){
				my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author");
# 				my $summary = C4::Context->preference("z3950authortemplate");
				my $auth_fields = C4::Context->preference("z3950AuthorAuthFields");
				my @auth_fields= split /,/,$auth_fields;
				my $field;
				#warn $record->as_formatted;
				if ($record->field($tag)){
					foreach my $tmpfield ($record->field($tag)->subfields){
#						foreach my $subfieldcode ($tmpfield->subfields){
						my $subfieldcode=shift @$tmpfield;
						my $subfieldvalue=shift @$tmpfield;
						if ($field){
							$field->add_subfields("$subfieldcode"=>$subfieldvalue) if ($subfieldcode ne $subfield);
						} else {
							$field=MARC::Field->new($tag,"","",$subfieldcode=>$subfieldvalue) if ($subfieldcode ne $subfield);
						}
					}
					#warn $field->as_formatted;
#					}
				}
				$record->delete_field($record->field($tag));
				foreach my $fieldtag (@auth_fields){
					next unless ($record->field($fieldtag));
					my $lastname = $record->field($fieldtag)->subfield('a');
					my $firstname= $record->field($fieldtag)->subfield('b');
					my $title = $record->field($fieldtag)->subfield('c');
					my $number= $record->field($fieldtag)->subfield('d');
					if ($title){
# 						$field->add_subfields("$subfield"=>"[ ".ucfirst($title).ucfirst($firstname)." ".$number." ]");
						$field->add_subfields("$subfield"=>ucfirst($title)." ".ucfirst($firstname)." ".$number);
					}else{
# 						$field->add_subfields("$subfield"=>"[ ".ucfirst($firstname).", ".ucfirst($lastname)." ]");
						$field->add_subfields("$subfield"=>ucfirst($firstname).", ".ucfirst($lastname));
					}
				}
				$record->insert_fields_ordered($field);
			}
# 			warn $record->as_formatted."";
			return $record,$encoding;
		}
	}
	return -1;
}


our ($sec, $min, $hour, $mday, $mon, $year, undef, undef, undef) = localtime(time);
$year +=1900;
$mon +=1;

our %creators = (
	'000@' => sub { '     nam a22     7a 4500' },
	'005@' => sub { sprintf('%4d%02d%02d%02d%02d%02d.0', $year, $mon, $mday, $hour, $min, $sec) },
	'008@' => sub { substr($year,2,2) . sprintf("%02d%02d", $mon, $mday) . 't        xxu||||| |||| 00| 0 eng d' },
);

=item build_authorized_values_list

=cut

sub build_authorized_values_list ($$$$$) {
	my($tag, $subfield, $value, $dbh,$authorised_values_sth) = @_;

	my @authorised_values;
	my %authorised_lib;

	# builds list, depending on authorised value...

	#---- branch
	if ($tagslib->{$tag}->{$subfield}->{'authorised_value'} eq "branches" ) {
	my $sth=$dbh->prepare("select branchcode,branchname from branches order by branchname");
	$sth->execute;
	push @authorised_values, ""
		unless ($tagslib->{$tag}->{$subfield}->{mandatory});

	while (my ($branchcode,$branchname) = $sth->fetchrow_array) {
		push @authorised_values, $branchcode;
		$authorised_lib{$branchcode}=$branchname;
	}

	#----- itemtypes
	} elsif ($tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes") {
		my $sth=$dbh->prepare("select itemtype,description from itemtypes order by description");
		$sth->execute;
		push @authorised_values, "" unless ($tagslib->{$tag}->{$subfield}->{mandatory});
	
		while (my ($itemtype,$description) = $sth->fetchrow_array) {
			push @authorised_values, $itemtype;
			$authorised_lib{$itemtype}=$description;
		}
		$value=$itemtype unless ($value);

	#---- "true" authorised value
	} else {
		$authorised_values_sth->execute($tagslib->{$tag}->{$subfield}->{authorised_value});

		push @authorised_values, "" unless ($tagslib->{$tag}->{$subfield}->{mandatory});
	
		while (my ($value,$lib) = $authorised_values_sth->fetchrow_array) {
			push @authorised_values, $value;
			$authorised_lib{$value}=$lib;
		}
    }
    return CGI::scrolling_list( -name     => 'field_value',
				-values   => \@authorised_values,
				-default  => $value,
				-labels   => \%authorised_lib,
				-override => 1,
				-size     => 1,
				-multiple => 0 );
}


sub build_tabs ($$$$) {
    my($template, $record, $dbh,$encoding) = @_;
    # fill arrays
    my @loop_data =();
    my $tag;
    my $i=0;
	my $authorised_values_sth = $dbh->prepare("select authorised_value,lib
		from authorised_values
		where category=? order by lib");
    
    # in this array, we will push all the 10 tabs
    # to avoid having 10 tabs in the template : they will all be in the same BIG_LOOP
    my @BIG_LOOP;
	my @HIDDEN_LOOP;

# loop through each tab 0 through 9
	foreach my $tag (sort(keys (%{$tagslib}))) {
		my $taglib = $tagslib->{$tag};
		my $indicator;
# if MARC::Record is not empty => use it as master loop, then add missing subfields that should be in the tab.
# if MARC::Record is empty => use tab as master loop.
		if ($record ne -1 && ($record->field($tag) || $tag eq '000')) {
			my @fields;
			if ($tag ne '000') {
				@fields = $record->field($tag);
			} else {
				push @fields,$record->leader();
			}
			foreach my $field (@fields)  {
				my $tag_writeout = "$tag ";
				$tag_writeout .= ($field->indicator(1) eq ' ' ? '_' : $field->indicator(1)) . ($field->indicator(1) eq ' ' ? '_' : $field->indicator(1)) . ' ' if ($tag>=10);
				my @subfields_data;
				if ($tag<10) {
					my ($value,$subfield);
					if ($tag ne '000') {
						$value=$field->data();
						$subfield="@";
					} else {
						$value = $field;
						$subfield='@';
					}
					next if ($tagslib->{$tag}->{$subfield}->{kohafield} eq 'biblio.biblionumber');
					my $subfieldlib = $taglib->{$subfield};

					if (($subfieldlib->{hidden} <= -4) or ($subfieldlib->{hidden}>=5) or ($taglib->{tab} == -1)) {
						my %row = (
							tag => $tag,
							subfield => $subfield,
							mandatory => $subfieldlib->{mandatory},
							kohafield => $subfieldlib->{kohafield},
							tag_mandatory => $taglib->{mandatory},
							field_value => $value
						);
						push @HIDDEN_LOOP, \%row;
						next;
					}

					push(@subfields_data, "$value");
					$i++;
				} else {
					my @subfields=$field->subfields();
					foreach my $subfieldcount (0..$#subfields) {
						my $subfield=$subfields[$subfieldcount][0];
						my $value=$subfields[$subfieldcount][1];
						my $subfieldlib = $taglib->{$subfield};
						next if (length $subfield !=1);
						next if ($subfieldlib->{tab} > 9 or $subfieldlib->{tab} == -1);
						push(@subfields_data, "\$$subfield $value");
						$i++;
					}
				}
# now, loop again to add parameter subfield that are not in the MARC::Record
				foreach my $subfield (sort( keys %{$tagslib->{$tag}})) {
					my $subfieldlib = $taglib->{$subfield};
					next if (length $subfield !=1);
					next if ($tag<10);
					next if (!$subfieldlib->{mandatory});
					next if ($subfieldlib->{tab} > 9 or $subfieldlib->{tab} == -1);
					next if (defined($field->subfield($subfield)));
					push(@subfields_data, "\$$subfield ");
					$i++;
				}
				if (@subfields_data) {
					$tag_writeout .= join(' ', @subfields_data);
					push (@BIG_LOOP, $tag_writeout);
				}
# If there is more than 1 field, add an empty hidden field as separator.
			}
# if breeding is empty
		} else {
			my $tag_writeout = "$tag ";
			$tag_writeout .= '__ ' if ($tag>=10);
			my @subfields_data;
			foreach my $subfield (sort(keys %{$tagslib->{$tag}})) {
				my $subfieldlib = $taglib->{$subfield};
				next if (length $subfield !=1);
				next if (!$subfieldlib->{mandatory});
				next if ($subfieldlib->{tab} > 9);

				if (ref($creators{$tag . $subfield}) eq 'CODE') {
					if (($subfieldlib->{hidden} <= -4) or ($subfieldlib->{hidden}>=5) or ($taglib->{tab} == -1)) {
						my %row = (
							tag => $tag,
							subfield => $subfield,
							mandatory => $subfieldlib->{mandatory},
							kohafield => $subfieldlib->{kohafield},
							tag_mandatory => $taglib->{mandatory},
							field_value => $creators{$tag . $subfield}(),
						);
						push @HIDDEN_LOOP, \%row;
						next;
					} else {
						push @subfields_data, $creators{$tag . $subfield}();
						next;
					}
				}

				if ($tag >= 10) {
					push @subfields_data, "\$$subfield";
				} else {
					push @subfields_data, "";
				}
				$i++;
			}
			next if (!@subfields_data);
			push (@BIG_LOOP, $tag_writeout . join(' ', @subfields_data));
		}
	}
# 		$template->param($tabloop."XX" =>\@loop_data);
	$template->param(
		BIG_LOOP => join("\n", @BIG_LOOP),
		HIDDEN_LOOP => \@HIDDEN_LOOP,
		record_length => $#BIG_LOOP,
	);
}

sub MARCtext2marc {
	my ($dbh, $text, $record) = @_;

	if (!$record) {
		$record = MARC::Record->new();
	}

	foreach my $line (split "\n", $text) {
		my $field;
		$line =~ s/^\s+$//g;
		next if not $line;

		if ($line =~ /^(00[0-9]) (.*)/) {
			$field = MARC::Field->new($0, $1);
		} elsif (my @tag_components = ($line =~ /^([0-9]{3}) (?:([0-9_ ])([0-9_ ]) )?(\$[a-z0-9](?:.*)?)/)) {
			my ($tag, $ind1, $ind2, $subfields) = @tag_components;
			my @subfields_data;

			foreach my $subfield (split(/\$(?=[a-z0-9] )/, $subfields)) {
				$subfield =~ s/(^\s+|\s+$)//g;
				$subfield =~ s/\s+/ /g;
				next if not $subfield;
				my ($name, $value) = split(' ', $subfield, 2);
				if ($value) {
					chomp $name; chomp $value;
					push @subfields_data, ($name, $value);
				}
			}

			next if not @subfields_data;
			
			$field = MARC::Field->new($tag,
				($ind1 eq '_' ? ' ' : $ind1),
				($ind2 eq '_' ? ' ' : $ind2),
				@subfields_data
			);
		} else {
			return "Did not understand \"$line\"";
		}
		$record->append_fields($field) if $field;
	}

	return $record;
}


sub build_hidden_data () {
    # build hidden data =>
    # we store everything, even if we show only requested subfields.

    my @loop_data =();
    my $i=0;
    foreach my $tag (keys %{$tagslib}) {
	my $previous_tag = '';

	# loop through each subfield
	foreach my $subfield (keys %{$tagslib->{$tag}}) {
	    next if ($subfield eq 'lib');
	    next if ($subfield eq 'tab');
	    next if ($subfield eq 'mandatory');
		next if ($subfield eq 'repeatable');
		if ($tag < 10) {
			next if (($tagslib->{$tag}->{$subfield}->{hidden}>-4) or ($tagslib->{$tag}->{$subfield}->{hidden}<5) ); #check for visibility flag
		} else {
		    next if ($tagslib->{$tag}->{$subfield}->{'tab'}  ne "-1");
		}
	    my %subfield_data;
	    $subfield_data{marc_lib}=$tagslib->{$tag}->{$subfield}->{lib};
	    $subfield_data{marc_mandatory}=$tagslib->{$tag}->{$subfield}->{mandatory};
	    $subfield_data{marc_repeatable}=$tagslib->{$tag}->{$subfield}->{repeatable};
	    $subfield_data{marc_value}="<input type=\"hidden\" name=\"field_value[]\">";
	    push(@loop_data, \%subfield_data);
	    $i++
	}
    }
}


# ======================== 
#          MAIN 
#=========================
my $input = new CGI;
my $error = $input->param('error');
my $oldbiblionumber=$input->param('oldbiblionumber'); # if bib exists, it's a modif, not a new biblio.
my $breedingid = $input->param('breedingid');
my $z3950 = $input->param('z3950');
my $op = $input->param('op');
my $frameworkcode = $input->param('frameworkcode');
my $dbh = C4::Context->dbh;
my $bibid;


if ($oldbiblionumber) {
	$bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$oldbiblionumber);
	# find framework type
	$frameworkcode = &MARCfind_frameworkcode($dbh,$bibid) if ($bibid and not ($frameworkcode));
}else {
	$bibid = $input->param('bibid');
	$frameworkcode = &MARCfind_frameworkcode($dbh,$bibid) if ($bibid and not ($frameworkcode));
}
$frameworkcode='' if ($frameworkcode eq 'Default');
my ($template, $loggedinuser, $cookie)
    = get_template_and_user({template_name => "acqui.simple/addbiblio-text.tmpl",
			     query => $input,
			     type => "intranet",
			     authnotrequired => 0,
			     flagsrequired => {editcatalogue => 1},
			     debug => 1,
			     });

#Getting the list of all frameworks
my $queryfwk =$dbh->prepare("select frameworktext, frameworkcode from biblio_framework");
$queryfwk->execute;
my %select_fwk;
my @select_fwk;
my $curfwk;
push @select_fwk,"Default";
$select_fwk{"Default"} = "Default";
while (my ($description, $fwk) =$queryfwk->fetchrow) {
	push @select_fwk, $fwk;
	$select_fwk{$fwk} = $description;
}
$curfwk=$frameworkcode;
my $framework=CGI::scrolling_list( -name     => 'Frameworks',
			-id => 'Frameworks',
			-default => $curfwk,
			-OnChange => 'Changefwk(this);',
			-values   => \@select_fwk,
			-labels   => \%select_fwk,
			-size     => 1,
			-multiple => 0 );
$template->param( framework => $framework);

$tagslib = &MARCgettagslib($dbh,1,$frameworkcode);
my $record=-1;
my $encoding="";
$record = MARCgetbiblio($dbh,$bibid) if ($bibid);
#warn "REC : ".$record->as_formatted;
($record,$encoding) = MARCfindbreeding($dbh,$breedingid) if ($breedingid);

$is_a_modif=0;
my ($oldbiblionumtagfield,$oldbiblionumtagsubfield);
my ($oldbiblioitemnumtagfield,$oldbiblioitemnumtagsubfield,$bibitem,$oldbiblioitemnumber);
if ($bibid) {
	$is_a_modif=1;
	# if it's a modif, retrieve old biblio and bibitem numbers for the future modification of old-DB.
	($oldbiblionumtagfield,$oldbiblionumtagsubfield) = &MARCfind_marc_from_kohafield($dbh,"biblio.biblionumber",$frameworkcode);
	($oldbiblioitemnumtagfield,$oldbiblioitemnumtagsubfield) = &MARCfind_marc_from_kohafield($dbh,"biblioitems.biblioitemnumber",$frameworkcode);
	# search biblioitems value
	my $sth=$dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
	$sth->execute($oldbiblionumber);
	($oldbiblioitemnumber) = $sth->fetchrow;
}
#------------------------------------------------------------------------------------------------------------------------------
if ($op eq "addbiblio") {
#------------------------------------------------------------------------------------------------------------------------------
	# rebuild
	my @tags = $input->param('tag');
	my @subfields = $input->param('subfield');
	my @values = $input->param('field_value');
	# build indicator hash.
	my @ind_tag = $input->param('ind_tag');
	my @indicator = $input->param('indicator');
	my $text_record = $input->param('record');
	if (C4::Context->preference('TemplateEncoding') eq "iso-8859-1") {
        my %indicators;
        for (my $i=0;$i<=$#ind_tag;$i++) {
            $indicators{$ind_tag[$i]} = $indicator[$i];
        }
		$record = MARChtml2marc($dbh,\@tags,\@subfields,\@values,%indicators);
# 		warn "RECORD : ".$record->as_formatted;
	} else {
		my $xml = MARChtml2xml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag);
		$record=MARC::Record->new_from_xml($xml,C4::Context->preference('TemplateEncoding'),C4::Context->preference('marcflavour'));
	}
	my $new_record = MARCtext2marc($dbh, $text_record, $record);
	my $error;
	#warn $record->as_formatted;
	#warn "IN ADDBIB";
	# check for a duplicate
	if (ref $new_record eq 'MARC::Record') {
		$record = $new_record;
	} else {
		$error = $new_record;
	}
	
	my ($duplicatebiblionumber,$duplicatebibid,$duplicatetitle) = FindDuplicate($record) if ($op eq "addbiblio") && (!$is_a_modif) && !$error;
	my $confirm_not_duplicate = $input->param('confirm_not_duplicate');
	# it is not a duplicate (determined either by Koha itself or by user checking it's not a duplicate)
	if ((!$duplicatebiblionumber or $confirm_not_duplicate) && !$error) {
		# MARC::Record built => now, record in DB
		my $oldbibnum;
		my $oldbibitemnum;
		if ($is_a_modif) {
			NEWmodbiblioframework($dbh,$bibid,$frameworkcode);
			NEWmodbiblio($dbh,$record,$bibid,$frameworkcode);
		} else {
			($bibid,$oldbibnum,$oldbibitemnum) = NEWnewbiblio($dbh,$record,$frameworkcode);
		}
	# now, redirect to additem page
		print $input->redirect("additem.pl?bibid=$bibid&frameworkcode=$frameworkcode");
		exit;
	} else {
	# it may be a duplicate, warn the user and do nothing
		build_tabs ($template, $record, $dbh,$encoding);
		if ($error) {
			$template->param(
				BIG_LOOP => $text_record,
				record_length => 30
			);
		}
		build_hidden_data;
		$template->param(
			oldbiblionumber             => $oldbiblionumber,
			bibid                       => $bibid,
			oldbiblionumtagfield        => $oldbiblionumtagfield,
			oldbiblionumtagsubfield     => $oldbiblionumtagsubfield,
			oldbiblioitemnumtagfield    => $oldbiblioitemnumtagfield,
			oldbiblioitemnumtagsubfield => $oldbiblioitemnumtagsubfield,
			oldbiblioitemnumber         => $oldbiblioitemnumber,
			duplicatebiblionumber		=> $duplicatebiblionumber,
			duplicatebibid				=> $duplicatebibid,
			duplicatetitle				=> $duplicatetitle,
			error              			=> $error,
			 );
	}
#------------------------------------------------------------------------------------------------------------------------------
} elsif ($op eq "delete") {
#------------------------------------------------------------------------------------------------------------------------------
	&NEWdelbiblio($dbh,$bibid);
	print "Content-Type: text/html\n\n<META HTTP-EQUIV=Refresh CONTENT=\"0; URL=/cgi-bin/koha/search.marc/search.pl?type=intranet\"></html>";
	exit;
#------------------------------------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------------------------------------
} else {
#------------------------------------------------------------------------------------------------------------------------------
	# If we're in a duplication case, we have to set to "" the bibid and biblionumber
	# as we'll save the biblio as a new one.
	if ($op eq "duplicate")
	{
		$bibid = "";
		$oldbiblionumber= "";
	}
	build_tabs ($template, $record, $dbh,$encoding);
	build_hidden_data;
	$template->param(
		oldbiblionumber             => $oldbiblionumber,
		bibid                       => $bibid,
		oldbiblionumtagfield        => $oldbiblionumtagfield,
		oldbiblionumtagsubfield     => $oldbiblionumtagsubfield,
		oldbiblioitemnumtagfield    => $oldbiblioitemnumtagfield,
		oldbiblioitemnumtagsubfield => $oldbiblioitemnumtagsubfield,
		oldbiblioitemnumber         => $oldbiblioitemnumber,
		);
}
$template->param(
		frameworkcode => $frameworkcode,
		itemtype => $frameworkcode, # HINT: if the library has itemtype = framework, itemtype is auto filled !
		hide_marc => C4::Context->preference('hide_marc'),
		intranetcolorstylesheet => C4::Context->preference("intranetcolorstylesheet"),
		intranetstylesheet => C4::Context->preference("intranetstylesheet"),
		IntranetNav => C4::Context->preference("IntranetNav"),
		advancedMARCEditor => C4::Context->preference("advancedMARCEditor"),
		);
output_html_with_http_headers $input, $cookie, $template->output;
