package PhotoPub::Album;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(&albumhtml);

use strict;

use PhotoPub::Global qw($error);
use PhotoPub::Range qw(&dispimg);
use PhotoPub::Handlers qw(&handlephoto &listhandlephoto);
use PhotoPub::Annots qw(&getannot);
use PhotoPub::Utils qw($pathre &slurp &doifcount &untaint &uri_escape
		       &handleparameters &includetag &excludetag
                       &handlepages &handletagoptions &photodatestr
		       &getlinkroot &getdefault &makeabsolutepath);
use PhotoPub::Search qw(&makesearchre &filteralbum);
use PhotoPub::Ages qw(&updateagefromfiles);
use PhotoPub::Images qw(&picrange);

use HTML::Entities;

sub rangelink {
  my ($otheroptions,$queryprefix,$params,$styleroot)=@_;
  my $rangelinkroot=&getlinkroot('range');
  &handletagoptions(\$queryprefix,$styleroot,$params);
  return '<a'.$otheroptions.'href="'.$rangelinkroot
            .'?'.$queryprefix.'">';
}

sub dispimgwithdefaults {
  my ($other,$photo,$extra)=@_;
  &dispimg($other,$photo,&getannot($photo,'options'),$extra);
}

sub albumhtml {
  my ($options,$printheader,$printout)=@_;

  my $debug=exists $options->{'debug'} ? $options->{'debug'} : 0;

  if( $debug >= 1 ) {
    # Do the headers early, so we can output to the browser soon
    # Might lead to some of the headers being wrong though
    &$printheader();
    print "<pre>\n";
  }

  my $album=$options->{'album'};
  $album=&getdefault('album') unless defined $album;
  &$error(type=>'userinput',message=>"album not given and no default defined")
    unless defined $album;

  &makeabsolutepath(\$album);

  my $style=$options->{'style'};
  $style=&handlephoto('albumstyle',$album) unless defined $style;
  $style=&getdefault('albumstyle') unless defined $style;
  &$error(type=>'userinput',message=>"style not given and no default defined")
    unless defined $style;

  my $albumtemplate=&handlephoto('albumtemplate',$style);

  my $search=$options->{'search'};
  my $searchre;
  $searchre=&makesearchre($search) if defined $search;

  &$error(type=>'userinput',message=>"Album style $style not defined")
    unless defined $albumtemplate;

  &updateagefromfiles($albumtemplate);

  if( $debug >= 2 ) { 
    print "Listing handle photo for $album\n";
  }

  my $items=&listhandlephoto('album',$album);

  if( $debug >= 2 ) {
    print "Done Listing\n";
    print "</pre>";
  }

  defined $items 
    or &$error(type => 'userinput', message => "Album $album not defined");

  my $template=&slurp($albumtemplate);
  
  defined $template
    or &$error(type => 'config', 
	       message => "Couldn't open template file $albumtemplate");

  my $title=&handlephoto('albumtitle',$album);

  # perhaps HTML should be stripped completely?
  if(defined $title) {
    &includetag('iftitle',\$template);
    &excludetag('ifnotitle',\$template);
    $template=~s/\$albumtitle/&encode_entities($title)/ieg;
  } else {
    &excludetag('iftitle',\$template);
    &includetag('ifnotitle',\$template);
    $template=~s/\$albumtitle//ig;
  }

  my @params=&handleparameters($options,\$template);
  
  # Handle the search now, before we do anything fancy
  &filteralbum($searchre,$items) if defined $search;

  # Handle ordering requests _before_ we handle pages
  my $reversed = 0;
  # order=reverse        => reverse the normal order
  if( $template =~ /\<repeat items order\=reverse\>/i ) {
    @$items = reverse(@$items);
    $reversed = 1;
  }
  # order=reversegroups  => only reverse the order of the group links
  # this isn't the most efficient of order options...
  if( $template =~ /\<repeat items order=reversegroups\>/i ) {
    my @linklist = ();
    my @grouplist = ();
    foreach my $item (@$items) {
      #    print "<p>Item is $item,Item Type is ".$item->{'type'}."</p>\n";
      if($item->{'type'} eq 'group') {
	unshift( @grouplist, $item );
      } elsif($item->{'type'} eq 'link') {
	push( @linklist, $item );
      } elsif($item->{'type'} eq '') {
	# Do nothing
      } else {
	&$error(type=>'internal',
		message=>"Unsupported item type \"".$item->{'type'}
		."\" found when processing order=reversegroups");
      }
    }
    # now add back
    @$items = (@linklist,@grouplist);
    $reversed = 1;
  }
  
  # Now split the list into multiple pages if requested to do so
  my ($startnum,$endnum)=(0,scalar(@$items)-1);
  
  #    Do proper blank album page here
  #    -------------------------------
  if($endnum == -1 ) {
    if(defined $search) {
      # Odds on, search didn't match
      &$error(type => 'userinput', message =>
	      "That album \($album\) with the specified search contains ".
	      "no entries - maybe the thing you're searching for isn't ".
	      "present, or maybe you specified an incorrect album?");
    } else {
      &$error(type => 'userinput', message =>
	      "That album \($album\) contains no entries - perhaps ". 
	      "you specified an incorrect album?");
    }
  }

  my $styleroot = substr( $style, 0, rindex( $style, '/' ) );

  # string for links to different pages of the same album, if needed
  my $albumquery;
  
  $albumquery=&getlinkroot('album').'?album='.&uri_escape($album);
  &handlepages($options,\$template,\$startnum,\$endnum,
	       sub {
		 foreach my $param (defined $options->{'style'} 
				    ? ('style') : (),
				    @params) {
		   $albumquery.='&amp;'.&uri_escape($param)
		     .'='.&uri_escape($options->{$param});
		 }
	       },
	       sub {
		 my ($pagenum)=@_;
		 return "$albumquery&amp;page=$pagenum";
	       });


  my ($pre,$repeat,$repeatop,$post);

  my $uristyle = &uri_escape($style) if $style;

  if( $debug >= 1 ) {
    $template=~s/\$album/\$album, start is $startnum, end is $endnum/gi;  
  }

  # Should we come up with a better way of doing this sort of substitution?
  # Perhaps have a list of allowed photopub internal variables to be 
  # exported, and iterate through these.

  $template=~s/\$album/$album/gi;

  &$printheader() if $debug==0;
  
  while(($pre,$repeatop,$repeat,$post)
	=($template=~/^(.*?)\<REPEAT ITEMS(.*?)\>(.*?)\<\/REPEAT\>(.*)$/si)) {

    if( $debug >= 1 ) {

      if( $repeat =~ /\$description/ ) {
	print "** repeat has a \$description **";
      }
      if( $pre =~ /\$description/ ) {
	print "** pre has a \$description **";
      }
      if( $post =~ /\$description/ ) {
	print "** post has a \$description **";
      }
    }

    &$printout($pre);
    my $count=1;
    my $oldlevel=0;
    my $out=undef;

    my @itemlist = ($startnum..$endnum);

    foreach my $itemnum (@itemlist) {
      my $item=$items->[$itemnum];
      my $text=$repeat;
      my $newlevel=$item->{'level'};

      if( $debug >= 1 ) {
	print "*** Processing item number $itemnum, item is $item ***<br>\n";
	print "    -> Item level is $newlevel<br>\n";
	print "    -> Item type is ".$item->{'type'}."<br>\n";
      }

      if(defined $out) {
	if( $debug >=2 ) {
	  print "    -> Item level was $oldlevel<br>\n";
	}
	my $upcount=$oldlevel-$newlevel>0 ? $oldlevel-$newlevel : 0;
	&includetag('ifnextuplevel',\$out,$upcount);
	my $downcount=$newlevel-$oldlevel>0 ? $newlevel-$oldlevel : 0;
	&includetag('ifnextdownlevel',\$out,$downcount);
	&$printout($out);
      }

      if($item->{'type'} eq 'group') {
	&includetag('ifgroup',\$text);
	&excludetag('iflink',\$text);
	my $urirange=&uri_escape($item->{'range'});
	my $desc=$item->{'description'};
	if( $debug >=2 ) {
	  print "    -> Range is $urirange<br>\n";
	  print "    -> Description is \"$desc\"<br>\n";
	}
	$out=$text;
	# This code sucks even more than some of the rest of 
	# the substitution stuff :-)
	my $queryprefix="range=$urirange";

	$out=~s{\<a(.*?)group(.*?)\>}
	  {&rangelink($1,$queryprefix,$2,$styleroot)}sieg;

	# Current policy is that if you want a style name with characters 
        # needing URI escaping, you do this yourself in the template file
	#      my $search = quotemeta $queryprefix;
	#      $out=~s/$search(.*)"\>/$queryprefix.&uri_escape($1).'">'/eg;

	$out=~s/\$description/$desc/ig;

	if( $out =~ /\$photocount/i || $out =~ /\<IFPHOTOS\>/i ||
	    $out =~ /\<NOPHOTOS\>/i || 
	    $out =~ /(?:first|last|rand|random)pic/i ) {
	  # Only go count if we've been asked to, on performance grounds
	  my @photos=&picrange($item->{'range'});
	  my $numphotos = scalar(@photos);
	  $out=~s/\$photocount/$numphotos/ieg;
	  if($numphotos == 1) {
	    &excludetag('ifplural',\$out);
	    &includetag('ifsingular',\$out);
	  } else {
	    &includetag('ifplural',\$out);
	    &excludetag('ifsingular',\$out);
	  }
	  if($numphotos > 0 ) {
	    &excludetag('nophotos',\$out);
	    &includetag('ifphotos',\$out);
	    
	    my $randnum=int(rand($numphotos));
	    my $lastnum=$numphotos-1;
	    
	    $out =~ s{\<img(.*?)firstpic(.*?)\>}
	      {&dispimgwithdefaults($1,$photos[0],$2)}sieg;
	    
	    $out =~ s{\<img(.*?)lastpic(.*?)\>}
	      {&dispimgwithdefaults($1,$photos[$lastnum],$2)}sieg;
	    
	    $out =~ s{\<img(.*?)rand(?:om)?pic(.*?)\>}
	      {&dispimgwithdefaults
		 ($1,$photos[$randnum],$2)}sieg;
	    
	    $out =~ s{\<whentaken\s+firstpic(.*?)\>}
	      {&photodatestr($photos[0],$1)}sieg;
	    $out =~ s{\<whentaken\s+lastpic(.*?)\>}
	      {&photodatestr($photos[$lastnum],$1)}sieg;
	    
	  } else {
	    &includetag('nophotos',\$out);
	    &excludetag('ifphotos',\$out);
	  }
	}
      } elsif($item->{'type'} eq 'link') {
        &excludetag('ifgroup',\$text);
	&includetag('iflink',\$text);

	my $linkedalbum=$item->{'album'};
	# Again, URI escape this yourself if needed
	#	$linkedalbum=&uri_escape($linkedalbum);
	my $title=$item->{'title'} || "";
	$out=$text;
        my $albumlinkroot=&getlinkroot('album');
	$out=~s/\<A(.*?)LINK NOSTYLE\>/\<a${1}href=\"$albumlinkroot?album=$linkedalbum\"\>/sig;
        $out=~s/\<A(.*?)LINK\>/\<a${1}href=\"$albumlinkroot?album=$linkedalbum&amp;style=$uristyle\"\>/sig;
        # HTML is valid in the $title because it came from the config file
        $out=~s/\$title/$title/ig;
      }
      # count only contains numbers and we control it => not escaped
      $out=~s/\$counter/$count/gi;
      $out=doifcount($out,$count,$#$items+1);
      my $upcount=$oldlevel-$newlevel>0 ? $oldlevel-$newlevel : 0;
      &includetag('ifupprevlevel',\$out,$upcount);
      my $downcount=$newlevel-$oldlevel>0 ? $newlevel-$oldlevel : 0;
      &includetag('ifdownprevlevel',\$out,$downcount);
      $count++;
      $oldlevel=$newlevel;
    }
    if(defined $out) {
      &includetag('ifnextuplevel',\$out,$oldlevel);
      &excludetag('ifnextdownlevel',\$out);
      &$printout($out);
    }
    $template=$post;
  }

  &$printout($template);

}
