#!/usr/bin/perl

# comic book viewer 
# Copyright 2002-2003 Steve Pomeroy <steve@staticfree.info>
# Released under the GNU GPL

use XML::Simple;
use CGI qw/:standard -nosticky/;
use Data::Dumper;

# <comic name="">
#   <nav id="next" src="">
#   <section name="sec name">
#     <page src="" title="" date="">

# <?xml version="1.0"?>

#  <comic name="Thalion Dynasty">
#    <base name="comic" path="/Book1/"/>
#    <base name="nav" path="/images/"/>
#    <nav id="prev" src="back.png"/>
#    <section title="sec one - the fall from grace" path="book1/">
#       <page small="" src="1-1.JPG" title="The Beginning" date="February 2002"/>
#       <page small="" src="1-2.JPG" title="The Beginning" date="March 10, 2002"/>
#    </section>

#  </comic>


print "content-type:text/html\n\n";

my $struct = "../struct.xml";
my $template = "../template.html";
my $cgiurl = "cgi-bin/comicview.pl";

# options for displaying the url
my %urlopts = ( -absolute=>1, -query=>1 );

my $str = XMLin( $struct, forcearray=>1 ) or die "Error: cannot open $struct: $1";

open TMPL, $template or die "Error opening template $template: $!";
# slurrrp....
my $tmpl = join "", <TMPL>;

close TMPL;

#print Dumper $str;
#exit; 

my $sec  = 0;
my $page = 0;

$sec  = param( 'section' ) if defined param('section');
$page = param( 'page' )    if defined param('page');

err( "invalid section" ) if ($sec < 0 || $sec >= scalar (@{$str->{'section'}}) );
my $cursec = $str->{'section'}[$sec];

err( "invalid page" ) if ($page < 0 || $page >= scalar (@{$cursec->{'page'}}) );
my $curpage = $cursec->{'page'}[$page];


param( 'page', $page  )    unless defined param('page');
param( 'section', $sec )   unless defined param('section');

my $url = url( %urlopts );

