#!perl

use strict;
use warnings;

use CGI::Carp qw(fatalsToBrowser);

use CGI;
use File::Copy;
use File::Util;
use Template;
use XML::Simple;
use Data::Dumper;

use TCE::Config;


# global variables
our @messages;
our $go = 1;
our $shortened_imagemap = [];
our $shortened_structmap = [];


our $msg_ok = $TCE::Config::MSG_SYMBOLS{'ok'};
our $msg_fail = $TCE::Config::MSG_SYMBOLS{'fail'};
our $msg_warn = $TCE::Config::MSG_SYMBOLS{'warn'};

# create the File::Util object
my $fu = File::Util->new();

# create the CGI object
my $cgi = CGI->new();


#receive cgi parameter
my $goobi_file = $cgi->param('data')   || error($msg_fail.' Es wurde keine Goobidatei (METS) ausgewählt. Daher konnte keine Aktualisierung der Paginierungssequenz vorgenommen werden.');
my $item_id    = $cgi->param('itemid') || error($msg_fail.' Es wurde kein Vorgangstitel angegeben. Daher konnte keine Aktualisierung der Paginierungssequenz vorgenommen werden.');
my $action     = $cgi->param('action') || 'images';


# trim whitespaces in item_id
$item_id =~ s/ //g;

# backup existing files
mkdir $TCE::Config::ITEMS.$item_id.$TCE::Config::DATA_STORAGE{'backup_dir'} unless (-e $TCE::Config::ITEMS.$item_id.$TCE::Config::DATA_STORAGE{'backup_dir'});
copy($TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'goobi'},$TCE::Config::ITEMS.$item_id.$TCE::Config::DATA_STORAGE{'backup_dir'}.'/'.$TCE::Config::DATA_STORAGE{'goobi'});
copy($TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'images'},$TCE::Config::ITEMS.$item_id.$TCE::Config::DATA_STORAGE{'backup_dir'}.'/'.$TCE::Config::DATA_STORAGE{'images'});
copy($TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'pages'},$TCE::Config::ITEMS.$item_id.$TCE::Config::DATA_STORAGE{'backup_dir'}.'/'.$TCE::Config::DATA_STORAGE{'pages'});
copy($TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'stat_pages'},$TCE::Config::ITEMS.$item_id.$TCE::Config::DATA_STORAGE{'backup_dir'}.'/'.$TCE::Config::DATA_STORAGE{'stat_pages'});
copy($TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'externalId'},$TCE::Config::ITEMS.$item_id.$TCE::Config::DATA_STORAGE{'backup_dir'}.'/'.$TCE::Config::DATA_STORAGE{'externalId'});
copy($TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'struct'},$TCE::Config::ITEMS.$item_id.$TCE::Config::DATA_STORAGE{'backup_dir'}.'/'.$TCE::Config::DATA_STORAGE{'struct'});

# copy external METS file (Goobi file)
if ((-e $TCE::Config::GOOBI_HOME.$goobi_file) && $go)
{
	move $TCE::Config::GOOBI_HOME.$goobi_file, $TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'goobi'};
	message("$msg_ok Goobidatei (METS) erfolgreich in das Arbeitsverzeichnis kopiert");
	
	open FILE,'>'.$TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'externalId'};
      	print FILE Dumper $goobi_file;
      	close FILE;    
      
        message("$msg_ok Externe Vorgangsbenennung aktualisiert.");


	# try to delete the anchor file
	my $anchor_file = substr($goobi_file,0,index($goobi_file,'.xml')).'_anchor.xml';
	if (unlink $TCE::Config::GOOBI_HOME.$anchor_file) 
	{
		message ("$msg_ok Ankerdatei ".$anchor_file." gelöscht");
	} 
	else
	{
		message ("$msg_warn Versuch Ankerdatei ".$anchor_file." zu löschen war nicht erfolgreich");	
	}
}
elsif ($go)
{
	error("$msg_fail Goobidatei $goobi_file nicht gefunden. Daher konnte keine Aktualisierung der Paginierungssequenz vorgenommen werden.");
	$go = 0;
}

# read page sequence from XML File
if ($go)
{

    #extract information from goobi file
    my $xs = XML::Simple->new(ForceArray => 1, KeepRoot => 1);
    my $goobi_doc = $xs->XMLin($TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'goobi'});
    
    # extract structmaps, choose structmap/physical
    my @structmaps = @{$goobi_doc->{'mets:mets'}->[0]->{'mets:structMap'}};
    my @structmap = ();
    foreach my $s_map (@structmaps)
    {
    	@structmap = @{$s_map->{'mets:div'}->[0]->{'mets:div'}} if ($s_map->{'TYPE'} eq 'PHYSICAL');
    }
    
    
    foreach my $page (@structmap)
    {
    	my $newpage = {};
    	   $newpage->{'structId'} = $page->{'ID'};
    	   $newpage->{'order'}    = $page->{'ORDER'};
    	   $newpage->{'label'}    = $page->{'ORDERLABEL'};
    	   push @{$shortened_structmap},$newpage;
    }
    
    # store to disc
    open FILE,'>'.$TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'pages'};
    print FILE Dumper $shortened_structmap;
    close FILE;
    
    message("$msg_ok Paginierung zwischengespeichert.");
    
    # clear large data structures
    $goobi_doc = undef;
    $xs = undef;
}


