#!/usr/bin/perl -w

BEGIN {
    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
    die "GSDL3HOME not set\n" unless defined $ENV{'GSDL3HOME'};
    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
    unshift (@INC, "$ENV{'GSDL3HOME'}/lib/perl/cpan");
}

use colcfg;
use util;
use parsargv;
use FileHandle;
use XML::Writer;

&main();
sub print_usage() {
    print STDOUT "Usage: convert_coll_from_gs2.pl [options] coll-name\n";
    print STDOUT "options:\n";
    
    print STDOUT "   -collectdir         Directory where collection lives.\n";
    print STDOUT "   -verbosity          Controls the amount of output.\n";
    print STDOUT "   -defaultlang        The language that is considered the default (for display text etc). defaults to 'en'\n\n";
}

sub main {

    my ($defaultlang, $verbosity, $collectdir);
    # note that no defaults are passed for most options as they're set
    # later (after we check the collect.cfg file)
    if (!&parsargv::parse(\@ARGV,
			  'verbosity/\d+/', \$verbosity,
			  'collectdir/.*/', \$collectdir,
			  'defaultlang/.*/', \$defaultlang)) {
	&print_usage();
	die "\n";
    }

    # get and check the collection name
    my ($collection) = @ARGV;
    if (!defined($collection) || $collection eq "") {
	die "No collection specified\n";
    }
    if ($collection eq "gs2model") {
	die "You cant convert the model collection\n";
    }
    
    if (!defined $collectdir || $collectdir eq "") {
	$collectdir = &util::filename_cat ($ENV{'GSDLHOME'}, "collect");
    }

    if (!defined $defaultlang || $defaultlang eq "") {
	$defaultlang = 'en';
    }
    # add on the coll name
    $collectdir = &util::filename_cat ($collectdir, $collection);
    
    $collconfigfilename = &util::filename_cat ($collectdir, "etc", "collect.cfg");
    print STDOUT "coll config=$collconfigfilename\n";
    my $collectcfg;
    if (-e $collconfigfilename) {
	$collectcfg = &colcfg::read_collect_cfg ($collconfigfilename);

    } else {
	print STDERR "collect.cfg not found!!";
	die "\n";
    }
    

    $buildconfigfilename = &util::filename_cat ($collectdir, "index", "build.cfg");
    my $buildcfg;
    if (-e $buildconfigfilename) {
	$buildcfg = &colcfg::read_build_cfg ($buildconfigfilename);

    } else {
	print STDERR "build.cfg not found!!";
	die "\n";
    }
    

     
    my $colloutfile = &util::filename_cat ($collectdir, "etc", "collectionConfig.xml");
    if (-e $colloutfile) {
	print STDOUT "collectionConfig file already exists! overwriting it!\n";
	
    }
   
    my $buildoutfile = &util::filename_cat ($collectdir, "index", "buildConfig.xml");
    if (-e $buildoutfile) {
	print STDOUT "buildConfig file already exists! overwriting it!\n";
	
    }

    my $buildtype;
    if (defined $buildcfg->{'buildtype'}) {
	$buildtype = $buildcfg->{'buildtype'};
    } else {
	$buildtype = 'mg';
    }
    
    my $buildoutput = new IO::File(">$buildoutfile");
    my $buildwriter = new XML::Writer(OUTPUT => $buildoutput, NEWLINES => 1);
    
    $buildwriter->startTag('buildConfig', 'xmlns:gsf'=>"http://www.greenstone.org/configformat");
    
    my $colloutput = new IO::File(">$colloutfile");
    my $collwriter = new XML::Writer(OUTPUT => $colloutput, NEWLINES => 1);
    
    $collwriter->startTag('collectionConfig', 'xmlns:gsf'=>"http://www.greenstone.org/configformat", 'xmlns:xsl'=>'http://www.w3.org/1999/XSL/Transform');
    
    #output the collection metadata to the collectionConfig file
    $collwriter->startTag('metadataList');
    
    my $creator = $collectcfg->{'creator'};
    &output_metadata($collwriter, 'creator', $creator);
    $collwriter->endTag('metadataList');

    #output the display collectionmeta to collectionConfig.xml
    
    my $collectionmeta = $collectcfg->{'collectionmeta'};
    if (defined $collectionmeta) {
	%name_map = ('collectionname', 'name',
		     'collectionextra', 'description',
		     'iconcollection', 'icon',
		     'iconcollectionsmall', 'smallicon');
	
	$collwriter->startTag('displayItemList');
	foreach $entry ( keys %$collectionmeta) {
	    if (defined $name_map{$entry}) {
		$name= $name_map{$entry};
		foreach $lang (keys %{$collectionmeta->{$entry}}) {
		    $value = $collectionmeta->{$entry}->{$lang};
		    if ($entry =~ /^icon/) {
			$value = format_icon_value($value);
		    }
		    &output_display($collwriter, $name, $lang, $value);
		}
	    }
	}
	$collwriter->endTag('displayItemList');
    } 
    
    # output building metadata to build config file 
    my $numdocs = $buildcfg->{'numdocs'};
    $buildwriter->startTag('metadataList');
    &output_metadata($buildwriter, 'numDocs', $numdocs);
    &output_metadata($buildwriter, 'buildType', $buildtype);
    $buildwriter->endTag('metadataList');
    
    
    #indexes
    my $indexmap = {};
    my $firstindex = "";
    my $first = 1;
    if (defined $buildcfg->{'indexmap'}) {
	$indexmap_t = $buildcfg->{'indexmap'};
	foreach $i (@$indexmap_t) {
	    my ($k, $v) = $i =~ /^(.*)\-\>(.*)$/;
	    $indexmap->{$k} = $v;
	    if ($first) {
		$firstindex = $v;
		$first = 0;
	    }	
	}
    } else {
	print STDERR "indexmap not defined";
    }
    my $defaultindex;
    if (defined $collectcfg->{'defaultindex'}) {
	$defaultindex = $collectcfg->{'defaultindex'};
	$defaultindex = $indexmap->{$defaultindex};
    } else {
	# use the first one
	$defaultindex = $firstindex;
    }
    
    # format stuff
    my $format = $collectcfg->{'format'};

    #output the search stuff to coll cfg
    $collwriter->startTag('search');
    foreach $i (keys %$indexmap) {
	$shortname = $indexmap->{$i};
	$collwriter->startTag('index', 'name'=>$shortname);
	#find the coll meta stuff
	$indexdisplay = ".$i";
	foreach $lang (keys %{$collectionmeta->{$indexdisplay}}) {
	    $value = $collectionmeta->{$indexdisplay}->{$lang};
	    output_display($collwriter, 'name', $lang, $value);
	}
	$collwriter->endTag('index');
	
    }

    # add in the format stuff
    if (defined $format->{'SearchVList'}) {
	
	$collwriter->startTag('format');
	write_format($collwriter, $format->{'SearchVList'});
	$collwriter->endTag('format');
    }
    
    $collwriter->endTag('search');
    
    $buildwriter->startTag('serviceRackList');
    
    my @levels = ();
    my $defaultlevel;
    
    #do the retrieve service
    # assume mgpp or mg 
    if ($buildtype eq 'mgpp') {
	#for each level
	if (defined $buildcfg->{'indexlevels'}) {
	    push @levels, @{$buildcfg->{'indexlevels'}};
	    
	    if (defined $buildcfg->{'textlevel'}) {
		$defaultlevel = $buildcfg->{'textlevel'};
	    } else {
		$defaultlevel = $levels[0];
	    }
	} else { #use levels from collect.cfg - must be an old collection
	    @levels = ('Document');
	    $defaultlevel = 'Document';
	    if (defined $collectcfg->{'levels'}) {
		foreach $l (@{$collectcfg->{'levels'}}) {
		    if ($l eq "Section") {
			$defaultlevel = 'Section';
		    }
		    push @levels, $l;
		}
	    }
	}
	
	$buildwriter->startTag('serviceRack', 'name'=>'GS2MGPPRetrieve');
	$buildwriter->emptyTag('defaultLevel', 'name'=>$defaultlevel);

	
    } else {
	$buildwriter->startTag('serviceRack', 'name'=>'GS2MGRetrieve');
	$buildwriter->emptyTag('defaultIndex', 'name'=>$defaultindex);
	
    }

    # add in the classifiers if needed

    my $count = 1;
    my $phind = 0;
    my $started_classifiers = 0;
    if (defined $collectcfg->{'classify'}) { 
	$collwriter->startTag('browse');
	my $classifiers = $collectcfg->{'classify'};
	foreach $cl (@$classifiers) {
	    $name = "CL$count";
	    $count++;
	    my ($classname) = @$cl[0];
	    if ($classname =~ /^phind$/i) {
		$phind=1;
		#should add it into coll config classifiers
		next;
	    }
	    
	    my $horizontalAtTop = "false";
	    if ($classname eq "AZList" || $classname eq "AZCompactList") { #there may be others
		$horizontalAtTop = "true";
	    }
	    if (not $started_classifiers) {
		$buildwriter->startTag('classifierList');
		$started_classifiers = 1;
	    }
	    my $content = ''; #use buttonname first, then metadata
	    if ($classname eq "DateList") {
		$content = "Date";
	    } else {
		for ($i=0; $i<scalar(@$cl); $i++) {
		    $arg = @$cl[$i];
		    if ($arg eq "-buttonname"){
			$content = @$cl[$i+1];
			last;
		    } elsif ($arg eq "-metadata") {
			$content = @$cl[$i+1];
		    }
		    
		}
	    }
	    if ($horizontalAtTop eq "false") {
		$buildwriter->emptyTag('classifier', 'name'=>$name, 'content'=>$content);
	    } else {
		$buildwriter->emptyTag('classifier', 'name'=>$name, 'content'=>$content, 'horizontalAtTop'=>'true');
	    }
	    
	    
	    $collwriter->startTag('classifier', 'name'=>$name);
	    $vlist = $name."VList";
	    $hlist = $name."HList";
	    $dlist = "";
	    if ($classname eq "DateList") {
		$dlist = "DateList";
	    }
	    if (defined $format->{$vlist} || defined $format->{"VList"}|| defined $format->{$hlist} || defined $format->{"HList"} || defined $format->{$dlist}) {
		$collwriter->startTag('format');
		if (defined $format->{$vlist}) {
		    write_format($collwriter, $format->{$vlist});
		} elsif (defined $format->{"VList"}) {
		    # use VList if no specific one
		    write_format($collwriter, $format->{"VList"});
		}
		if (defined $format->{$hlist}) {
		    write_format($collwriter, $format->{$hlist});
		} elsif (defined $format->{"HList"}) {
		    # use HList if no specific one
		    write_format($collwriter, $format->{"HList"});
		}
		if (defined $format->{$dlist}) {
		    write_format($collwriter, $format->{$dlist});
		}
		$collwriter->endTag('format');
	    }
	    $collwriter->endTag('classifier');
	} #foreach classifier
	if ($started_classifiers) {
	    # end the classifiers
	    $buildwriter->endTag('classifierList');
	}
	
	$collwriter->endTag('browse');
    }
    # close off the Retrieve service
    $buildwriter->endTag('serviceRack');
    
    # the phind classifier is a separate service
    if ($phind) {
	# if phind classifier
	$buildwriter->emptyTag('serviceRack', 'name'=>'PhindPhraseBrowse');
    }
   
    # do the search service
    if ($buildtype eq 'mgpp') {
		
	$buildwriter->startTag('serviceRack', 'name'=>'GS2MGPPSearch');
	$buildwriter->emptyTag('defaultLevel', 'name'=>$defaultlevel);
	$buildwriter->startTag('levelList');
	foreach $level (@levels) {
	    $buildwriter->emptyTag('level', 'name'=>$level);
	}
	$buildwriter->endTag('levelList');
	
	#fieldlist
	my $fieldmap = {};
	my $fieldlist = ();
	if (defined $buildcfg->{'indexfields'}) {
	    push @fieldlist, @{$buildcfg->{'indexfields'}};
	    if (defined $buildcfg->{'indexfieldmap'}) {
		$fieldmap_t = $buildcfg->{'indexfieldmap'};
		foreach $f (@$fieldmap_t) {
		    my ($k, $v) = $f =~ /^(.*)\-\>(.*)$/;
		    $fieldmap->{$k} = $v;
		}
	    }
	    $buildwriter->startTag('fieldList');
	    foreach $f (@fieldlist) {
		$field = $fieldmap->{$f};
		$buildwriter->emptyTag('field', 'shortname'=>$field, 'name'=>$f);
	    }	
	    $buildwriter->endTag('fieldList');
	} else {
	    print STDERR "indexfieldmap not defined";
	}

	# do the search types if there
	if (defined $collectcfg->{'searchtype'}) {
	    $buildwriter->startTag('searchTypeList');
	    foreach $st (@{$collectcfg->{'searchtype'}}) {
		$buildwriter->emptyTag('searchType', 'name'=>$st);
	    }
	    $buildwriter->endTag('searchTypeList');
	}
    } elsif ($buildtype eq 'mg') {
	$buildwriter->startTag('serviceRack', 'name'=>'GS2MGSearch');
    }
    
    
    $buildwriter->emptyTag('defaultIndex', 'name'=>$defaultindex);
    $buildwriter->startTag('indexList');
    #for each index
    foreach $i (keys %$indexmap) {
	$index = $indexmap->{$i};
	$buildwriter->emptyTag('index', 'name'=>$index);
    }	
    $buildwriter->endTag('indexList');
    
    $buildwriter->endTag('serviceRack');
    
    $buildwriter->endTag('serviceRackList');
    $buildwriter->endTag('buildConfig');
    $collwriter->endTag('collectionConfig');
    $collwriter->end();
    $buildwriter->end();
    $buildoutput->close();
    $colloutput->close();
}


