/index.fcgi
#!/usr/bin/perl
use CGI::Fast qw/:standard/;
use CGI::Session;
#use CGI::Carp qw/fatalsToBrowser/;
use Vector::Config qw/$webroot/;
use Vector::Util qw/url_encode/;
use Vector::Channel;
use Vector::Post;
use Vector::Auth qw/authbox/;
use Vector::Paginator;
use Vector::File;
use Vector::Notify;
use Vector::Error;
use Vector::Template;
use strict;

our ($login_id, $login_user);
my ($type, $object, $subobject, @extra);
my ($pobject, $plink, $head);

sub page_setup {
	my ($session) = @_;

	if ($type eq 'channel') {
		$pobject = "#$object";
		$plink = "${webroot}channel/$object";
		if (defined $subobject) {
			$head = qq{<link rel="alternate" type="application/rss+xml" title="Thread $subobject in #$object [RSS]" href="${webroot}rss/$object/$subobject">};
		} else {
			$head = qq{<link rel="alternate" type="application/rss+xml" title="All posts in #$object [RSS]" href="${webroot}rss/$object">};
		}

		if ($login_id) {
			if (param('Reply')) {
				my $channel_id = Vector::Channel::id($object);
				my $replyto = param('replyto');
				my $file = Vector::File::store;
				my $post = new Vector::Post($login_id, $channel_id, param('data'), $file, $replyto);
				$post->save;

				print redirect($post->post_uri);
				next REQUEST;
			} elsif (param('Start Thread')) {
				my $channel_id = Vector::Channel::id($object);
				unless ($channel_id) {
					$channel_id = Vector::Channel::create($object);
				}
				my $file = Vector::File::store;
				my $post = new Vector::Post($login_id, $channel_id, param('data'), $file);
				$post->save;

				print redirect($post->thread_uri);
				next REQUEST;
			} elsif (url_param('watch')) {
				my $channel_id = Vector::Channel::id($object);
				if (url_param('watch') eq 'on') {
					Vector::Notify::set($login_id, $channel_id, $subobject);
				} else {
					Vector::Notify::clear($login_id, $channel_id, $subobject);
				}

				print redirect("${webroot}channel/$object" . (defined $subobject ? "/$subobject" : ''));
				next REQUEST;
			}
		}
	} elsif ($type eq 'user') {
		$plink = "${webroot}user/$object/" . join('/', @extra);
		$object = $object . '://' . @extra[0] . '/' . join('/', splice(@extra, 1));
		$pobject = "~$object";

		if ($login_user->{username} eq $object) {
			if (param('Save')) {
				$login_user->{email} = param('email');
				$login_user->save;

				print redirect($login_user->user_url);
				next REQUEST;
			}
		}
	} else {
		$pobject = 'Home';
		$plink = $webroot;
		$head = qq{<link rel="alternate" type="application/rss+xml" title="Channel List [RSS]" href="${webroot}rss">};

		if (param('Join Channel')) {
			my $channel = param('channel');
			$channel =~ s/^#//;
			print redirect($webroot . 'channel/' . url_encode($channel));
			next REQUEST;
		}
	}

	Delete('data');
}

sub page_display {
	my ($session) = @_;

	print $session->header,
	      start_html(
		-title => "Vector: $pobject",
		-style => "${webroot}static/style.css",
		-head => <<HEAD
<link rel="icon" type="image/png" href="${webroot}static/favicon.png">
<script type="text/javascript" src="${webroot}static/ui.js"></script>
$head
HEAD
	      );
	
	print h1(a({href => $plink}, $pobject));
		
	authbox($session);
	if ($login_id) {
		print div({style => 'text-align: right'}, a({href => $login_user->user_url}, 'Preferences'));
	}

	if ($type eq 'channel') {
		my $channel_id = Vector::Channel::id($object);

		if (defined $subobject) {
			my $head = load Vector::Post($subobject);

			if ($login_id) {
				print p, Vector::Notify::widget($login_id, $channel_id, $subobject);
			}

			print '<ul class="posts">';
			$head->print;
			print '</ul>';
		} else {
			my $paginator = new Vector::Paginator("$webroot$type/$object", param('page') || 0, reverse Vector::Channel::list($object));
			my $navigator = $paginator->navigator;
			my @heads = map { load Vector::Post($_) } $paginator->page_items;

			if ($login_id) {
				print p, Vector::Notify::widget($login_id, $channel_id);
			}

			if (@heads) {
				print p, $navigator;

				print '<ul class="posts">';
				foreach my $h (@heads) {
					$h->print(10);
				}
				print '</ul>';

				print p, $navigator;
			} else {
				print p, "Channel is empty.";
			}

			if ($login_id) {
				print h2('Start Thread');
				print start_form,
				      textarea('data', '', 5, 60), br,
				      filefield(-name => 'file'), br, 
				      submit('Start Thread'),
				      end_form;
			}
		}
	} elsif ($type eq 'user') {
		if ($login_id) {
			if ($object eq $login_user->{username}) {
				print start_form,
				      'Email: ', textfield('email', $login_user->{email}, 40),
				      p, submit('Save'),
				      end_form;
			}
		}
	} else {
		my %env;
		unless ($login_id) {
			$env{GETSTARTED} = "After you log in, you can create a channel by joining a nonexistent channel and then posting.";
		}
		$env{GETSTARTED} .= p . start_form .
		      textfield('channel', '', 20) .
		      submit('Join Channel') .
		      end_form;
		Vector::Template::process('home', \%env);
	}

	print end_html;
}

REQUEST:
while (my $q = new CGI::Fast) {
	my $session = new CGI::Session($q);

	$login_id = $session->param('id');
	if ($login_id) {
		$login_user = Vector::User->fetch_by_id($login_id);
	} else {
		$login_user = undef;
	}

	(undef, $type, $object, @extra) = split(m'/', $ENV{PATH_INFO});
	$subobject = $extra[0];

	eval { page_setup($session) };
	if ($@) {
		Vector::Error::error_page;
		next REQUEST;
	}

	eval { page_display($session) };
	if ($@) {
		print "Kaboom: $@";
	}
}