# create new imagemap
if ($go)
{

    #extract information from goobi file
    my $xs = XML::Simple->new(ForceArray => 1, KeepRoot => 1);
    my $goobi_doc = $xs->XMLin($TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'goobi'});
    
    # extract fileGroups, choose fileGrp/default
    if ($goobi_doc->{'mets:mets'}->[0]->{'mets:fileSec'}->[0]->{'mets:fileGrp'})
    {
	    my @filegroups = @{$goobi_doc->{'mets:mets'}->[0]->{'mets:fileSec'}->[0]->{'mets:fileGrp'}};
	    my @filegroup = ();
	    foreach my $s_map (@filegroups)
	    {
	    	@filegroup = @{$s_map->{'mets:file'}} if ($s_map->{'USE'} eq 'DEFAULT');
	    }
	    
	    foreach my $page (@filegroup)
	    {
	    	push @{$shortened_imagemap},$page->{'mets:FLocat'}->[0]->{'xlink:href'};
	    }
	    unshift @{$shortened_imagemap},'http://localhost/tce/include/images/default.jpg';
	    
	    # store to disc
	    open FILE,'>'.$TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'images'};
	    print FILE Dumper $shortened_imagemap;
	    close FILE;
	
	    # store statistics to disc
	    open FILE,'>'.$TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'stat_pages'};
	    print FILE $#{$shortened_imagemap};
	    close FILE;
	    
	    message("$msg_ok Image URLs zwischengespeichert.");
	    
	    # clear large data structures
	    $goobi_doc = undef;
	    $xs = undef;
    }
    else
    {
    	message("$msg_warn Die eingelesene Goobi-Datei enthält keine Verweise auf Bilddateien. Möglicherweise haben Sie eine Ankerdatei eingelesen.");
    }
    
}


# change struct tree
if ($go)
{
	my $tree = read_file($TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'struct'});
	
	foreach my $elem (@{$tree})
	{
		my ($current_page) = grep($elem->{'endpage'}->{'structId'} eq $_->{'structId'},@{$shortened_structmap});
		if ($current_page->{'order'} == $elem->{'endpage'}->{'order'})
		{
			if ($current_page->{'label'} ne $elem->{'endpage'}->{'label'})
			{
				if ($action eq 'labelsonly')
				{
					$elem->{'endpage'}->{'label'} = $current_page->{'label'};
				}
				else
				{
					$elem->{'endpage'}->{'label'} = undef;
					$elem->{'endpage'}->{'order'} = undef;
					$elem->{'endpage'}->{'structId'} = undef;	
				}
			}
		}
		else
		{
			$elem->{'endpage'}->{'label'} = undef;
			$elem->{'endpage'}->{'order'} = undef;
			$elem->{'endpage'}->{'structId'} = undef;
		}
		
		($current_page) = grep($elem->{'startpage'}->{'structId'} eq $_->{'structId'},@{$shortened_structmap});
		if ($current_page->{'order'} == $elem->{'startpage'}->{'order'})
		{
			if ($current_page->{'label'} ne $elem->{'startpage'}->{'label'})
			{
				if ($action eq 'labelsonly')
				{
					$elem->{'startpage'}->{'label'} = $current_page->{'label'};
				}
				else
				{
					$elem->{'startpage'}->{'label'} = undef;
					$elem->{'startpage'}->{'order'} = undef;
					$elem->{'startpage'}->{'structId'} = undef;
				}
			}
		}
		else
		{
			$elem->{'startpage'}->{'label'} = undef;
			$elem->{'startpage'}->{'order'} = undef;
			$elem->{'startpage'}->{'structId'} = undef;
		}
	}
	
	# save data
      	open FILE, '>'.$TCE::Config::ITEMS.$item_id.'/'.$TCE::Config::DATA_STORAGE{'struct'};
      	print FILE Dumper $tree;
      	close FILE;
      	
      	message("$msg_ok Strukturbaum wurde angepasst.");
}

#output success/error messages to browser
my $template = Template->new({'INCLUDE_PATH' => $TCE::Config::TEMPLATES_DIR});
print $cgi->header( -type=>"text/html" );
$template->process('tce_updatePageSequence.tmpl',{'messages' => \@messages, 'success' => $go, 'itemid' => $item_id }) || die $template->error();	

exit(1);

sub error
{
	my $text = shift;
	push @messages, $text;
	$go = 0;
	return undef; 

}

sub message
{
	my $text = shift;
	push @messages, $text;
	return 1;
}

sub read_file
{
  my $filename = shift;
  open FILE, '<'.$filename;
  my @lines = <FILE>;
  close FILE;
  my $object = join('',@lines);
  my $VAR1;
  eval ($object);
  return $VAR1;	
}