sub output_metadata {
    my ($writer, $metaname,  $metavalue) = @_;
    $writer->startTag('metadata',  'name'=>$metaname);
    $writer->characters($metavalue);
    $writer->endTag('metadata');
}

sub output_display {
    my ($writer, $name, $lang, $value) = @_;
    $lang = 'en' if $lang eq 'default';
    if ($lang =~ /^\[/) {
	($lang) = $lang =~ /\[l=(.*)\]/;
    }
    $writer->startTag('displayItem', 'name'=>$name, 'lang'=>$lang);
    $writer->characters($value);
    $writer->endTag('displayItem');
}
sub format_icon_value {
    my ($value) = @_;
    if ($value =~ /^_/) {
	($newvalue) = $value =~ /\/([^\/]*)$/;
	if ($newvalue) {
	    return $newvalue;
	}
    }
    return $value;
}

sub write_format {
    my ($writer, $old_format) = @_;
    # replace \' with '
    $old_format =~ s/\\\'/\'/g;

    #convert [] to <gsf:...>
    #remove IFs, for now just make the first option true
    $old_format =~ s/\{If\}\{[^,]*,([^,\}]*)(,[^\}]*)?\}/$1/g;
    #remove ORs, for now just make the first option true
    $old_format =~ s/\{Or\}\{([^,]*),[^\}]*\}/$1/g;
    $old_format =~ s/\[Text\]/\<gsf:text\/\>/g;
    $old_format =~ s/\[num\]/\<gsf:num\/\>/g;
    $old_format =~ s/\[link\]/\<gsf:link\>/g;
    $old_format =~ s/\[\/link\]/\<\/gsf:link\>/g;
    $old_format =~ s/\[srclink\]/\<gsf:link type=\'source\'\>/g;
    $old_format =~ s/\[\/srclink\]/\<\/gsf:link\>/g;
    $old_format =~ s/\[icon\]/\<gsf:icon\/\>/g;
    $old_format =~ s/\[srcicon\]/\<gsf:icon type=\'source\'\/\>/g;

    #now do the rest of the [] which are assumed to be metadata
    $old_format =~ s/\[([^\]]*\:)?([^\]\:]*)\]/\<gsf:metadata name=\'$2\' select=\'$1\'\/\>/g;
    # remove ex.
    $old_format =~ s/<gsf:metadata name=\'ex\.([^\']+)\'/<gsf:metadata name=\'$1\'/g;
    #do the parent stuff
    $old_format =~ s/(select=\'parent)\:\'/$1\'/g;
    $old_format =~ s/select=\'parent\(Top\)\:\'/select=\'root\'/g;
    $old_format =~ s/select=\'parent\(All\)\:\'/select=\'ancestors\'/g;
    $old_format =~ s/select=\'parent\(All\'([^\']*)\'\)\:\'/select=\'ancestors\' separator=\'$1\'/g;
    #remove any select=''
    $old_format =~ s/select=\'\'//g;
    #turn <br> into <br />
    $old_format =~ s/\<br\>/\<br \/\>/g;
    #turn <p> into <p />
    $old_format =~ s/\<p\>/\<p \/\>/g;
    
    #put quotes around any atts
    $old_format =~ s/=([a-z]+)([> ])/=\'$1\'$2/g;

    $writer->startTag('gsf:template', 'match'=>'documentNode');
    $writer->charactersXML($old_format);
    $writer->endTag('gsf:template');

    
}

#$writer->startTag('');
#$writer->endTag('');
#$writer->characters();
#$writer->emptyTag('');

1;
