package GimpSite::Handler;

use strict;
$^W = 1;

require DBI;
require CompoSite;
require GimpSite;
require GimpSite::Util;

use vars qw(%Config %Handlers $db_l);

# Read Configuration ---------------------------------------------------------

%Config = %GimpSite::Config;

# Handlers for different sections --------------------------------------------

%Handlers = (
  # The settings handler alters %$args based on lines of the form:
  #   arg .= foo --> $args->{'arg'} .= 'foo';
  #   arg := bar --> $args->{'arg'} = 'bar';
    settings => sub {
        my ($page, $fh, $args) = @_;
        my $next = &GimpSite::Util::Settings ($fh, $args);
        return $next;
    },

  # The static handler sends out the current block of the file.
    static => sub {
        my ($page, $fh, $args) = @_;
        $page->header ($args);
        my ($text, $next) = &CompoSite::Util::next_part ($fh);
        $page->print ($text);
        return $next;
    },

  # The dump handler sends the rest of the file, verbatim, without looking for
  # an end-of-section.
    dump => sub {
        my ($page, $fh, $args) = @_;
        $page->header ($args);
        while (<$fh>) {
            $page->print ($_);
        }
        return undef;
    },

  # The contemplate handler replaces contemplate {|blocks|}.
    contemplate => sub {
        my ($page, $fh, $args) = @_;
        $page->header ($args);
        my ($text, $next) = &CompoSite::Util::next_part ($fh);
        $page->print ($page->render_block($text, $args));
        return $next;
    },

  # This is a Yahoo-style link database - but the database and
  # templates and editor are yet to be created. TODO
    links => sub {
        my ($page, $fh, $args) = @_;

        $db_l = DBI->connect(@{$Config{'db'}{'links'}})
            or die "trying connect to db [$DBI::errstr]";

        my ($topic, @pathnames) = &links_traverse ($db_l, $args->{'links_root'}, $args->{'path_info'});

        $args->{'SubTitle'} = join (': ', map ( { s/_/ /g; $_ } @pathnames));
        # shift @pathnames; # drop first one
        $args->{'tdesc'} = $topic->{'description'};

        $page->header($args);
        my ($blurb, $next) = &CompoSite::Util::next_part ($fh);
        $page->print($page->render_block($blurb, $args));

        $topic->{'ptitle'} = $topic->{'title'};
        $topic->{'ptitle'} =~ s/_/ /g;
        $topic->{'dpath'} =~ s/^Top\/// if defined $topic->{'dpath'};

        # find subtopics
        my $query = (<<"");
            SELECT topic_id, lastupdate, title, total_links, description
              FROM Topics
             WHERE parent_id = $topic->{'topic_id'}
             ORDER BY sort_order;

        my $stmt = $db_l->prepare ($query)
            or die "trying to prepare statement [$DBI::errstr]";
        my $rows = $stmt->execute
            or die "trying to execute statement [$DBI::errstr]";

        $args->{'tlist'} = '';

        if ($rows > 0) {
            $page->block ($args->{'links_dir_head'}, $topic);

            while (my $subtopic = $stmt->fetchrow_hashref) {
                $subtopic->{'ptitle'} = $subtopic->{'title'};
                $subtopic->{'ptitle'} =~ s/_/ /g;
                $page->block ($args->{'links_dir_topic'}, $subtopic);
            }

            $page->block ($args->{'links_dir_foot'}, $topic);
        }

        $stmt->finish;

        $stmt = $db_l->prepare ("SELECT tl.tl_id, l.link_id, l.url, l.title, l.description
                                   FROM Links l, Topic_Link tl
                                  WHERE tl.topic_id = $topic->{'topic_id'}
                                    AND tl.link_id = l.link_id
                                  ORDER BY tl.sort_order;")
            or die "trying to prepare statement [$DBI::errstr]";
        $rows = $stmt->execute
            or die "trying to execute statement [$DBI::errstr]";

        if ($rows > 0) {
            $page->block ($args->{'links_topic_head'}, $topic);
            if ($topic->{'columns'} < 2) {
                $page->block ($args->{'links_topic_1col_head'}, $topic);
                while (my $link = $stmt->fetchrow_hashref) {
                    $page->block ($args->{'links_topic_link'}, $link);
                }
                $page->block ($args->{'links_topic_1col_foot'}, $topic);
            } else {
                $page->block ($args->{'links_topic_mcol_head'}, $topic);
                my $div = int ($rows / $topic->{'columns'});
                my $row = 0;
                while (my $link = $stmt->fetchrow_hashref) {
                    $page->block ($args->{'links_topic_link'}, $link);
                    $row++;
                    $page->block ($args->{'links_topic_mcol_break'}, {}) if (($row % $div) == 0);
                }
                $page->block ($args->{'links_topic_mcol_foot'}, $topic);
            }
            $stmt->finish;
            $page->block ($args->{'links_topic_foot'}, $topic);
        }

        return $next;
    },
);

# Auxilliary things for handlers ---------------------------------------------

sub links_traverse ($$$) {
    my ($db, $root, $path) = @_;

    $path =~ s/^\/*//g;
    $path =~ s/\/*$//g;
    $path =~ s/\/+/\//g;
    my @pathparts = split /\//, $path;

    my $query = (<<"");
        SELECT topic_id, lastupdate, title, description, columns
          FROM Topics
         WHERE topic_id = $root

    my $stmt = $db->prepare ($query)
        or die "trying to prepare statement [$DBI::errstr]";
    my $rows = $stmt->execute
        or die "trying to execute statement [$DBI::errstr]";

    my $topic = $stmt->fetchrow_hashref;
    my @pathnames = ($topic->{'title'});

    $stmt->finish;

    while (my $path = shift @pathparts and $path ne '') {
        my $q_path = $db->quote ($path);

        my $query = (<<"");
            SELECT topic_id, lastupdate, title, columns, description
              FROM Topics
             WHERE parent_id = $topic->{'topic_id'}
               AND title = $q_path

        my $stmt = $db->prepare ($query)
            or die "trying to prepare statement [$DBI::errstr]";
        my $rows = $stmt->execute
            or die "trying to execute statement [$DBI::errstr]";

        $topic = $stmt->fetchrow_hashref
            or die 'because there\'s no such topic'; # TODO - die more gracefully
        $stmt->finish;

        push @pathnames, $topic->{'title'};
    }

    return ($topic, @pathnames);
}

# Handler called by mod_perl -------------------------------------------------

sub handler {
    my $req = shift || die "Couldn't get Apache request: $!";
    CompoSite::Compose ($req, \%Handlers, $Config{'default'},
                        $Config{'tdir'}, $Config{'tcache'});
}

# EOF