my $lastsec = $str->{'section'}[$#{$str->{'section'}}];
my $lastpage = $lastsec->{'page'}[$#{$lastsec->{'page'}}];

# the base url
my $base = "";
$base = $str->{'base'}->{'comic'}->{'path'} if 
    defined $str->{'base'}->{'comic'}->{'path'};
$base =~ s/\/$//;

# base directory for all the navigation graphics
my $navbase = "";
$navbase = $str->{'base'}->{'nav'}->{'path'} if 
    defined $str->{'base'}->{'nav'}->{'path'};
$navbase =~ s/\/$//;

my $secbase = "";
$secbase = $str->{'section'}[$sec]->{'path'} if defined $str->{'section'}[$sec]->{'path'};
$secbase =~ s/^(.+?)\/?$/$1\//;


# all loaded

if( defined param( 'show' )){
    my $show = param( 'show' );
    Delete('show');
    print $lastpage->{'date'} if( $show eq "lastdate");
    my $img = $lastpage->{'src'};
    $img = $lastpage->{'small'} if exists $lastpage->{'small'};
    my $url= url_abs($#{$str->{'section'}}, $#{$lastsec->{'page'}}, $str);
    $url =~ s#^/(.*)\?#/$cgiurl?#i;
    print $url if ( $show eq "lasturl");

    print "$base/$secbase$img" if( $show eq "lastimg");

    exit;
}

my %links;

# set the types of nav bars we know
for ( qw( next prev first last nextsec prevsec ) ){
    $links{$_} = {};
}

# then set what they mean
$links{'next'}{'rel'}  = [$sec, $page, 1];
$links{'prev'}{'rel'}  = [$sec, $page, -1];
$links{'prev'}{'title'} = "previous";

$links{'first'}{'rel'} = [0, 0, 0];
$links{'last'}{'rel'}  = [$#{$str->{'section'}}, $#{$lastsec->{'page'}}, 0];

# set some defaults...
foreach my $nav (keys %links){
    $links{$nav}{'img'}   = "";
    $links{$nav}{'linkrel'}    = "$nav" unless exists $links{$nav}{'linknav'}; 
    $links{$nav}{'title'}      = "$nav" unless exists $links{$nav}{'title'};
    $links{$nav}{'titleimg'}   = "$nav.png";
    
    
    # allow the user to override stuff
    foreach my $attr (keys %{$str->{'nav'}->{$nav}}){
	$links{$nav}{$attr} = $str->{'nav'}->{$nav}->{$attr};
    }

    $links{$nav}{'page'}  = page_rel( @{$links{$nav}{'rel'}}, $str ) if
	exists $links{$nav}{'rel'};
    $links{$nav}{'url'}   = url_rel( @{$links{$nav}{'rel'}}, $str ) if
	exists $links{$nav}{'rel'};

    if( $links{$nav}{'url'} ne "" ){
	$links{$nav}{'link'}  = "<a href=\"$links{$nav}{'url'}\">$links{$nav}{'title'}<\/a>";
	$links{$nav}{'img'} = imglink(link=>$links{$nav}{'url'}, alt=>$nav, src=>"$navbase/$links{$nav}{'titleimg'}");
    }

}

#$links{'next'}{'url'} = url_rel( $sec, $page, 1, $str );
#$links{'prev'}{'url'} = url_rel( $sec, $page, -1, $str );


#$links{'prev'}{'page'} = page_rel( $sec, $page, -1, $str );

$links{'nextsec'}{'url'} = url_rel_sec( $sec, $page, 1, $str );
$links{'prevsec'}{'url'} = url_rel_sec( $sec, $page, -1, $str );

my $linkrel="";
foreach my $nav (keys %links){
    if ( $links{$nav}{'linkrel'} ne "" && $links{$nav}{'url'} ne "" ){
	my $title="";
	$title = " title=\"$links{$nav}{'title'}" if exists $links{$nav}{'title'};
	$linkrel .= "<link rel=\"$links{$nav}{'linkrel'}\" href=\"$links{$nav}{'url'}\"$title\">\n";
    }
}

my $comicname = $str->{'name'};


# replace %URL% like values from the template with actual data
$tmpl =~ s/\%PAGE(?:\:(.+?))?\%/pagehtml($curpage, "$base\/$secbase", $1)/ige;
$tmpl =~ s/\%PAGE-SMALL\%/$base\/$secbase$curpage->{'small'}/ig;

$tmpl =~ s/\%URL\%/$url/g;
$tmpl =~ s/\%URL-NEXT\%/$links{'next'}{'url'}/ig;
$tmpl =~ s/\%URL-PREV\%/$links{'prev'}{'url'}/ig;


foreach my $nav (keys %links){
    $tmpl =~ s/\%LINK-$nav\%/$links{$nav}{'link'}/ig;
    $tmpl =~ s/\%NAV-$nav\%/$links{$nav}{'img'}/ig;
    $tmpl =~ s/\%URL-$nav\%/$links{$nav}{'url'}/ig;
    $tmpl =~ s/\%LINKREL\%/$linkrel/ig;
}

$tmpl =~ s/\%LIST-PAGES(?:\:(\w+))?\%/page_list($sec,$1,$str)/gei;
$tmpl =~ s/\%LIST-PAGES-IMG(?:\:(\w+))?\%/page_list_img($sec,$1,$str,"$base\/$secbase")/gei;
$tmpl =~ s/\%LIST-SECTIONS\:(\w+)\%/section_list($1,$str)/gei;
$tmpl =~ s/\%LIST-SECTIONS-IMG(?:\:(\w+))?\%/section_list_img($1,$str,"$base\/$secbase")/gei;

$tmpl =~ s/\%TITLE\%/$curpage->{'title'}/gi;
$tmpl =~ s/\%TITLE-IMG(?:\:(.+?))?\%/imglink(atts=>$1,alt=>$curpage->{'title'}, src=>"$base\/$secbase$curpage->{'titleimg'}")/gei;
$tmpl =~ s/\%SECTION-TITLE\%/$cursec->{'title'}/gi;
$tmpl =~ s/\%SECTION-TITLE-IMG(?:\:(.+?))?\%/imglink(atts=>$1,alt=>$cursec->{'title'}, src=>"$base\/$secbase$cursec->{'titleimg'}")/gei;
$tmpl =~ s/\%DATE\%/$curpage->{'date'}/gi;

$tmpl =~ s/\%COMIC-NAME\%/$str->{'name'}/gi;



print $tmpl;

sub err{
    my ($err) = @_;
    print "$err\n";
    exit;
}


sub pagehtml{
    my ($page, $base, $atts ) = @_;

    # setup the page
    my $pagehtml = "";
    if( exists $page->{'small'} ){
	$pagehtml = imglink( link=>"$base$page->{'src'}", 
			     alt=>$page->{'title'},
			     src=>"$base$page->{'small'}",
			     atts=>$atts);
    }else{
	$pagehtml = imglink( alt=>$page->{'title'}, 
			     src=>"$base$page->{src}");
    }

    return $pagehtml;
}

sub move_sec{

  my ( $sec, $page, $offset, $str ) = @_;

  $page = 0;

  if( ($sec + $offset >= 0 ) && 
      ($sec + $offset ) < scalar( @{$str->{'section'}} )){

      return (($sec + $offset), $page);

  }else{ 

      return -1;

  }
}

sub move_page{

  my ( $sec, $page, $offset, $str ) = @_;

  $page += $offset;
  
  if( $page < 0 || $page >= scalar(@{$str->{'section'}[$sec]->{'page'}}) ){
      $sec += $offset;
      if( ($sec >= 0 ) && 
	  $sec < scalar( @{$str->{'section'}} )){
	  if( $offset < 0 ){
	      $page = scalar( @{$str->{'section'}[$sec]->{'page'}}) + $offset;
	  }else{
	      $page = $offset - 1;
	  }
      }else{
	  return -1;
      }      
  }

  return ($sec, $page);
}

sub url_rel{
    my ($sec, $page, $offset, $str ) = @_;
#    print "<!--".Dumper(\@_)."-->";
    my $url = "";
    my( $nsec, $npage ) = move_page( $sec, $page, $offset, $str );
    if( $nsec != -1 ){
	param( 'page', $npage  );
	param( 'section', $nsec );
	$url = url( %urlopts );
	param( 'page', $page  );
	param( 'section', $sec );
    }
    return $url;
}

sub url_abs{
    my ($sec, $page, $str ) = @_;
    my $url = "";
	param( 'page', $page  );
	param( 'section', $sec );
	$url = url( %urlopts );
	param( 'page', $page  );
	param( 'section', $sec );

    return $url;
}

sub url_rel_sec{
    my ($sec, $page, $offset, $str ) = @_;
    my $url = "";
    my( $nsec, $npage ) = move_sec( $sec, $page, $offset, $str );
    if( $nsec != -1 ){
	param( 'page', $npage  );
	param( 'section', $nsec );
	$url = url( %urlopts );
	param( 'page', $page  );
	param( 'section', $sec );
    }
    return $url;
}

sub page_rel{
    my ($sec, $page, $offset, $str ) = @_;

    my $title;
    my( $nsec, $npage ) = move_page( $sec, $page, $offset, $str );
    if( $nsec != -1 ){
	$page = $str->{'section'}[$nsec]->{'page'}[$npage];
    }else{
	undef $page;
    }
    return $page;
}

sub page_list{

    my( $sec, $tag, $str ) = @_;

    my $ret = "";
    for (my $page = 0; $page < scalar (@{$str->{'section'}[$sec]->{'page'}}); $page++){
	my $pg  = @{$str->{'section'}[$sec]->{'page'}}[$page];
	my $url = url_abs( $sec, $page, $str );

	$ret .= "<$tag><a href=\"$url\">".$pg->{'title'}."</a></$tag>\n";
    }
    return $ret;

}

sub page_list_img{

    my( $sec, $tag, $str, $base ) = @_;

    my $ret = "";
    for (my $page = 0; $page < scalar (@{$str->{'section'}[$sec]->{'page'}}); $page++){
	my $pg  = @{$str->{'section'}[$sec]->{'page'}}[$page];
	my $url = url_abs( $sec, $page, $str );
	my $img = exists $pg->{'titleimg'} ? $base.$pg->{'titleimg'} : "";
	# allow small icons for the list to be used
	$img = $base.$pg->{'titlesmall'} if exists $pg->{'titlesmall'};

	$ret .= "<$tag>" if defined $tag;
	$ret .= imglink( link=>$url, alt=>$pg->{'title'}, 
			 src=> $img);
	$ret .= "</$tag>" if defined $tag;
	$ret .= "\n";
    }
    return $ret;

}

sub section_list{

    my( $tag, $str ) = @_;

    my $ret = "";
    for (my $secn = 0; $secn < scalar (@{$str->{'section'}}); $secn++){
	my $sec  = @{$str->{'section'}}[$secn];
	my $url = url_abs( $secn, 0, $str );

	$ret .= "<$tag><a href=\"$url\">".$sec->{'title'}."</a></$tag>\n";
    }
    return $ret;

}

sub section_list_img{

    my( $tag, $str, $base ) = @_;

    my $ret = "";
    for (my $secn = 0; $secn < scalar (@{$str->{'section'}}); $secn++){

	my $sec  = @{$str->{'section'}}[$secn];
	my $url = url_abs( $secn, 0, $str );
	my $img = exists $sec->{'titleimg'} ? $base.$sec->{'titleimg'} : "";
	$img = $base.$sec->{'titlesmall'} if exists $sec->{'titlesmall'};

	$ret .= "<$tag>" if defined $tag;
	$ret .= imglink( link=>$url, alt=>$sec->{'title'}, 
			 src=> $img);
	$ret .= "</$tag>" if defined $tag;
	$ret .= "\n";
    }
    return $ret;

}


sub imglink{

  my (%opts) = @_;
  my $code = "";

  my $params="";
  $params .= " src=\"$opts{'src'}\"" if exists $opts{'src'};
  $params .= " alt=\"$opts{'alt'}\"" if exists $opts{'alt'};
  $params .= " $opts{'atts'}"        if exists $opts{'atts'} && 
                                        defined $opts{'atts'};

  $code = "<img border=0$params>";
  $code = "<a href=\"$opts{'link'}\">$code</a>" if exists $opts{'link'};

  return $code;

}

sub setdefaults{
    my ($links, $link, %defs) = @_;

    $links->{$link}{'title'} = "";
    $links->{$link}{'img'} = "";
    $links->{$link}{'src'} = "";
    
    $links->{$link} = %defs;
}


