#!/usr/bin/perl

use strict;
use Data::Dumper;
use File::Slurp;
use Image::Magick;

################################################################################
#
################################################################################

# notes:
# expects a directory structure of the following:
# /home/your_name/gallery
#   /photos
#       /2005-10-20
#       /2005-10-21
#       /2005-11-15
#   /art
#       /2004-05-30
#       /2004-07-19
#   ...

my $root      = "/home/your_name/gallery";      # top gallery directory
my $dump_file = "$root/scripts/dump.txt";       # Data::Dumper file
my $md5sum    = "/usr/bin/md5sum";              # md5sum program
my $catalog;

my $color0 = "FFFFFF";
my $color1 = "AAAAAA";

my $max_thumb_x      = 150;     # max allowable thumb width
my $max_thumb_y      = 150;     # max allowable thumb height
my $max_thumb_col    = 5;       # max thumbs per column
my $max_thumb_sample = 10;      # max number of sample thumbs on index pages
                                # (shows all thumbs on detail pages)

################################################################################
#
################################################################################

# preload a data file containing information about known images and thumbs;
# this stops us from reprocessing things;  the eval() reads a Data::Dumper
# formatted output
if (-e $dump_file)
{
    my $dump_data = read_file($dump_file);
    $dump_data =~ s/VAR1/catalog/;
    eval($dump_data);
}
else
{
    $catalog = {};
}

# operate per top directory
my @top_dirs = map { chomp($_); $_; } `ls -1 $root`;

foreach my $top_dir (@top_dirs)
{
    next unless (-d "$root/$top_dir");
    next if $top_dir eq "scripts";

    print "* working on $top_dir\n";

    my @gallery_dirs = map { chomp($_); $_; } `ls -1 $root/$top_dir`;

    # operate per gallery directory
    foreach my $gallery_dir (@gallery_dirs)
    {
        next unless (-d "$root/$top_dir/$gallery_dir");

        print "    * working on $top_dir - $gallery_dir\n";

        my @gallery_files =
          map { chomp($_); $_; } `ls -1 $root/$top_dir/$gallery_dir`;

        # operate per gallery file
        foreach my $gallery_file (@gallery_files)
        {
            next unless (-f "$root/$top_dir/$gallery_dir/$gallery_file");
            next if $gallery_file =~ m/\.html/;

            # rename if filename is mixed case
            if ($gallery_file ne lc($gallery_file))
            {
                print "            * lc($gallery_file)\n";
                my $new_file = lc($gallery_file);
                `mv $root/$top_dir/$gallery_dir/$gallery_file $root/$top_dir/$gallery_dir/$new_file`;
                $gallery_file = $new_file;
            }

            # see if we can skip the file
            my $sum = `$md5sum $root/$top_dir/$gallery_dir/$gallery_file`;
            chomp($sum);
            $sum =~ s/\s+.+$//;

            my $catalog_sum =
              $catalog->{$top_dir}->{$gallery_dir}->{$gallery_file}->{md5sum};

            #print "        * $catalog_sum ?= $sum\n";
            next if $catalog_sum eq $sum;

            print "        * working on $gallery_file\n";

            # analyze the file and catalog its data
            my $pm = new Image::Magick;
            $pm->Read("$root/$top_dir/$gallery_dir/$gallery_file");

            my $file_data = {
                             path           => "$root/$top_dir/$gallery_dir",
                             name           => $gallery_file,
                             height         => $pm->Get('height'),
                             width          => $pm->Get('width'),
                             'x-resolution' => $pm->Get('x-resolution'),
                             'y-resolution' => $pm->Get('y-resolution'),
                             'md5sum'       => $sum,
                            };

            $catalog->{$top_dir}->{$gallery_dir}->{$gallery_file} = $file_data;

            # now, operate on the data
            # need to create a thumbnail
            my $thumbnail = "$root/$top_dir/$gallery_dir/thumb/$gallery_file";
            unless (-e $thumbnail)
            {
                unless (-d "$root/$top_dir/$gallery_dir/thumb/")
                {
                    print "            * making thumb dir\n";
                    `mkdir $root/$top_dir/$gallery_dir/thumb`;
                }

                my $scaling_factor = 0;
                if ($file_data->{width} > $file_data->{height})
                {
                    $scaling_factor = $max_thumb_y / $file_data->{width};
                }
                else
                {
                    $scaling_factor = $max_thumb_x / $file_data->{height};
                }
                my $scaled_x = int($file_data->{width} * $scaling_factor);
                my $scaled_y = int($file_data->{height} * $scaling_factor);

                $pm->Scale(width => $scaled_x, height => $scaled_y);
                $pm->Write($thumbnail);
            }
        }
    }
}

print "\n* saving catalog\n";
write_file($dump_file, Dumper($catalog));

print "\n\n";

#print Dumper $catalog;
print "* creating general index\n";
my @galleries = sort keys %{$catalog};

my $html = "";

foreach my $gallery (@galleries)
{
    print "* creating samples for $gallery\n";
    my $gallery_title   = "$gallery gallery";
    my @gallery_samples = undef;

    my $sample_count = 0;
    my $i            = 0;
    my $j            = 0;

    my $set_count = scalar keys %{$catalog->{$gallery}};

    foreach my $set (sort keys %{$catalog->{$gallery}})
    {
        last if ($sample_count == $max_thumb_sample);
        print "    * working on set $set\n";

        if ($j == $max_thumb_col)
        {
            $i++;
            $j = 0;
        }

        my @files = (
                     map { $catalog->{$gallery}->{$set}->{$_}; }
                       sort keys %{$catalog->{$gallery}->{$set}}
                    );

        $gallery_samples[$i][$j] = $files[0];
        $j++;
        $sample_count++;
    }

    $html .= <<END_HTML;
  <B>$gallery_title</B> <FONT SIZE="-1" COLOR="#666666">($set_count sets)</FONT><BR><BR>

  <TABLE CELLPADDING="5" CELLSPACING="0" BORDER="0">
END_HTML

    foreach my $row (@gallery_samples)
    {

        $html .= <<END_HTML;
  <TR>
END_HTML

        #print Dumper $row;
        foreach my $col (@{$row})
        {
            $html .= <<END_HTML;
    <TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"><A HREF="$root/$gallery/index.html"><IMG SRC="$col->{path}/thumb/$col->{name}" ALT="$col->{path}" BORDER="0"></A></TD>
END_HTML
        }

        $html .= <<END_HTML;
  </TR>
END_HTML

    }

    $html .= <<END_HTML;
  </TABLE>

  <BR>

END_HTML
}

write_file("$root/index.html", body_html("General Gallery Index", $html));

foreach my $gallery (@galleries)
{
    print "* creating index for $gallery\n";
    $html = "";

    my $gallery_title = "$gallery gallery";

    my $i = 0;
    my $j = 0;

    $html .= <<END_HTML;
  <B>$gallery_title</B><BR><BR>

  <TABLE CELLPADDING="5" CELLSPACING="0" BORDER="0">
END_HTML

    my $highlight = 1;
    my $group     = "";

    my @colors = ($color0, $color1);

    foreach my $set (sort keys %{$catalog->{$gallery}})
    {
        print "    * working on set $set\n";

        $set =~ m/^(\d+)-/;
        my $block = "$1";

        if ($block ne $group)
        {
            $group = $block;
            $highlight = ($highlight == 1 ? 0 : 1);
        }

        my @files = (
                     map { $catalog->{$gallery}->{$set}->{$_}; }
                       sort keys %{$catalog->{$gallery}->{$set}}
                    );
        my $pic_count = scalar(@files);

        $html .= <<END_HTML;
  <TR BGCOLOR="#$colors[$highlight]">
    <TD COLSPAN="$max_thumb_col"><I>$set set</I> <FONT SIZE="-1" COLOR="#000000">($pic_count pics)</FONT></TD>
  </TR>
  <TR BGCOLOR="#$colors[$highlight]">
END_HTML

        for (my $j = 0 ; $j < $max_thumb_col ; $j++)
        {
            if (!defined $files[$j])
            {
                $html .= <<END_HTML;
    <TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"></TD>
END_HTML
            }
            else
            {
                my $col = $files[$j];

                $html .= <<END_HTML;
    <TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"><A HREF="$col->{path}/index.html"><IMG SRC="$col->{path}/thumb/$col->{name}" ALT="$col->{path}" BORDER="0"></A></TD>
END_HTML
            }
        }

        $html .= <<END_HTML;
  </TR>
END_HTML
    }

    $html .= <<END_HTML;
  </TABLE>

  <BR>

END_HTML

    write_file("$root/$gallery/index.html", body_html($gallery_title, $html));
}

foreach my $gallery (@galleries)
{
    print "* working on gallery $gallery\n";

    my $i = 0;
    my $j = 0;

    foreach my $set (sort keys %{$catalog->{$gallery}})
    {
        print "    * working on set $set\n";

        my @files = (
                     map { $catalog->{$gallery}->{$set}->{$_}; }
                       sort keys %{$catalog->{$gallery}->{$set}}
                    );

        #print Dumper $catalog->{$gallery}->{$set};
        my $num_thumbs  = scalar(@files);
        my $thumb_count = 0;

        $html = <<END_HTML;
  <B>$set set</B><BR><BR>

  <TABLE CELLPADDING="5" CELLSPACING="0" BORDER="0">
END_HTML

        while ($thumb_count < $num_thumbs)
        {
            $html .= <<END_HTML;
      <TR>
END_HTML

            for (my $j = 0 ; $j < $max_thumb_col ; $j++)
            {
                if (!defined $files[$thumb_count])
                {
                    $html .= <<END_HTML;
        <TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"></TD>
END_HTML
                }
                else
                {
                    my $col = $files[$thumb_count];

                    $html .= <<END_HTML;
        <TD VALIGN="CENTER" ALIGN="CENTER" HEIGHT="$max_thumb_y" WIDTH="$max_thumb_x"><A HREF="$col->{path}/$col->{name}"><IMG SRC="$col->{path}/thumb/$col->{name}" ALT="$col->{path}" BORDER="0"></A></TD>
END_HTML
                }

                $thumb_count++;
            }

            $html .= <<END_HTML;
      </TR>
END_HTML
        }

        $html .= <<END_HTML;
  </TABLE>

  <BR>

END_HTML

        write_file("$root/$gallery/$set/index.html",
                   body_html("$set set", $html));
    }
}

################################################################################
#
################################################################################

sub body_html
{
    my $title = shift;
    my $body  = shift;

    my $HTML = <<END_HTML;
<HTML>
<HEAD>
  <TITLE>$title</TITLE>
</HEAD>
<BODY>
$body
</BODY>
</HTML>
END_HTML
}
